diff options
author | Tess Chu <tess@lindenlab.com> | 2007-10-02 22:38:38 +0000 |
---|---|---|
committer | Tess Chu <tess@lindenlab.com> | 2007-10-02 22:38:38 +0000 |
commit | cfd17f3322ec9c8efb120faa23adb83846272193 (patch) | |
tree | eefbf2fefcac737d4050fba10e072fe951cd4381 | |
parent | 97631054272eeb83155f70fec6a869efc39079e5 (diff) |
svn merge -r 70819:70853 svn+ssh://svn/svn/linden/branches/urldispatcher-for-merge
-rw-r--r-- | indra/llui/lltexteditor.cpp | 3 | ||||
-rw-r--r-- | indra/llui/lltexteditor.h | 10 | ||||
-rw-r--r-- | indra/newview/llcommandhandler.cpp | 80 | ||||
-rw-r--r-- | indra/newview/llcommandhandler.h | 62 | ||||
-rw-r--r-- | indra/newview/llfloatermap.cpp | 44 | ||||
-rw-r--r-- | indra/newview/llfloatermap.h | 2 | ||||
-rw-r--r-- | indra/newview/llpanellogin.cpp | 1 | ||||
-rw-r--r-- | indra/newview/llstartup.cpp | 69 | ||||
-rw-r--r-- | indra/newview/llstartup.h | 8 | ||||
-rw-r--r-- | indra/newview/llurldispatcher.cpp | 303 | ||||
-rw-r--r-- | indra/newview/llurldispatcher.h | 32 | ||||
-rw-r--r-- | indra/newview/llviewermenu.cpp | 8 | ||||
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 17 |
13 files changed, 548 insertions, 91 deletions
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 1ec62f6927..daf3438d3c 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -58,7 +58,8 @@ const S32 SPACES_PER_TAB = 4; LLColor4 LLTextEditor::mLinkColor = LLColor4::blue; void (* LLTextEditor::mURLcallback)(const char*) = NULL; -BOOL (* LLTextEditor::mSecondlifeURLcallback)(LLString) = NULL; +bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL; +bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL; /////////////////////////////////////////////////////////////////// //virtuals diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index e19e799033..ea2e6b3efe 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -194,9 +194,10 @@ public: // Callbacks static void setLinkColor(LLColor4 color) { mLinkColor = color; } - static void setURLCallbacks( void (*callback1) (const char* url), - BOOL (*callback2) (LLString url) ) - { mURLcallback = callback1; mSecondlifeURLcallback = callback2;} + static void setURLCallbacks(void (*callback1) (const char* url), + bool (*callback2) (const std::string& url), + bool (*callback3) (const std::string& url) ) + { mURLcallback = callback1; mSecondlifeURLcallback = callback2; mSecondlifeURLcallbackRightClick = callback3;} void setOnScrollEndCallback(void (*callback)(void*), void* userdata); @@ -318,7 +319,8 @@ public: LLKeywords mKeywords; static LLColor4 mLinkColor; static void (*mURLcallback) (const char* url); - static BOOL (*mSecondlifeURLcallback) (LLString url); + static bool (*mSecondlifeURLcallback) (const std::string& url); + static bool (*mSecondlifeURLcallbackRightClick) (const std::string& url); protected: LLWString mWText; mutable LLString mUTF8Text; diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp new file mode 100644 index 0000000000..47192c99f8 --- /dev/null +++ b/indra/newview/llcommandhandler.cpp @@ -0,0 +1,80 @@ +/** + * @file llcommandhandler.cpp + * @brief Central registry for text-driven "commands", most of + * which manipulate user interface. For example, the command + * "agent (uuid) about" will open the UI for an avatar's profile. + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llcommandhandler.h" + +// system includes +#include <boost/tokenizer.hpp> + +//--------------------------------------------------------------------------- +// Underlying registry for command handlers, not directly accessible. +//--------------------------------------------------------------------------- + +class LLCommandHandlerRegistry +{ +public: + static LLCommandHandlerRegistry& instance(); + void add(const char* cmd, LLCommandHandler* handler); + bool dispatch(const std::string& cmd, const std::vector<std::string>& params); + +private: + std::map<std::string, LLCommandHandler*> mMap; +}; + +// static +LLCommandHandlerRegistry& LLCommandHandlerRegistry::instance() +{ + // Force this to be initialized on first call, because we're going + // to be adding items to the std::map before main() and we can't + // rely on a global being initialized in the right order. + static LLCommandHandlerRegistry instance; + return instance; +} + +void LLCommandHandlerRegistry::add(const char* cmd, LLCommandHandler* handler) +{ + mMap[cmd] = handler; +} + +bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, + const std::vector<std::string>& params) +{ + std::map<std::string, LLCommandHandler*>::iterator it = mMap.find(cmd); + if (it == mMap.end()) return false; + LLCommandHandler* handler = it->second; + if (!handler) return false; + return handler->handle(params); +} + +//--------------------------------------------------------------------------- +// Automatic registration of commands, runs before main() +//--------------------------------------------------------------------------- + +LLCommandHandler::LLCommandHandler(const char* cmd) +{ + LLCommandHandlerRegistry::instance().add(cmd, this); +} + +LLCommandHandler::~LLCommandHandler() +{ + // Don't care about unregistering these, all the handlers + // should be static objects. +} + +//--------------------------------------------------------------------------- +// Public interface +//--------------------------------------------------------------------------- + +// static +bool LLCommandDispatcher::dispatch(const std::string& cmd, const std::vector<std::string>& params) +{ + return LLCommandHandlerRegistry::instance().dispatch(cmd, params); +} diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h new file mode 100644 index 0000000000..65ce6c633b --- /dev/null +++ b/indra/newview/llcommandhandler.h @@ -0,0 +1,62 @@ +/** + * @file llcommandhandler.h + * @brief Central registry for text-driven "commands", most of + * which manipulate user interface. For example, the command + * "agent (uuid) about" will open the UI for an avatar's profile. + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ +#ifndef LLCOMMANDHANDLER_H +#define LLCOMMANDHANDLER_H + +/* To implement a command "foo" that takes one parameter, + a UUID, do this: + +class LLFooHandler : public LLCommandHandler +{ +public: + // Inform the system you handle commands starting + // with "foo" + LLFooHandler() : LLCommandHandler("foo") { } + + // Your code here + bool handle(const std::vector<std::string>& tokens) + { + if (tokens.size() < 1) return false; + LLUUID id( tokens[0] ); + return doFoo(id); + } +}; + +// Creating the object registers with the dispatcher. +LLFooHandler gFooHandler; +*/ + +class LLCommandHandler +{ +public: + LLCommandHandler(const char* command); + // Automatically registers object to get called when + // command is executed. + + virtual ~LLCommandHandler(); + + virtual bool handle(const std::vector<std::string>& params) = 0; + // Execute the command with a provided (possibly empty) + // list of parameters. + // Return true if you did something, false if the parameters + // are invalid or on error. +}; + + +class LLCommandDispatcher +{ +public: + static bool dispatch(const std::string& cmd, const std::vector<std::string>& params); + // Execute a command registered via the above mechanism, + // passing string parameters. + // Returns true if command was found and executed correctly. +}; + +#endif diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index 242f5b7991..d53929272c 100644 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -197,47 +197,3 @@ void LLFloaterMap::toggle(void*) } } } - - -BOOL process_secondlife_url(LLString url) -{ - S32 strpos, strpos2; - - LLString slurlID = "slurl.com/secondlife/"; - strpos = url.find(slurlID); - - if (strpos < 0) - { - slurlID="secondlife://"; - strpos = url.find(slurlID); - } - - if (strpos >= 0) - { - LLString simname; - - strpos+=slurlID.length(); - strpos2=url.find("/",strpos); - if (strpos2 < strpos) strpos2=url.length(); - simname="secondlife://" + url.substr(strpos,url.length() - strpos); - - LLURLSimString::setString( simname ); - LLURLSimString::parse(); - - // if there is a world map - if ( gFloaterWorldMap ) - { - // mark where the destination is - gFloaterWorldMap->trackURL( LLURLSimString::sInstance.mSimName.c_str(), - LLURLSimString::sInstance.mX, - LLURLSimString::sInstance.mY, - LLURLSimString::sInstance.mZ ); - - // display map - LLFloaterWorldMap::show( NULL, TRUE ); - }; - - return TRUE; - } - return FALSE; -} diff --git a/indra/newview/llfloatermap.h b/indra/newview/llfloatermap.h index 5b581c0fe5..8f7629be3f 100644 --- a/indra/newview/llfloatermap.h +++ b/indra/newview/llfloatermap.h @@ -46,6 +46,4 @@ protected: extern LLFloaterMap *gFloaterMap; -BOOL process_secondlife_url(LLString url); - #endif // LL_LLFLOATERMAP_H diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 7a05f2bdbf..b730d15aab 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -31,6 +31,7 @@ #include "lltextbox.h" #include "llui.h" #include "lluiconstants.h" +#include "llurlsimstring.h" #include "llviewerbuild.h" #include "llviewerimagelist.h" #include "llviewermenu.h" // for handle_preferences() diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index fe17664c7d..615f872de8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -107,6 +107,8 @@ #include "lltexturefetch.h" #include "lltoolmgr.h" #include "llui.h" +#include "llurldispatcher.h" +#include "llurlsimstring.h" #include "llurlwhitelist.h" #include "lluserauth.h" #include "llviewerassetstorage.h" @@ -779,7 +781,7 @@ BOOL idle_startup() //For HTML parsing in text boxes. LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") ); - LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &process_secondlife_url ); + LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &LLURLDispatcher::dispatch, &LLURLDispatcher::dispatch ); //------------------------------------------------- // Handle startup progress screen @@ -2254,25 +2256,8 @@ BOOL idle_startup() gAgentPilot.startPlayback(); } - // ok, if we've gotten this far and have a startup URL - if (LLURLSimString::sInstance.parse()) - { - // kick off request for landmark to startup URL - if(gFloaterWorldMap) - { - LLVector3 pos = gAgent.getPositionAgent(); - if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName() - || LLURLSimString::sInstance.mX != llfloor(pos[VX]) - || LLURLSimString::sInstance.mY != llfloor(pos[VY]) ) - { - LLFloaterWorldMap::show(NULL, TRUE); - gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName, - LLURLSimString::sInstance.mX, - LLURLSimString::sInstance.mY, - LLURLSimString::sInstance.mZ); - } - } - } + // If we've got a startup URL, dispatch it + LLStartUp::dispatchURL(); // Clean up the userauth stuff. if (gUserAuthp) @@ -3665,13 +3650,6 @@ void release_start_screen() } // static -bool LLStartUp::canGoFullscreen() -{ - return LLStartUp::getStartupState() >= STATE_WORLD_INIT; -} - - -// static void LLStartUp::setStartupState( S32 state ) { llinfos << "Startup state changing from " << gStartupState << " to " << state << llendl; @@ -3692,3 +3670,40 @@ void reset_login() if ( gFloaterMap ) gFloaterMap->setVisible( FALSE ); } + +//--------------------------------------------------------------------------- + +std::string LLStartUp::sSLURLCommand; + +bool LLStartUp::canGoFullscreen() +{ + return gStartupState >= STATE_WORLD_INIT; +} + +bool LLStartUp::dispatchURL() +{ + // ok, if we've gotten this far and have a startup URL + if (!sSLURLCommand.empty()) + { + LLURLDispatcher::dispatch(sSLURLCommand); + } + else if (LLURLSimString::parse()) + { + // If we started with a location, but we're already + // at that location, don't pop dialogs open. + LLVector3 pos = gAgent.getPositionAgent(); + F32 dx = pos.mV[VX] - (F32)LLURLSimString::sInstance.mX; + F32 dy = pos.mV[VY] - (F32)LLURLSimString::sInstance.mY; + const F32 SLOP = 2.f; // meters + + if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName() + || (dx*dx > SLOP*SLOP) + || (dy*dy > SLOP*SLOP) ) + { + std::string url = LLURLSimString::getURL(); + LLURLDispatcher::dispatch(url); + } + return true; + } + return false; +} diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 9e1ff3c151..88ed0bdd24 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -64,6 +64,14 @@ public: static void setStartupState( S32 state ); static S32 getStartupState() { return gStartupState; }; + static bool dispatchURL(); + // if we have a SLURL or sim string ("Ahern/123/45") that started + // the viewer, dispatch it + + static std::string sSLURLCommand; + // *HACK: On startup, if we were passed a secondlife://app/do/foo + // command URL, store it for later processing. + protected: static S32 gStartupState; // Do not set directly, use LLStartup::setStartupState }; diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp new file mode 100644 index 0000000000..4145ec305c --- /dev/null +++ b/indra/newview/llurldispatcher.cpp @@ -0,0 +1,303 @@ +/** + * @file llurldispatcher.cpp + * @brief Central registry for all URL handlers + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ +#include "llviewerprecompiledheaders.h" + +#include "llurldispatcher.h" + +// viewer includes +#include "llagent.h" // teleportViaLocation() +#include "llcommandhandler.h" +// *FIX: code in merge sl-search-8 +//#include "llfloaterurldisplay.h" +#include "llfloaterdirectory.h" +#include "llfloaterhtmlhelp.h" +#include "llfloaterworldmap.h" +#include "llpanellogin.h" +#include "llstartup.h" // gStartupState +#include "llurlsimstring.h" +#include "llviewerwindow.h" // alertXml() +#include "llworldmap.h" + +// library includes +#include "llsd.h" + +// system includes +#include <boost/tokenizer.hpp> + +const std::string SLURL_SL_HELP_PREFIX = "secondlife://app."; +const std::string SLURL_SL_PREFIX = "sl://"; +const std::string SLURL_SECONDLIFE_PREFIX = "secondlife://"; +const std::string SLURL_SLURL_PREFIX = "http://slurl.com/secondlife/"; + +const std::string SLURL_APP_TOKEN = "app/"; + +class LLURLDispatcherImpl +{ +public: + static bool isSLURL(const std::string& url); + + static bool isSLURLCommand(const std::string& url); + + static bool dispatch(const std::string& url); + // returns true if handled + + static bool dispatchRightClick(const std::string& url); + +private: + static bool dispatchCore(const std::string& url, bool right_mouse); + // handles both left and right click + + static bool dispatchHelp(const std::string& url, BOOL right_mouse); + // Handles sl://app.floater.html.help by showing Help floater. + // Returns true if handled. + + static bool dispatchApp(const std::string& url, BOOL right_mouse); + // Handles secondlife://app/agent/<agent_id>/about and similar + // by showing panel in Search floater. + // Returns true if handled. + + static bool dispatchRegion(const std::string& url, BOOL right_mouse); + // handles secondlife://Ahern/123/45/67/ + // Returns true if handled. + +// *FIX: code in merge sl-search-8 +// static void regionHandleCallback(U64 handle, const std::string& url, +// const LLUUID& snapshot_id, bool teleport); +// // Called by LLWorldMap when a region name has been resolved to a +// // location in-world, used by places-panel display. + + static bool matchPrefix(const std::string& url, const std::string& prefix); + + static std::string stripProtocol(const std::string& url); + + friend class LLTeleportHandler; +}; + +// static +bool LLURLDispatcherImpl::isSLURL(const std::string& url) +{ + if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) return true; + if (matchPrefix(url, SLURL_SL_PREFIX)) return true; + if (matchPrefix(url, SLURL_SECONDLIFE_PREFIX)) return true; + if (matchPrefix(url, SLURL_SLURL_PREFIX)) return true; + return false; +} + +// static +bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url) +{ + if (matchPrefix(url, SLURL_SL_PREFIX + SLURL_APP_TOKEN) + || matchPrefix(url, SLURL_SECONDLIFE_PREFIX + SLURL_APP_TOKEN) + || matchPrefix(url, SLURL_SLURL_PREFIX + SLURL_APP_TOKEN) ) + { + return true; + } + return false; +} + +// static +bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool right_mouse) +{ + if (url.empty()) return false; + if (dispatchHelp(url, right_mouse)) return true; + if (dispatchApp(url, right_mouse)) return true; + if (dispatchRegion(url, right_mouse)) return true; + return false; +} + +// static +bool LLURLDispatcherImpl::dispatch(const std::string& url) +{ + llinfos << "url: " << url << llendl; + return dispatchCore(url, false); // not right click +} + +// static +bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url) +{ + llinfos << "url: " << url << llendl; + return dispatchCore(url, true); // yes right click +} +// static +bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, BOOL right_mouse) +{ + if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) + { + gViewerHtmlHelp.show(); + return true; + } + return false; +} + +// static +bool LLURLDispatcherImpl::dispatchApp(const std::string& url, BOOL right_mouse) +{ + if (!isSLURL(url)) + { + return false; + } + std::string s = stripProtocol(url); + + // At this point, "secondlife://app/foo/bar/baz/" should be left + // as: "app/foo/bar/baz/" + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep("/", "", boost::drop_empty_tokens); + tokenizer tokens(s, sep); + tokenizer::iterator it = tokens.begin(); + tokenizer::iterator end = tokens.end(); + + // Build parameter list suitable for LLDispatcher dispatch + if (it == end) return false; + if (*it != "app") return false; + ++it; + + if (it == end) return false; + std::string cmd = *it; + ++it; + + std::vector<std::string> params; + for ( ; it != end; ++it) + { + params.push_back(*it); + } + + bool handled = LLCommandDispatcher::dispatch(cmd, params); + if (handled) return true; + + // Inform the user we can't handle this + std::map<std::string, std::string> args; + args["[SLURL]"] = url; + gViewerWindow->alertXml("BadURL", args); + return false; +} + +// static +bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, BOOL right_mouse) +{ + if (!isSLURL(url)) + { + return false; + } + + // Before we're logged in, need to update the startup screen + // to tell the user where they are going. + if (LLStartUp::getStartupState() < STATE_CLEANUP) + { + // Parse it and stash in globals, it will be dispatched in + // STATE_CLEANUP. + LLURLSimString::setString(url); + // We're at the login screen, so make sure user can see + // the login location box to know where they are going. + LLPanelLogin::refreshLocation( true ); + return true; + } + + std::string sim_string = stripProtocol(url); + std::string region_name; + S32 x = 128; + S32 y = 128; + S32 z = 0; + LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z); + if (gFloaterWorldMap) + { + llinfos << "Opening map to " << region_name << llendl; + gFloaterWorldMap->trackURL( region_name.c_str(), x, y, z ); + LLFloaterWorldMap::show(NULL, TRUE); + } + return true; +} + +// static +bool LLURLDispatcherImpl::matchPrefix(const std::string& url, const std::string& prefix) +{ + std::string test_prefix = url.substr(0, prefix.length()); + LLString::toLower(test_prefix); + return test_prefix == prefix; +} + +// static +std::string LLURLDispatcherImpl::stripProtocol(const std::string& url) +{ + std::string stripped = url; + if (matchPrefix(stripped, SLURL_SL_HELP_PREFIX)) + { + stripped.erase(0, SLURL_SL_HELP_PREFIX.length()); + } + else if (matchPrefix(stripped, SLURL_SL_PREFIX)) + { + stripped.erase(0, SLURL_SL_PREFIX.length()); + } + else if (matchPrefix(stripped, SLURL_SECONDLIFE_PREFIX)) + { + stripped.erase(0, SLURL_SECONDLIFE_PREFIX.length()); + } + else if (matchPrefix(stripped, SLURL_SLURL_PREFIX)) + { + stripped.erase(0, SLURL_SLURL_PREFIX.length()); + } + return stripped; +} + +// *FIX: code in merge sl-search-8 +// +////--------------------------------------------------------------------------- +//// Teleportation links are handled here because they are tightly coupled +//// to URL parsing and sim-fragment parsing +//class LLTeleportHandler : public LLCommandHandler +//{ +//public: +// LLTeleportHandler() : LLCommandHandler("teleport") { } +// bool handle(const std::vector<std::string>& tokens) +// { +// // construct a "normal" SLURL, resolve the region to +// // a global position, and teleport to it +// if (tokens.size() < 1) return false; +// +// // Region names may be %20 escaped. +// std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]); +// +// // build secondlife://De%20Haro/123/45/67 for use in callback +// std::string url = SLURL_SECONDLIFE_PREFIX; +// for (size_t i = 0; i < tokens.size(); ++i) +// { +// url += tokens[i] + "/"; +// } +// gWorldMap->sendNamedRegionRequest(region_name, +// LLURLDispatcherImpl::regionHandleCallback, +// url, +// true); // teleport +// return true; +// } +//}; +//LLTeleportHandler gTeleportHandler; + +//--------------------------------------------------------------------------- + +// static +bool LLURLDispatcher::isSLURL(const std::string& url) +{ + return LLURLDispatcherImpl::isSLURL(url); +} + +// static +bool LLURLDispatcher::isSLURLCommand(const std::string& url) +{ + return LLURLDispatcherImpl::isSLURLCommand(url); +} + +// static +bool LLURLDispatcher::dispatch(const std::string& url) +{ + return LLURLDispatcherImpl::dispatch(url); +} +// static +bool LLURLDispatcher::dispatchRightClick(const std::string& url) +{ + return LLURLDispatcherImpl::dispatchRightClick(url); +} + diff --git a/indra/newview/llurldispatcher.h b/indra/newview/llurldispatcher.h new file mode 100644 index 0000000000..e701a01be4 --- /dev/null +++ b/indra/newview/llurldispatcher.h @@ -0,0 +1,32 @@ +/** + * @file llurldispatcher.h + * @brief Central registry for all SL URL handlers + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ +#ifndef LLURLDISPATCHER_H +#define LLURLDISPATCHER_H + +class LLURLDispatcher +{ +public: + static bool isSLURL(const std::string& url); + // Is this any sort of secondlife:// or sl:// URL? + + static bool isSLURLCommand(const std::string& url); + // Is this a special secondlife://app/ URL? + + static bool dispatch(const std::string& url); + // At startup time and on clicks in internal web browsers, + // teleport, open map, or run requested command. + // Handles: + // secondlife://RegionName/123/45/67/ + // secondlife://app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show + // sl://app/foo/bar + // Returns true if someone handled the URL. + static bool dispatchRightClick(const std::string& url); + +}; + +#endif diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c242d855f1..adea8968e5 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -83,7 +83,6 @@ #include "llfloatergroups.h" #include "llfloaterhtml.h" #include "llfloaterhtmlhelp.h" -#include "llfloaterhtmlfind.h" #include "llfloaterinspect.h" #include "llfloaterlagmeter.h" #include "llfloaterland.h" @@ -340,6 +339,7 @@ void toggle_show_xui_names(void *); BOOL check_show_xui_names(void *); // Debug UI +void handle_slurl_test(void*); void handle_save_to_xml(void*); void handle_load_from_xml(void*); @@ -976,6 +976,7 @@ extern BOOL gVectorizePerfTest; void init_debug_ui_menu(LLMenuGL* menu) { + menu->append(new LLMenuItemCallGL("SLURL Test", &handle_slurl_test)); menu->append(new LLMenuItemCallGL("Editable UI", &edit_ui)); menu->append(new LLMenuItemToggleGL("Async Keystrokes", &gHandleKeysAsync)); menu->append(new LLMenuItemCallGL( "Dump SelectMgr", &dump_select_mgr)); @@ -7282,6 +7283,11 @@ void handle_load_from_xml(void*) } } +void handle_slurl_test(void*) +{ + LLFloaterHtml::getInstance()->show("http://user.lindenlab.com/~james/slurl.html", "SLURL Test"); +} + void handle_rebake_textures(void*) { LLVOAvatar* avatar = gAgent.getAvatarObject(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 897831afc0..d4b87ceba0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -136,6 +136,7 @@ #include "lltoolview.h" #include "llvieweruictrlfactory.h" #include "lluploaddialog.h" +#include "llurldispatcher.h" // SLURL from other app instance #include "llviewercamera.h" #include "llviewergesture.h" #include "llviewerimagelist.h" @@ -1394,22 +1395,14 @@ void LLViewerWindow::handleWindowUnblock(LLWindow *window) void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data) { + const S32 SLURL_MESSAGE_TYPE = 0; switch (data_type) { - case 0: + case SLURL_MESSAGE_TYPE: // received URL - if (LLURLSimString::unpack_data(data)) + std::string url = (const char*)data; + if (LLURLDispatcher::dispatch(url)) { - if(gFloaterWorldMap) - { - gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName, - LLURLSimString::sInstance.mX, - LLURLSimString::sInstance.mY, - LLURLSimString::sInstance.mZ); - - LLFloaterWorldMap::show(NULL, TRUE); - } - // bring window to foreground, as it has just been "launched" from a URL mWindow->bringToFront(); } |