Initial moap commit. /VERY/ WIP. Primarily committed to clean up unstaged changes. Do not run this, even if it may compile, as it will NOT work (for a myriad of reasons)!

This commit is contained in:
Shyotl
2013-05-31 05:33:41 -05:00
parent 641ada030e
commit ef3e918558
148 changed files with 15636 additions and 4633 deletions

View File

@@ -76,6 +76,7 @@ set(llcommon_SOURCE_FILES
llrun.cpp
llscopedvolatileaprpool.h
llsd.cpp
llsdparam.cpp
llsdserialize.cpp
llsdserialize_xml.cpp
llsdutil.cpp
@@ -204,10 +205,11 @@ set(llcommon_HEADER_FILES
llqueuedthread.h
llrand.h
llrefcount.h
llrefcount.h
llregistry.h
llrun.h
llsafehandle.h
llsd.h
llsdparam.h
llsdserialize.h
llsdserialize_xml.h
llsdutil.h

356
indra/llcommon/llregistry.h Normal file
View File

@@ -0,0 +1,356 @@
/**
* @file llregistry.h
* @brief template classes for registering name, value pairs in nested scopes, statically, etc.
*
* $LicenseInfo:firstyear=2001&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$
*/
#ifndef LL_LLREGISTRY_H
#define LL_LLREGISTRY_H
#include <list>
#include <boost/type_traits.hpp>
#include "llsingleton.h"
#include "llstl.h"
template <typename T>
struct LLRegistryDefaultComparator
{
bool operator()(const T& lhs, const T& rhs) const
{
using std::less;
return less<T>()(lhs, rhs);
}
};
template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
class LLRegistry
{
public:
typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type ref_const_key_t;
typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type ref_const_value_t;
typedef typename boost::add_reference<VALUE>::type ref_value_t;
typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type ptr_const_value_t;
typedef typename boost::add_pointer<VALUE>::type ptr_value_t;
class Registrar
{
friend class LLRegistry<KEY, VALUE, COMPARATOR>;
public:
typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
bool add(ref_const_key_t key, ref_const_value_t value)
{
if (mMap.insert(std::make_pair(key, value)).second == false)
{
llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
return false;
}
return true;
}
void remove(ref_const_key_t key)
{
mMap.erase(key);
}
void replace(ref_const_key_t key, ref_const_value_t value)
{
mMap[key] = value;
}
typename registry_map_t::const_iterator beginItems() const
{
return mMap.begin();
}
typename registry_map_t::const_iterator endItems() const
{
return mMap.end();
}
protected:
ptr_value_t getValue(ref_const_key_t key)
{
typename registry_map_t::iterator found_it = mMap.find(key);
if (found_it != mMap.end())
{
return &(found_it->second);
}
return NULL;
}
ptr_const_value_t getValue(ref_const_key_t key) const
{
typename registry_map_t::const_iterator found_it = mMap.find(key);
if (found_it != mMap.end())
{
return &(found_it->second);
}
return NULL;
}
// if the registry is used to store pointers, and null values are valid entries
// then use this function to check the existence of an entry
bool exists(ref_const_key_t key) const
{
return mMap.find(key) != mMap.end();
}
bool empty() const
{
return mMap.empty();
}
protected:
// use currentRegistrar() or defaultRegistrar()
Registrar() {}
~Registrar() {}
private:
registry_map_t mMap;
};
typedef typename std::list<Registrar*> scope_list_t;
typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
LLRegistry()
{}
~LLRegistry() {}
ptr_value_t getValue(ref_const_key_t key)
{
for(scope_list_iterator_t it = mActiveScopes.begin();
it != mActiveScopes.end();
++it)
{
ptr_value_t valuep = (*it)->getValue(key);
if (valuep != NULL) return valuep;
}
return mDefaultRegistrar.getValue(key);
}
ptr_const_value_t getValue(ref_const_key_t key) const
{
for(scope_list_const_iterator_t it = mActiveScopes.begin();
it != mActiveScopes.end();
++it)
{
ptr_value_t valuep = (*it)->getValue(key);
if (valuep != NULL) return valuep;
}
return mDefaultRegistrar.getValue(key);
}
bool exists(ref_const_key_t key) const
{
for(scope_list_const_iterator_t it = mActiveScopes.begin();
it != mActiveScopes.end();
++it)
{
if ((*it)->exists(key)) return true;
}
return mDefaultRegistrar.exists(key);
}
bool empty() const
{
for(scope_list_const_iterator_t it = mActiveScopes.begin();
it != mActiveScopes.end();
++it)
{
if (!(*it)->empty()) return false;
}
return mDefaultRegistrar.empty();
}
Registrar& defaultRegistrar()
{
return mDefaultRegistrar;
}
const Registrar& defaultRegistrar() const
{
return mDefaultRegistrar;
}
Registrar& currentRegistrar()
{
if (!mActiveScopes.empty())
{
return *mActiveScopes.front();
}
return mDefaultRegistrar;
}
const Registrar& currentRegistrar() const
{
if (!mActiveScopes.empty())
{
return *mActiveScopes.front();
}
return mDefaultRegistrar;
}
protected:
void addScope(Registrar* scope)
{
// newer scopes go up front
mActiveScopes.insert(mActiveScopes.begin(), scope);
}
void removeScope(Registrar* scope)
{
// O(N) but should be near the beggining and N should be small and this is safer than storing iterators
scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
if (iter != mActiveScopes.end())
{
mActiveScopes.erase(iter);
}
}
private:
scope_list_t mActiveScopes;
Registrar mDefaultRegistrar;
};
template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
class LLRegistrySingleton
: public LLRegistry<KEY, VALUE, COMPARATOR>,
public LLSingleton<DERIVED_TYPE>
{
friend class LLSingleton<DERIVED_TYPE>;
public:
typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
typedef const KEY& ref_const_key_t;
typedef const VALUE& ref_const_value_t;
typedef VALUE* ptr_value_t;
typedef const VALUE* ptr_const_value_t;
typedef LLSingleton<DERIVED_TYPE> singleton_t;
class ScopedRegistrar : public registry_t::Registrar
{
public:
ScopedRegistrar(bool push_scope = true)
{
if (push_scope)
{
pushScope();
}
}
~ScopedRegistrar()
{
if (!singleton_t::destroyed())
{
popScope();
}
}
void pushScope()
{
singleton_t::instance().addScope(this);
}
void popScope()
{
singleton_t::instance().removeScope(this);
}
ptr_value_t getValueFromScope(ref_const_key_t key)
{
return getValue(key);
}
ptr_const_value_t getValueFromScope(ref_const_key_t key) const
{
return getValue(key);
}
private:
typename std::list<typename registry_t::Registrar*>::iterator mListIt;
};
class StaticRegistrar : public registry_t::Registrar
{
public:
virtual ~StaticRegistrar() {}
StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
{
singleton_t::instance().mStaticScope->add(key, value);
}
};
// convenience functions
typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
static ref_registrar_t currentRegistrar()
{
return singleton_t::instance().registry_t::currentRegistrar();
}
static ref_registrar_t defaultRegistrar()
{
return singleton_t::instance().registry_t::defaultRegistrar();
}
static ptr_value_t getValue(ref_const_key_t key)
{
return singleton_t::instance().registry_t::getValue(key);
}
protected:
// DERIVED_TYPE needs to derive from LLRegistrySingleton
LLRegistrySingleton()
: mStaticScope(NULL)
{}
virtual void initSingleton()
{
mStaticScope = new ScopedRegistrar();
}
virtual ~LLRegistrySingleton()
{
delete mStaticScope;
}
private:
ScopedRegistrar* mStaticScope;
};
// helper macro for doing static registration
#define GLUED_TOKEN(x, y) x ## y
#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
#endif

View File

@@ -0,0 +1,342 @@
/**
* @file llsdparam.cpp
* @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $LicenseInfo:firstyear=2008&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 "linden_common.h"
// Project includes
#include "llsdparam.h"
#include "llsdutil.h"
static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
static const LLSD NO_VALUE_MARKER;
LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
//
// LLParamSDParser
//
LLParamSDParser::LLParamSDParser()
: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
{
using boost::bind;
if (sReadFuncs.empty())
{
registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
}
}
// special case handling of U32 due to ambiguous LLSD::assign overload
bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
if (!sdparser.mWriteRootSD) return false;
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
sd_to_write.assign((S32)*((const U32*)val_ptr));
return true;
}
bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
if (!sdparser.mWriteRootSD) return false;
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
return true;
}
void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
{
mCurReadSD = &sd;
block.submitValue(name_stack, *this);
}
void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
{
mCurReadSD = NULL;
mNameStack.clear();
setParseSilently(silent);
LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
//readSDValues(sd, block);
}
void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
{
mNameStack.clear();
mWriteRootSD = &sd;
name_stack_t name_stack;
block.serializeBlock(*this, name_stack);
}
/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
{
std::string full_name = "sd";
for (name_stack_t::iterator it = mNameStack.begin();
it != mNameStack.end();
++it)
{
full_name += llformat("[%s]", it->first.c_str());
}
return full_name;
}
bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
return self.mCurReadSD == &NO_VALUE_MARKER;
}
bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((S32*)val_ptr) = self.mCurReadSD->asInteger();
return true;
}
bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((U32*)val_ptr) = self.mCurReadSD->asInteger();
return true;
}
bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((F32*)val_ptr) = self.mCurReadSD->asReal();
return true;
}
bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((F64*)val_ptr) = self.mCurReadSD->asReal();
return true;
}
bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((bool*)val_ptr) = self.mCurReadSD->asBoolean();
return true;
}
bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((std::string*)val_ptr) = self.mCurReadSD->asString();
return true;
}
bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
return true;
}
bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
return true;
}
bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
return true;
}
bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLSD*)val_ptr) = *self.mCurReadSD;
return true;
}
// static
LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
{
LLSD* sd_to_write = &input;
for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
it != name_stack_range.second;
++it)
{
bool new_traversal = it->second;
LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
if (child_sd->isArray())
{
if (new_traversal)
{
// write to new element at end
sd_to_write = &(*child_sd)[child_sd->size()];
}
else
{
// write to last of existing elements, or first element if empty
sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
}
}
else
{
if (new_traversal
&& child_sd->isDefined()
&& !child_sd->isArray())
{
// copy child contents into first element of an array
LLSD new_array = LLSD::emptyArray();
new_array.append(*child_sd);
// assign array to slot that previously held the single value
*child_sd = new_array;
// return next element in that array
sd_to_write = &((*child_sd)[1]);
}
else
{
sd_to_write = child_sd;
}
}
it->second = false;
}
return *sd_to_write;
}
//static
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
{
if (sd.isMap())
{
for (LLSD::map_const_iterator it = sd.beginMap();
it != sd.endMap();
++it)
{
stack.push_back(make_pair(it->first, true));
readSDValues(cb, it->second, stack);
stack.pop_back();
}
}
else if (sd.isArray())
{
for (LLSD::array_const_iterator it = sd.beginArray();
it != sd.endArray();
++it)
{
stack.back().second = true;
readSDValues(cb, *it, stack);
}
}
else if (sd.isUndefined())
{
if (!cb.empty())
{
cb(NO_VALUE_MARKER, stack);
}
}
else
{
if (!cb.empty())
{
cb(sd, stack);
}
}
}
//static
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
{
LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
readSDValues(cb, sd, stack);
}
namespace LLInitParam
{
// LLSD specialization
// block param interface
bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
{
LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
LLSD::String string;
if (p.readValue<LLSD::String>(string))
{
sd = string;
return true;
}
return false;
}
//static
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
{
p.writeValue<LLSD::String>(sd.asString(), name_stack);
}
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
{
// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
Parser::name_stack_t stack;
LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
}
}

126
indra/llcommon/llsdparam.h Normal file
View File

@@ -0,0 +1,126 @@
/**
* @file llsdparam.h
* @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $LicenseInfo:firstyear=2008&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$
*/
#ifndef LL_LLSDPARAM_H
#define LL_LLSDPARAM_H
#include "llinitparam.h"
#include "boost/function.hpp"
struct LL_COMMON_API LLParamSDParserUtilities
{
static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
};
class LL_COMMON_API LLParamSDParser
: public LLInitParam::Parser
{
LOG_CLASS(LLParamSDParser);
typedef LLInitParam::Parser parser_t;
public:
LLParamSDParser();
void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
/*virtual*/ std::string getCurrentElementName();
private:
void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
template<typename T>
static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
if (!sdparser.mWriteRootSD) return false;
LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
sd_to_write.assign(*((const T*)val_ptr));
return true;
}
static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
static bool readFlag(Parser& parser, void* val_ptr);
static bool readS32(Parser& parser, void* val_ptr);
static bool readU32(Parser& parser, void* val_ptr);
static bool readF32(Parser& parser, void* val_ptr);
static bool readF64(Parser& parser, void* val_ptr);
static bool readBool(Parser& parser, void* val_ptr);
static bool readString(Parser& parser, void* val_ptr);
static bool readUUID(Parser& parser, void* val_ptr);
static bool readDate(Parser& parser, void* val_ptr);
static bool readURI(Parser& parser, void* val_ptr);
static bool readSD(Parser& parser, void* val_ptr);
Parser::name_stack_t mNameStack;
const LLSD* mCurReadSD;
LLSD* mWriteRootSD;
LLSD* mCurWriteSD;
};
extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
template<typename T>
class LLSDParamAdapter : public T
{
public:
LLSDParamAdapter() {}
LLSDParamAdapter(const LLSD& sd)
{
LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
LLParamSDParser parser;
// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
bool parse_silently = true;
parser.readSD(sd, *this, parse_silently);
}
operator LLSD() const
{
LLParamSDParser parser;
LLSD sd;
parser.writeSD(sd, *this);
return sd;
}
LLSDParamAdapter(const T& val)
: T(val)
{
T::operator=(val);
}
};
#endif // LL_LLSDPARAM_H

View File

@@ -45,44 +45,49 @@ const std::string AUCTION_URL (
const std::string EVENTS_URL (
"http://secondlife.com/events/");
/*
const std::string TIER_UP_URL (
"http://secondlife.com/app/landtier");
const std::string LAND_URL (
"http://secondlife.com/app/landtier");
const std::string UPGRADE_TO_PREMIUM_URL (
"http://secondlife.com/app/upgrade/");
"http://secondlife.com/app/landtier"); // *TODO: NOT USED
*/
const std::string DIRECTX_9_URL (
"http://secondlife.com/support/");
"http://secondlife.com/support/"); // *TODO: NOT USED
/*
const std::string LAND_URL (
"http://secondlife.com/app/landtier"); // *TODO: NOT USED
const std::string UPGRADE_TO_PREMIUM_URL (
"http://secondlife.com/app/upgrade/"); // *TODO: NOT USED
const std::string AMD_AGP_URL (
"http://secondlife.com/support/");
"http://secondlife.com/support/"); // *TODO: NOT USED
const std::string VIA_URL (
"http://secondlife.com/support/");
"http://secondlife.com/support/"); // *TODO: NOT USED
const std::string SUPPORT_URL (
"http://secondlife.com/support/");
const std::string INTEL_CHIPSET_URL (
"http://secondlife.com/support/");
"http://secondlife.com/support/"); // *TODO: NOT USED
const std::string SIS_CHIPSET_URL (
"http://secondlife.com/support/");
"http://secondlife.com/support/"); // *TODO: NOT USED
const std::string BLOGS_URL (
"http://blog.secondlife.com/");
"http://blog.secondlife.com/"); // *TODO: NOT USED
*/
const std::string BUY_CURRENCY_URL (
"http://secondlife.com/app/currency/");
/*
const std::string LSL_DOC_URL (
"http://secondlife.com/app/lsldoc/");
"http://secondlife.com/app/lsldoc/"); // *TODO: NOT USED
const std::string SL_KB_URL (
"http://secondlife.com/knowledgebase/");
"http://secondlife.com/knowledgebase/"); // *TODO: NOT USED
const std::string RELEASE_NOTES_BASE_URL (
"http://ascent.balseraph.org/?");
"http://secondlife.com/app/releasenotes/");
*/

View File

@@ -43,18 +43,22 @@ LL_COMMON_API extern const std::string AUCTION_URL;
LL_COMMON_API extern const std::string EVENTS_URL;
/*
// Tier up to a new land level.
LL_COMMON_API extern const std::string TIER_UP_URL;
// Tier up to a new land level.
LL_COMMON_API extern const std::string LAND_URL;
// Upgrade from basic membership to premium membership
LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
*/
// How to get DirectX 9
LL_COMMON_API extern const std::string DIRECTX_9_URL;
/*
// Upgrade from basic membership to premium membership
LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
// Out of date VIA chipset
LL_COMMON_API extern const std::string VIA_URL;
@@ -63,10 +67,12 @@ LL_COMMON_API extern const std::string SUPPORT_URL;
// Linden Blogs page
LL_COMMON_API extern const std::string BLOGS_URL;
*/
// Currency page
LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
/*
// LSL script wiki
LL_COMMON_API extern const std::string LSL_DOC_URL;
@@ -75,5 +81,5 @@ LL_COMMON_API extern const std::string SL_KB_URL;
// Release Notes Redirect URL for Server and Viewer
LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
*/
#endif

View File

@@ -917,6 +917,7 @@ P(MPImportGetResponder);
P(MPImportPostResponder);
P(mapLayerResponder);
P2(maturityPreferences, transfer_30s);
P(mediaDataClientResponder);
P(mediaTypeResponder);
P(meshDecompositionResponder);
P(meshHeaderResponder);

View File

@@ -34,7 +34,9 @@
#include "llrect.h"
#include "v4color.h"
class LLPluginClassMedia : public LLPluginClassBasic
#include <boost/signals2.hpp>
class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::trackable
{
LOG_CLASS(LLPluginClassMedia);

View File

@@ -26,13 +26,30 @@
#include "linden_common.h"
#include "lluuid.h"
#include "llmediaentry.h"
#include "lltextureentry.h"
#include "llsdutil_math.h"
#include "v4color.h"
const U8 DEFAULT_BUMP_CODE = 0; // no bump or shininess
const LLTextureEntry LLTextureEntry::null;
// Some LLSD keys. Do not change these!
#define OBJECT_ID_KEY_STR "object_id"
#define TEXTURE_INDEX_KEY_STR "texture_index"
#define OBJECT_MEDIA_VERSION_KEY_STR "object_media_version"
#define OBJECT_MEDIA_DATA_KEY_STR "object_media_data"
#define TEXTURE_MEDIA_DATA_KEY_STR "media_data"
/*static*/ const char* LLTextureEntry::OBJECT_ID_KEY = OBJECT_ID_KEY_STR;
/*static*/ const char* LLTextureEntry::OBJECT_MEDIA_DATA_KEY = OBJECT_MEDIA_DATA_KEY_STR;
/*static*/ const char* LLTextureEntry::MEDIA_VERSION_KEY = OBJECT_MEDIA_VERSION_KEY_STR;
/*static*/ const char* LLTextureEntry::TEXTURE_INDEX_KEY = TEXTURE_INDEX_KEY_STR;
/*static*/ const char* LLTextureEntry::TEXTURE_MEDIA_DATA_KEY = TEXTURE_MEDIA_DATA_KEY_STR;
static const std::string MEDIA_VERSION_STRING_PREFIX = "x-mv:";
// static
LLTextureEntry* LLTextureEntry::newTextureEntry()
@@ -42,16 +59,19 @@ LLTextureEntry* LLTextureEntry::newTextureEntry()
//===============================================================
LLTextureEntry::LLTextureEntry()
: mMediaEntry(NULL)
{
init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)
: mMediaEntry(NULL)
{
init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
: mMediaEntry(NULL)
{
mID = rhs.mID;
mScaleS = rhs.mScaleS;
@@ -63,6 +83,10 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
if (rhs.mMediaEntry != NULL) {
// Make a copy
mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
}
}
LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
@@ -79,6 +103,16 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
if (mMediaEntry != NULL) {
delete mMediaEntry;
}
if (rhs.mMediaEntry != NULL) {
// Make a copy
mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
}
else {
mMediaEntry = NULL;
}
}
return *this;
@@ -98,10 +132,19 @@ void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 of
mGlow = 0;
setColor(LLColor4(1.f, 1.f, 1.f, 1.f));
if (mMediaEntry != NULL) {
delete mMediaEntry;
}
mMediaEntry = NULL;
}
LLTextureEntry::~LLTextureEntry()
{
if(mMediaEntry)
{
delete mMediaEntry;
mMediaEntry = NULL;
}
}
bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const
@@ -153,6 +196,13 @@ void LLTextureEntry::asLLSD(LLSD& sd) const
sd["bump"] = getBumpShiny();
sd["fullbright"] = getFullbright();
sd["media_flags"] = mMediaFlags;
if (hasMedia()) {
LLSD mediaData;
if (NULL != getMediaData()) {
getMediaData()->asLLSD(mediaData);
}
sd[TEXTURE_MEDIA_DATA_KEY] = mediaData;
}
sd["glow"] = mGlow;
}
@@ -201,6 +251,17 @@ bool LLTextureEntry::fromLLSD(const LLSD& sd)
{
setMediaTexGen( sd[w].asInteger() );
} else goto fail;
// If the "has media" flag doesn't match the fact that
// media data exists, updateMediaData will "fix" it
// by either clearing or setting the flag
w = TEXTURE_MEDIA_DATA_KEY;
if (hasMedia() != sd.has(w))
{
llwarns << "LLTextureEntry::fromLLSD: media_flags (" << hasMedia() <<
") does not match presence of media_data (" << sd.has(w) << "). Fixing." << llendl;
}
updateMediaData(sd[w]);
w = "glow";
if (sd.has(w))
{
@@ -362,12 +423,10 @@ S32 LLTextureEntry::setBumpShinyFullbright(U8 bump)
S32 LLTextureEntry::setMediaTexGen(U8 media)
{
if (mMediaFlags != media)
{
mMediaFlags = media;
return TEM_CHANGE_MEDIA;
}
return TEM_CHANGE_NONE;
S32 result = TEM_CHANGE_NONE;
result |= setTexGen(media & TEM_TEX_GEN_MASK);
result |= setMediaFlags(media & TEM_MEDIA_MASK);
return result;
}
S32 LLTextureEntry::setBumpmap(U8 bump)
@@ -425,6 +484,18 @@ S32 LLTextureEntry::setMediaFlags(U8 media_flags)
{
mMediaFlags &= ~TEM_MEDIA_MASK;
mMediaFlags |= media_flags;
// Special code for media handling
if( hasMedia() && mMediaEntry == NULL)
{
mMediaEntry = new LLMediaEntry;
}
else if ( ! hasMedia() && mMediaEntry != NULL)
{
delete mMediaEntry;
mMediaEntry = NULL;
}
return TEM_CHANGE_MEDIA;
}
return TEM_CHANGE_NONE;
@@ -452,4 +523,112 @@ S32 LLTextureEntry::setGlow(F32 glow)
return TEM_CHANGE_NONE;
}
void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry)
{
mMediaFlags |= MF_HAS_MEDIA;
if (NULL != mMediaEntry)
{
delete mMediaEntry;
}
mMediaEntry = new LLMediaEntry(media_entry);
}
bool LLTextureEntry::updateMediaData(const LLSD& media_data)
{
if (media_data.isUndefined())
{
// clear the media data
clearMediaData();
return false;
}
else {
mMediaFlags |= MF_HAS_MEDIA;
if (mMediaEntry == NULL)
{
mMediaEntry = new LLMediaEntry;
}
// *NOTE: this will *clobber* all of the fields in mMediaEntry
// with whatever fields are present (or not present) in media_data!
mMediaEntry->fromLLSD(media_data);
return true;
}
}
void LLTextureEntry::clearMediaData()
{
mMediaFlags &= ~MF_HAS_MEDIA;
if (mMediaEntry != NULL) {
delete mMediaEntry;
}
mMediaEntry = NULL;
}
void LLTextureEntry::mergeIntoMediaData(const LLSD& media_fields)
{
mMediaFlags |= MF_HAS_MEDIA;
if (mMediaEntry == NULL)
{
mMediaEntry = new LLMediaEntry;
}
// *NOTE: this will *merge* the data in media_fields
// with the data in our media entry
mMediaEntry->mergeFromLLSD(media_fields);
}
//static
std::string LLTextureEntry::touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id)
{
// XXX TODO: make media version string binary (base64-encoded?)
// Media "URL" is a representation of a version and the last-touched agent
// x-mv:nnnnn/agent-id
// where "nnnnn" is version number
// *NOTE: not the most efficient code in the world...
U32 current_version = getVersionFromMediaVersionString(in_version) + 1;
const size_t MAX_VERSION_LEN = 10; // 2^32 fits in 10 decimal digits
char buf[MAX_VERSION_LEN+1];
snprintf(buf, (int)MAX_VERSION_LEN+1, "%0*u", (int)MAX_VERSION_LEN, current_version); // added int cast to fix warning/breakage on mac.
return MEDIA_VERSION_STRING_PREFIX + buf + "/" + agent_id.asString();
}
//static
U32 LLTextureEntry::getVersionFromMediaVersionString(const std::string &version_string)
{
U32 version = 0;
if (!version_string.empty())
{
size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
if (found != std::string::npos)
{
found = version_string.find_first_of("/", found);
std::string v = version_string.substr(MEDIA_VERSION_STRING_PREFIX.length(), found);
version = strtoul(v.c_str(),NULL,10);
}
}
return version;
}
//static
LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &version_string)
{
LLUUID id;
if (!version_string.empty())
{
size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
if (found != std::string::npos)
{
found = version_string.find_first_of("/", found);
if (found != std::string::npos)
{
std::string v = version_string.substr(found + 1);
id.set(v);
}
}
}
return id;
}
//static
bool LLTextureEntry::isMediaVersionString(const std::string &version_string)
{
return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX);
}

View File

@@ -62,6 +62,8 @@ const S32 TEM_MEDIA_MASK = 0x01;
const S32 TEM_TEX_GEN_MASK = 0x06;
const S32 TEM_TEX_GEN_SHIFT = 1;
// forward declarations
class LLMediaEntry;
class LLTextureEntry
{
@@ -137,6 +139,34 @@ public:
U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; }
U8 getMediaTexGen() const { return mMediaFlags; }
F32 getGlow() const { return mGlow; }
// *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
// CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
// to NOT return NULL.
bool hasMedia() const { return (bool)(mMediaFlags & MF_HAS_MEDIA); }
LLMediaEntry* getMediaData() const { return mMediaEntry; }
// Completely change the media data on this texture entry.
void setMediaData(const LLMediaEntry &media_entry);
// Returns true if media data was updated, false if it was cleared
bool updateMediaData(const LLSD& media_data);
// Clears media data, and sets the media flags bit to 0
void clearMediaData();
// Merges the given LLSD of media fields with this media entry.
// Only those fields that are set that match the keys in
// LLMediaEntry will be affected. If no fields are set or if
// the LLSD is undefined, this is a no-op.
void mergeIntoMediaData(const LLSD& media_fields);
// Takes a media version string (an empty string or a previously-returned string)
// and returns a "touched" string, touched by agent_id
static std::string touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id);
// Given a media version string, return the version
static U32 getVersionFromMediaVersionString(const std::string &version_string);
// Given a media version string, return the UUID of the agent
static LLUUID getAgentIDFromMediaVersionString(const std::string &version_string);
// Return whether or not the given string is actually a media version
static bool isMediaVersionString(const std::string &version_string);
// Media flags
enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 };
@@ -149,6 +179,14 @@ public:
F32 mRotation; // anti-clockwise rotation in rad about the bottom left corner
static const LLTextureEntry null;
// LLSD key defines
static const char* OBJECT_ID_KEY;
static const char* OBJECT_MEDIA_DATA_KEY;
static const char* MEDIA_VERSION_KEY;
static const char* TEXTURE_INDEX_KEY;
static const char* TEXTURE_MEDIA_DATA_KEY;
protected:
LLUUID mID; // Texture GUID
LLColor4 mColor;
@@ -156,6 +194,9 @@ protected:
U8 mMediaFlags; // replace with web page, movie, etc.
F32 mGlow;
// Note the media data is not sent via the same message structure as the rest of the TE
LLMediaEntry* mMediaEntry; // The media data for the face
// NOTE: when adding new data to this class, in addition to adding it to the serializers asLLSD/fromLLSD and the
// message packers (e.g. LLPrimitive::packTEMessage) you must also implement its copy in LLPrimitive::copyTEs()

View File

@@ -39,6 +39,7 @@ set(llui_SOURCE_FILES
llfunctorregistry.cpp
lliconctrl.cpp
llkeywords.cpp
lllayoutstack.cpp
lllineeditor.cpp
lllocalcliprect.cpp
llmenugl.cpp
@@ -78,6 +79,10 @@ set(llui_SOURCE_FILES
lluictrlfactory.cpp
lluistring.cpp
llundo.cpp
llurlaction.cpp
llurlentry.cpp
llurlmatch.cpp
llurlregistry.cpp
llview.cpp
llviewborder.cpp
llviewmodel.cpp
@@ -105,6 +110,7 @@ set(llui_HEADER_FILES
llhtmlhelp.h
lliconctrl.h
llkeywords.h
lllayoutstack.h
lllineeditor.h
lllocalcliprect.h
llmemberlistener.h
@@ -150,6 +156,10 @@ set(llui_HEADER_FILES
lluistring.h
lluixmltags.h
llundo.h
llurlaction.h
llurlentry.h
llurlmatch.h
llurlregistry.h
llview.h
llviewborder.h
llviewmodel.h

View File

@@ -520,7 +520,7 @@ void LLAlertDialog::onButtonPressed( LLUICtrl* ctrl, const std::string url )
// If we declared a URL and chose the URL option, go to the url
if (!url.empty() && sURLLoader != NULL)
{
sURLLoader->load(url);
sURLLoader->load(url, false);
}
mNote->respond(response); // new notification reponse

View File

@@ -57,7 +57,7 @@ public:
class URLLoader
{
public:
virtual void load(const std::string& url) = 0;
virtual void load(const std::string& url, bool force_open_externally) = 0;
virtual ~URLLoader() {}
};

View File

@@ -2487,8 +2487,13 @@ LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
if (filename.empty())
{
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
floaterp->getCommitCallbackRegistrar().pushScope();
floaterp->getEnableCallbackRegistrar().pushScope();
// Load from node
floaterp->initFloaterXML(node, parent, factory);
floaterp->getCommitCallbackRegistrar().popScope();
floaterp->getEnableCallbackRegistrar().popScope();
}
else
{

View File

@@ -0,0 +1,682 @@
/**
* @file lllayoutstack.cpp
* @brief LLLayout class - dynamic stacking of UI elements
*
* $LicenseInfo:firstyear=2001&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$
*/
// Opaque view with a background and a border. Can contain LLUICtrls.
#include "linden_common.h"
#include "lllayoutstack.h"
#include "lllocalcliprect.h"
#include "llpanel.h"
#include "llresizebar.h"
#include "lluictrlfactory.h"
#include "llcriticaldamp.h"
#include "boost/foreach.hpp"
static const F32 MIN_FRACTIONAL_SIZE = 0.0f;
static const F32 MAX_FRACTIONAL_SIZE = 1.f;
static const S32 RESIZE_BAR_OVERLAP = 1;
static const S32 RESIZE_BAR_HEIGHT = 3;
//
// LLLayoutPanel
//
LLLayoutPanel::LLLayoutPanel(LLPanel* panelp, LLLayoutStack::eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) :
mPanel(panelp),
mMinWidth(min_width),
mMinHeight(min_height),
mAutoResize(auto_resize),
mUserResize(user_resize),
mCollapsed(FALSE),
mCollapseAmt(0.f),
mVisibleAmt(1.f), // default to fully visible
mResizeBar(NULL),
mOrientation(orientation)
{
LLResizeBar::Side side = (orientation == LLLayoutStack::HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
S32 min_dim;
if (orientation == LLLayoutStack::HORIZONTAL)
{
min_dim = mMinHeight;
}
else
{
min_dim = mMinWidth;
}
LLResizeBar::Params p;
p.name = "resizer";
p.resizing_view = mPanel;
p.min_size = min_dim;
p.max_size = S32_MAX;
p.side = side;
mResizeBar = LLUICtrlFactory::create<LLResizeBar>(p);
mResizeBar->setEnableSnapping(FALSE);
// panels initialized as hidden should not start out partially visible
if (!mPanel->getVisible())
{
mVisibleAmt = 0.f;
}
}
LLLayoutPanel::~LLLayoutPanel()
{
// probably not necessary, but...
delete mResizeBar;
mResizeBar = NULL;
}
F32 LLLayoutPanel::getCollapseFactor()
{
if (mOrientation == LLLayoutStack::HORIZONTAL)
{
F32 collapse_amt =
clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth()));
return mVisibleAmt * collapse_amt;
}
else
{
F32 collapse_amt =
clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight())));
return mVisibleAmt * collapse_amt;
}
}
static LLRegisterWidget<LLLayoutStack> r2("layout_stack");
LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
mOrientation(orientation),
mMinWidth(0),
mMinHeight(0),
mPanelSpacing(RESIZE_BAR_HEIGHT)
{
}
LLLayoutStack::~LLLayoutStack()
{
e_panel_list_t panels = mPanels; // copy list of panel pointers
mPanels.clear(); // clear so that removeChild() calls don't cause trouble
std::for_each(panels.begin(), panels.end(), DeletePointer());
}
void LLLayoutStack::draw()
{
updateLayout();
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
// clip to layout rectangle, not bounding rectangle
LLRect clip_rect = (*panel_it)->mPanel->getRect();
// scale clipping rectangle by visible amount
if (mOrientation == HORIZONTAL)
{
clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
}
else
{
clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
}
LLPanel* panelp = (*panel_it)->mPanel;
LLLocalClipRect clip(clip_rect);
// only force drawing invisible children if visible amount is non-zero
drawChild(panelp, 0, 0, clip_rect.notEmpty());
}
}
void LLLayoutStack::removeChild(LLView* ctrl)
{
LLView::removeChild(ctrl);
LLPanel* panel = dynamic_cast<LLPanel*>(ctrl);
if(!panel)
return;
LLLayoutPanel* embedded_panelp = findEmbeddedPanel(panel);
if (embedded_panelp)
{
mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
delete embedded_panelp;
}
// need to update resizebars
calcMinExtents();
}
LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
{
LLXMLNodePtr node = LLView::getXML();
node->setName(LL_LAYOUT_STACK_TAG);
if (mOrientation == HORIZONTAL)
{
node->createChild("orientation", TRUE)->setStringValue("horizontal");
}
else
{
node->createChild("orientation", TRUE)->setStringValue("vertical");
}
if (save_children)
{
LLView::child_list_const_reverse_iter_t rit;
for (rit = getChildList()->rbegin(); rit != getChildList()->rend(); ++rit)
{
LLView* childp = *rit;
if (childp->getSaveToXML())
{
LLXMLNodePtr xml_node = childp->getXML();
if (xml_node->hasName(LL_PANEL_TAG))
{
xml_node->setName(LL_LAYOUT_PANEL_TAG);
}
node->addChild(xml_node);
}
}
}
return node;
}
//static
LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string orientation_string("vertical");
node->getAttributeString("orientation", orientation_string);
eLayoutOrientation orientation = VERTICAL;
if (orientation_string == "horizontal")
{
orientation = HORIZONTAL;
}
else if (orientation_string == "vertical")
{
orientation = VERTICAL;
}
else
{
llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
}
LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
node->getAttributeS32("border_size", layout_stackp->mPanelSpacing);
// don't allow negative spacing values
layout_stackp->mPanelSpacing = llmax(layout_stackp->mPanelSpacing, 0);
std::string name("stack");
node->getAttributeString("name", name);
layout_stackp->setName(name);
layout_stackp->initFromXML(node, parent);
LLXMLNodePtr child;
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
S32 min_width = 0;
S32 min_height = 0;
BOOL auto_resize = TRUE;
child->getAttributeS32("min_width", min_width);
child->getAttributeS32("min_height", min_height);
child->getAttributeBOOL("auto_resize", auto_resize);
if (child->hasName("layout_panel"))
{
BOOL user_resize = TRUE;
child->getAttributeBOOL("user_resize", user_resize);
LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
if (panelp)
{
panelp->setFollowsNone();
layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
}
}
else
{
BOOL user_resize = FALSE;
child->getAttributeBOOL("user_resize", user_resize);
LLPanel* panelp = new LLPanel(std::string("auto_panel"));
LLView* new_child = factory->createWidget(panelp, child);
if (new_child)
{
// put child in new embedded panel
layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
// resize panel to contain widget and move widget to be contained in panel
panelp->setRect(new_child->getRect());
new_child->setOrigin(0, 0);
}
else
{
panelp->die();
}
}
}
layout_stackp->updateLayout();
return layout_stackp;
}
S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
{
// if we are spanning our children (crude upward propagation of size)
// then don't enforce our size on our children
if (mOrientation == HORIZONTAL)
{
cur_height = llmax(mMinHeight, getRect().getHeight());
}
return cur_height;
}
S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
{
// if we are spanning our children (crude upward propagation of size)
// then don't enforce our size on our children
if (mOrientation == VERTICAL)
{
cur_width = llmax(mMinWidth, getRect().getWidth());
}
return cur_width;
}
void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
{
// panel starts off invisible (collapsed)
if (animate == ANIMATE)
{
panel->setVisible(FALSE);
}
LLLayoutPanel* embedded_panel = new LLLayoutPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
addChild(panel);
addChild(embedded_panel->mResizeBar);
// bring all resize bars to the front so that they are clickable even over the panels
// with a bit of overlap
for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
sendChildToFront(resize_barp);
}
// start expanding panel animation
if (animate == ANIMATE)
{
panel->setVisible(TRUE);
}
}
void LLLayoutStack::removePanel(LLPanel* panel)
{
removeChild(panel);
}
void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
{
LLLayoutPanel* panel_container = findEmbeddedPanel(panel);
if (!panel_container) return;
panel_container->mCollapsed = collapsed;
}
void LLLayoutStack::updateLayout(BOOL force_resize)
{
calcMinExtents();
// calculate current extents
S32 total_width = 0;
S32 total_height = 0;
const F32 ANIM_OPEN_TIME = 0.02f;
const F32 ANIM_CLOSE_TIME = 0.03f;
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLPanel* panelp = (*panel_it)->mPanel;
if (panelp->getVisible())
{
(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
if ((*panel_it)->mVisibleAmt > 0.99f)
{
(*panel_it)->mVisibleAmt = 1.f;
}
}
else // not visible
{
(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
if ((*panel_it)->mVisibleAmt < 0.001f)
{
(*panel_it)->mVisibleAmt = 0.f;
}
}
if ((*panel_it)->mCollapsed)
{
(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
}
else
{
(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
}
if (mOrientation == HORIZONTAL)
{
// enforce minimize size constraint by default
if (panelp->getRect().getWidth() < (*panel_it)->mMinWidth)
{
panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight());
}
total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor());
// want n-1 panel gaps for n panels
if (panel_it != mPanels.begin())
{
total_width += mPanelSpacing;
}
}
else //VERTICAL
{
// enforce minimize size constraint by default
if (panelp->getRect().getHeight() < (*panel_it)->mMinHeight)
{
panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight);
}
total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor());
if (panel_it != mPanels.begin())
{
total_height += mPanelSpacing;
}
}
}
S32 num_resizable_panels = 0;
S32 shrink_headroom_available = 0;
S32 shrink_headroom_total = 0;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
// panels that are not fully visible do not count towards shrink headroom
if ((*panel_it)->getCollapseFactor() < 1.f)
{
continue;
}
// if currently resizing a panel or the panel is flagged as not automatically resizing
// only track total available headroom, but don't use it for automatic resize logic
if ((*panel_it)->mResizeBar->hasMouseCapture()
|| (!(*panel_it)->mAutoResize
&& !force_resize))
{
if (mOrientation == HORIZONTAL)
{
shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
}
else //VERTICAL
{
shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
}
}
else
{
num_resizable_panels++;
if (mOrientation == HORIZONTAL)
{
shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
}
else //VERTICAL
{
shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
}
}
}
// calculate how many pixels need to be distributed among layout panels
// positive means panels need to grow, negative means shrink
S32 pixels_to_distribute;
if (mOrientation == HORIZONTAL)
{
pixels_to_distribute = getRect().getWidth() - total_width;
}
else //VERTICAL
{
pixels_to_distribute = getRect().getHeight() - total_height;
}
// now we distribute the pixels...
S32 cur_x = 0;
S32 cur_y = getRect().getHeight();
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLPanel* panelp = (*panel_it)->mPanel;
S32 cur_width = panelp->getRect().getWidth();
S32 cur_height = panelp->getRect().getHeight();
S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
S32 delta_size = 0;
// if panel can automatically resize (not animating, and resize flag set)...
if ((*panel_it)->getCollapseFactor() == 1.f
&& (force_resize || (*panel_it)->mAutoResize)
&& !(*panel_it)->mResizeBar->hasMouseCapture())
{
if (mOrientation == HORIZONTAL)
{
// if we're shrinking
if (pixels_to_distribute < 0)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available)) : 0;
shrink_headroom_available -= (cur_width - (*panel_it)->mMinWidth);
}
else
{
// grow all elements equally
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
}
else
{
new_width = getDefaultWidth(new_width);
}
if (mOrientation == VERTICAL)
{
if (pixels_to_distribute < 0)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available)) : 0;
shrink_headroom_available -= (cur_height - (*panel_it)->mMinHeight);
}
else
{
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
}
else
{
new_height = getDefaultHeight(new_height);
}
}
else
{
if (mOrientation == HORIZONTAL)
{
new_height = getDefaultHeight(new_height);
}
else // VERTICAL
{
new_width = getDefaultWidth(new_width);
}
}
// adjust running headroom count based on new sizes
shrink_headroom_total += delta_size;
panelp->reshape(new_width, new_height);
panelp->setOrigin(cur_x, cur_y - new_height);
LLRect panel_rect = panelp->getRect();
LLRect resize_bar_rect = panel_rect;
if (mOrientation == HORIZONTAL)
{
resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + RESIZE_BAR_OVERLAP;
}
else
{
resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - RESIZE_BAR_OVERLAP;
}
(*panel_it)->mResizeBar->setRect(resize_bar_rect);
if (mOrientation == HORIZONTAL)
{
cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
}
else //VERTICAL
{
cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
}
}
// update resize bars with new limits
LLResizeBar* last_resize_bar = NULL;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLPanel* panelp = (*panel_it)->mPanel;
if (mOrientation == HORIZONTAL)
{
(*panel_it)->mResizeBar->setResizeLimits(
(*panel_it)->mMinWidth,
(*panel_it)->mMinWidth + shrink_headroom_total);
}
else //VERTICAL
{
(*panel_it)->mResizeBar->setResizeLimits(
(*panel_it)->mMinHeight,
(*panel_it)->mMinHeight + shrink_headroom_total);
}
// toggle resize bars based on panel visibility, resizability, etc
BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
(*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
if (resize_bar_enabled)
{
last_resize_bar = (*panel_it)->mResizeBar;
}
}
// hide last resize bar as there is nothing past it
// resize bars need to be in between two resizable panels
if (last_resize_bar)
{
last_resize_bar->setVisible(FALSE);
}
// not enough room to fit existing contents
if (force_resize == FALSE
// layout did not complete by reaching target position
&& ((mOrientation == VERTICAL && cur_y != -mPanelSpacing)
|| (mOrientation == HORIZONTAL && cur_x != getRect().getWidth() + mPanelSpacing)))
{
// do another layout pass with all stacked elements contributing
// even those that don't usually resize
llassert_always(force_resize == FALSE);
updateLayout(TRUE);
}
} // end LLLayoutStack::updateLayout
LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
{
e_panel_list_t::const_iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
if ((*panel_it)->mPanel == panelp)
{
return *panel_it;
}
}
return NULL;
}
void LLLayoutStack::calcMinExtents()
{
mMinWidth = 0;
mMinHeight = 0;
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
if (mOrientation == HORIZONTAL)
{
mMinHeight = llmax( mMinHeight,
(*panel_it)->mMinHeight);
mMinWidth += (*panel_it)->mMinWidth;
if (panel_it != mPanels.begin())
{
mMinWidth += mPanelSpacing;
}
}
else //VERTICAL
{
mMinWidth = llmax( mMinWidth,
(*panel_it)->mMinWidth);
mMinHeight += (*panel_it)->mMinHeight;
if (panel_it != mPanels.begin())
{
mMinHeight += mPanelSpacing;
}
}
}
}

113
indra/llui/lllayoutstack.h Normal file
View File

@@ -0,0 +1,113 @@
/**
* @file lllayoutstack.h
* @author Richard Nelson
* @brief LLLayout class - dynamic stacking of UI elements
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Reshasearch, 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$
*/
#ifndef LL_LLLAYOUTSTACK_H
#define LL_LLLAYOUTSTACK_H
#include "llpanel.h"
class LLLayoutPanel;
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
{
public:
typedef enum e_layout_orientation
{
HORIZONTAL,
VERTICAL
} eLayoutOrientation;
LLLayoutStack(eLayoutOrientation orientation);
virtual ~LLLayoutStack();
/*virtual*/ void draw();
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void removeChild(LLView* ctrl);
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
S32 getMinWidth() const { return mMinWidth; }
S32 getMinHeight() const { return mMinHeight; }
typedef enum e_animate
{
NO_ANIMATE,
ANIMATE
} EAnimate;
void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
void removePanel(LLPanel* panel);
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
S32 getNumPanels() { return mPanels.size(); }
void updateLayout(BOOL force_resize = FALSE);
S32 getPanelSpacing() const { return mPanelSpacing; }
private:
void calcMinExtents();
S32 getDefaultHeight(S32 cur_height);
S32 getDefaultWidth(S32 cur_width);
const eLayoutOrientation mOrientation;
typedef std::vector<LLLayoutPanel*> e_panel_list_t;
e_panel_list_t mPanels;
LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
S32 mMinWidth;
S32 mMinHeight;
S32 mPanelSpacing;
}; // end class LLLayoutStack
class LLLayoutPanel
{
friend class LLLayoutStack;
friend class LLUICtrlFactory;
friend struct DeletePointer;
LLLayoutPanel(LLPanel* panelp, LLLayoutStack::eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize);
~LLLayoutPanel();
F32 getCollapseFactor();
LLPanel* mPanel;
S32 mMinWidth;
S32 mMinHeight;
bool mAutoResize;
bool mUserResize;
bool mCollapsed;
F32 mVisibleAmt;
F32 mCollapseAmt;
LLLayoutStack::eLayoutOrientation mOrientation;
class LLResizeBar* mResizeBar;
};
#endif //LL_LLLAYOUTSTACK_H

View File

@@ -1562,4 +1562,3 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
s << notification.summarize();
return s;
}

View File

@@ -100,6 +100,7 @@
#include "llinstancetracker.h"
// and we need this to manage the notification callbacks
#include "llavatarname.h"
#include "llevents.h"
#include "llfunctorregistry.h"
#include "llui.h"
@@ -791,7 +792,5 @@ private:
LLNotificationMap mUniqueNotifications;
};
#endif//LL_LLNOTIFICATIONS_H

View File

@@ -62,9 +62,6 @@
#include "llresizebar.h"
#include "llcriticaldamp.h"
const S32 RESIZE_BAR_OVERLAP = 1;
const S32 RESIZE_BAR_HEIGHT = 3;
static LLRegisterWidget<LLPanel> r1("panel");
void LLPanel::init()
@@ -81,6 +78,9 @@ void LLPanel::init()
setTabStop(FALSE);
mVisibleSignal = NULL;
mCommitCallbackRegistrar = false;
mEnableCallbackRegistrar = false;
}
LLPanel::LLPanel()
@@ -459,7 +459,12 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
createRect(node, rect, parent, LLRect());
// create a new panel without a border, by default
panelp = new LLPanel(name, rect, FALSE);
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
panelp->mCommitCallbackRegistrar.pushScope();
panelp->mEnableCallbackRegistrar.pushScope();
panelp->initPanelXML(node, parent, factory);
panelp->mCommitCallbackRegistrar.popScope();
panelp->mEnableCallbackRegistrar.popScope();
// preserve panel's width and height, but override the location
const LLRect& panelrect = panelp->getRect();
S32 w = panelrect.getWidth();
@@ -470,7 +475,14 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
else
{
if(!factory->builtPanel(panelp))
{
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
panelp->mCommitCallbackRegistrar.pushScope();
panelp->mEnableCallbackRegistrar.pushScope();
panelp->initPanelXML(node, parent, factory);
panelp->mCommitCallbackRegistrar.popScope();
panelp->mEnableCallbackRegistrar.popScope();
}
else
{
LLRect new_rect = panelp->getRect();
@@ -1026,651 +1038,3 @@ void LLPanel::storeRectControl()
}
//
// LLLayoutStack
//
struct LLLayoutStack::LLEmbeddedPanel
{
LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) :
mPanel(panelp),
mMinWidth(min_width),
mMinHeight(min_height),
mAutoResize(auto_resize),
mUserResize(user_resize),
mOrientation(orientation),
mCollapsed(FALSE),
mCollapseAmt(0.f),
mVisibleAmt(1.f) // default to fully visible
{
LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
S32 min_dim;
if (orientation == HORIZONTAL)
{
min_dim = mMinHeight;
}
else
{
min_dim = mMinWidth;
}
LLResizeBar::Params p;
p.name = "resizer";
p.resizing_view = mPanel;
p.min_size = min_dim;
p.max_size = S32_MAX;
p.side = side;
mResizeBar = LLUICtrlFactory::create<LLResizeBar>(p);
mResizeBar->setEnableSnapping(FALSE);
// panels initialized as hidden should not start out partially visible
if (!mPanel->getVisible())
{
mVisibleAmt = 0.f;
}
}
~LLEmbeddedPanel()
{
// probably not necessary, but...
delete mResizeBar;
mResizeBar = NULL;
}
F32 getCollapseFactor()
{
if (mOrientation == HORIZONTAL)
{
F32 collapse_amt =
clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth()));
return mVisibleAmt * collapse_amt;
}
else
{
F32 collapse_amt =
clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight())));
return mVisibleAmt * collapse_amt;
}
}
LLPanel* mPanel;
S32 mMinWidth;
S32 mMinHeight;
BOOL mAutoResize;
BOOL mUserResize;
BOOL mCollapsed;
LLResizeBar* mResizeBar;
eLayoutOrientation mOrientation;
F32 mVisibleAmt;
F32 mCollapseAmt;
};
static LLRegisterWidget<LLLayoutStack> r2("layout_stack");
LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
mOrientation(orientation),
mMinWidth(0),
mMinHeight(0),
mPanelSpacing(RESIZE_BAR_HEIGHT)
{
}
LLLayoutStack::~LLLayoutStack()
{
std::for_each(mPanels.begin(), mPanels.end(), DeletePointer());
}
void LLLayoutStack::draw()
{
updateLayout();
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
// clip to layout rectangle, not bounding rectangle
LLRect clip_rect = (*panel_it)->mPanel->getRect();
// scale clipping rectangle by visible amount
if (mOrientation == HORIZONTAL)
{
clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
}
else
{
clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
}
LLPanel* panelp = (*panel_it)->mPanel;
LLLocalClipRect clip(clip_rect);
// only force drawing invisible children if visible amount is non-zero
drawChild(panelp, 0, 0, clip_rect.notEmpty());
}
}
void LLLayoutStack::removeChild(LLView* ctrl)
{
LLView::removeChild(ctrl);
LLPanel* panel = dynamic_cast<LLPanel*>(ctrl);
if(!panel)
return;
LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel(panel);
if (embedded_panelp)
{
mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
delete embedded_panelp;
}
// need to update resizebars
calcMinExtents();
}
LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
{
LLXMLNodePtr node = LLView::getXML();
node->setName(LL_LAYOUT_STACK_TAG);
if (mOrientation == HORIZONTAL)
{
node->createChild("orientation", TRUE)->setStringValue("horizontal");
}
else
{
node->createChild("orientation", TRUE)->setStringValue("vertical");
}
if (save_children)
{
LLView::child_list_const_reverse_iter_t rit;
for (rit = getChildList()->rbegin(); rit != getChildList()->rend(); ++rit)
{
LLView* childp = *rit;
if (childp->getSaveToXML())
{
LLXMLNodePtr xml_node = childp->getXML();
if (xml_node->hasName(LL_PANEL_TAG))
{
xml_node->setName(LL_LAYOUT_PANEL_TAG);
}
node->addChild(xml_node);
}
}
}
return node;
}
//static
LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string orientation_string("vertical");
node->getAttributeString("orientation", orientation_string);
eLayoutOrientation orientation = VERTICAL;
if (orientation_string == "horizontal")
{
orientation = HORIZONTAL;
}
else if (orientation_string == "vertical")
{
orientation = VERTICAL;
}
else
{
llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
}
LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
node->getAttributeS32("border_size", layout_stackp->mPanelSpacing);
// don't allow negative spacing values
layout_stackp->mPanelSpacing = llmax(layout_stackp->mPanelSpacing, 0);
std::string name("stack");
node->getAttributeString("name", name);
layout_stackp->setName(name);
layout_stackp->initFromXML(node, parent);
LLXMLNodePtr child;
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
S32 min_width = 0;
S32 min_height = 0;
BOOL auto_resize = TRUE;
child->getAttributeS32("min_width", min_width);
child->getAttributeS32("min_height", min_height);
child->getAttributeBOOL("auto_resize", auto_resize);
if (child->hasName("layout_panel"))
{
BOOL user_resize = TRUE;
child->getAttributeBOOL("user_resize", user_resize);
LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
if (panelp)
{
panelp->setFollowsNone();
layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
}
}
else
{
BOOL user_resize = FALSE;
child->getAttributeBOOL("user_resize", user_resize);
LLPanel* panelp = new LLPanel(std::string("auto_panel"));
LLView* new_child = factory->createWidget(panelp, child);
if (new_child)
{
// put child in new embedded panel
layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
// resize panel to contain widget and move widget to be contained in panel
panelp->setRect(new_child->getRect());
new_child->setOrigin(0, 0);
}
else
{
panelp->die();
}
}
}
layout_stackp->updateLayout();
return layout_stackp;
}
S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
{
// if we are spanning our children (crude upward propagation of size)
// then don't enforce our size on our children
if (mOrientation == HORIZONTAL)
{
cur_height = llmax(mMinHeight, getRect().getHeight());
}
return cur_height;
}
S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
{
// if we are spanning our children (crude upward propagation of size)
// then don't enforce our size on our children
if (mOrientation == VERTICAL)
{
cur_width = llmax(mMinWidth, getRect().getWidth());
}
return cur_width;
}
void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
{
// panel starts off invisible (collapsed)
if (animate == ANIMATE)
{
panel->setVisible(FALSE);
}
LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
addChild(panel);
addChild(embedded_panel->mResizeBar);
// bring all resize bars to the front so that they are clickable even over the panels
// with a bit of overlap
for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
sendChildToFront(resize_barp);
}
// start expanding panel animation
if (animate == ANIMATE)
{
panel->setVisible(TRUE);
}
}
void LLLayoutStack::removePanel(LLPanel* panel)
{
removeChild(panel);
}
void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
{
LLEmbeddedPanel* panel_container = findEmbeddedPanel(panel);
if (!panel_container) return;
panel_container->mCollapsed = collapsed;
}
void LLLayoutStack::updateLayout(BOOL force_resize)
{
calcMinExtents();
// calculate current extents
S32 total_width = 0;
S32 total_height = 0;
const F32 ANIM_OPEN_TIME = 0.02f;
const F32 ANIM_CLOSE_TIME = 0.03f;
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLPanel* panelp = (*panel_it)->mPanel;
if (panelp->getVisible())
{
(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
if ((*panel_it)->mVisibleAmt > 0.99f)
{
(*panel_it)->mVisibleAmt = 1.f;
}
}
else // not visible
{
(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
if ((*panel_it)->mVisibleAmt < 0.001f)
{
(*panel_it)->mVisibleAmt = 0.f;
}
}
if ((*panel_it)->mCollapsed)
{
(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
}
else
{
(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
}
if (mOrientation == HORIZONTAL)
{
// enforce minimize size constraint by default
if (panelp->getRect().getWidth() < (*panel_it)->mMinWidth)
{
panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight());
}
total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor());
// want n-1 panel gaps for n panels
if (panel_it != mPanels.begin())
{
total_width += mPanelSpacing;
}
}
else //VERTICAL
{
// enforce minimize size constraint by default
if (panelp->getRect().getHeight() < (*panel_it)->mMinHeight)
{
panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight);
}
total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor());
if (panel_it != mPanels.begin())
{
total_height += mPanelSpacing;
}
}
}
S32 num_resizable_panels = 0;
S32 shrink_headroom_available = 0;
S32 shrink_headroom_total = 0;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
// panels that are not fully visible do not count towards shrink headroom
if ((*panel_it)->getCollapseFactor() < 1.f)
{
continue;
}
// if currently resizing a panel or the panel is flagged as not automatically resizing
// only track total available headroom, but don't use it for automatic resize logic
if ((*panel_it)->mResizeBar->hasMouseCapture()
|| (!(*panel_it)->mAutoResize
&& !force_resize))
{
if (mOrientation == HORIZONTAL)
{
shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
}
else //VERTICAL
{
shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
}
}
else
{
num_resizable_panels++;
if (mOrientation == HORIZONTAL)
{
shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
}
else //VERTICAL
{
shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
}
}
}
// calculate how many pixels need to be distributed among layout panels
// positive means panels need to grow, negative means shrink
S32 pixels_to_distribute;
if (mOrientation == HORIZONTAL)
{
pixels_to_distribute = getRect().getWidth() - total_width;
}
else //VERTICAL
{
pixels_to_distribute = getRect().getHeight() - total_height;
}
// now we distribute the pixels...
S32 cur_x = 0;
S32 cur_y = getRect().getHeight();
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLPanel* panelp = (*panel_it)->mPanel;
S32 cur_width = panelp->getRect().getWidth();
S32 cur_height = panelp->getRect().getHeight();
S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
S32 delta_size = 0;
// if panel can automatically resize (not animating, and resize flag set)...
if ((*panel_it)->getCollapseFactor() == 1.f
&& (force_resize || (*panel_it)->mAutoResize)
&& !(*panel_it)->mResizeBar->hasMouseCapture())
{
if (mOrientation == HORIZONTAL)
{
// if we're shrinking
if (pixels_to_distribute < 0)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available)) : 0;
shrink_headroom_available -= (cur_width - (*panel_it)->mMinWidth);
}
else
{
// grow all elements equally
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
}
else
{
new_width = getDefaultWidth(new_width);
}
if (mOrientation == VERTICAL)
{
if (pixels_to_distribute < 0)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available)) : 0;
shrink_headroom_available -= (cur_height - (*panel_it)->mMinHeight);
}
else
{
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
}
else
{
new_height = getDefaultHeight(new_height);
}
}
else
{
if (mOrientation == HORIZONTAL)
{
new_height = getDefaultHeight(new_height);
}
else // VERTICAL
{
new_width = getDefaultWidth(new_width);
}
}
// adjust running headroom count based on new sizes
shrink_headroom_total += delta_size;
panelp->reshape(new_width, new_height);
panelp->setOrigin(cur_x, cur_y - new_height);
LLRect panel_rect = panelp->getRect();
LLRect resize_bar_rect = panel_rect;
if (mOrientation == HORIZONTAL)
{
resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + RESIZE_BAR_OVERLAP;
}
else
{
resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - RESIZE_BAR_OVERLAP;
}
(*panel_it)->mResizeBar->setRect(resize_bar_rect);
if (mOrientation == HORIZONTAL)
{
cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
}
else //VERTICAL
{
cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
}
}
// update resize bars with new limits
LLResizeBar* last_resize_bar = NULL;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
LLPanel* panelp = (*panel_it)->mPanel;
if (mOrientation == HORIZONTAL)
{
(*panel_it)->mResizeBar->setResizeLimits(
(*panel_it)->mMinWidth,
(*panel_it)->mMinWidth + shrink_headroom_total);
}
else //VERTICAL
{
(*panel_it)->mResizeBar->setResizeLimits(
(*panel_it)->mMinHeight,
(*panel_it)->mMinHeight + shrink_headroom_total);
}
// toggle resize bars based on panel visibility, resizability, etc
BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
(*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
if (resize_bar_enabled)
{
last_resize_bar = (*panel_it)->mResizeBar;
}
}
// hide last resize bar as there is nothing past it
// resize bars need to be in between two resizable panels
if (last_resize_bar)
{
last_resize_bar->setVisible(FALSE);
}
// not enough room to fit existing contents
if (force_resize == FALSE
// layout did not complete by reaching target position
&& ((mOrientation == VERTICAL && cur_y != -mPanelSpacing)
|| (mOrientation == HORIZONTAL && cur_x != getRect().getWidth() + mPanelSpacing)))
{
// do another layout pass with all stacked elements contributing
// even those that don't usually resize
llassert_always(force_resize == FALSE);
updateLayout(TRUE);
}
} // end LLLayoutStack::updateLayout
LLLayoutStack::LLEmbeddedPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
{
e_panel_list_t::const_iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
if ((*panel_it)->mPanel == panelp)
{
return *panel_it;
}
}
return NULL;
}
void LLLayoutStack::calcMinExtents()
{
mMinWidth = 0;
mMinHeight = 0;
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
if (mOrientation == HORIZONTAL)
{
mMinHeight = llmax( mMinHeight,
(*panel_it)->mMinHeight);
mMinWidth += (*panel_it)->mMinWidth;
if (panel_it != mPanels.begin())
{
mMinWidth += mPanelSpacing;
}
}
else //VERTICAL
{
mMinWidth = llmax( mMinWidth,
(*panel_it)->mMinWidth);
mMinHeight += (*panel_it)->mMinHeight;
if (panel_it != mPanels.begin())
{
mMinHeight += mPanelSpacing;
}
}
}
}

View File

@@ -140,6 +140,8 @@ public:
const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; }
CommitCallbackRegistry::ScopedRegistrar& getCommitCallbackRegistrar() { return mCommitCallbackRegistrar; }
EnableCallbackRegistry::ScopedRegistrar& getEnableCallbackRegistrar() { return mEnableCallbackRegistrar; }
BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
void initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory);
void setPanelParameters(LLXMLNodePtr node, LLView *parentp);
@@ -226,6 +228,8 @@ protected:
// Override to set not found list
LLButton* getDefaultButton() { return mDefaultBtn; }
LLCallbackMap::map_t mFactoryMap;
CommitCallbackRegistry::ScopedRegistrar mCommitCallbackRegistrar;
EnableCallbackRegistry::ScopedRegistrar mEnableCallbackRegistrar;
commit_signal_t* mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD()
private:
@@ -254,56 +258,4 @@ private:
}; // end class LLPanel
class LLLayoutStack : public LLView
{
public:
typedef enum e_layout_orientation
{
HORIZONTAL,
VERTICAL
} eLayoutOrientation;
LLLayoutStack(eLayoutOrientation orientation);
virtual ~LLLayoutStack();
/*virtual*/ void draw();
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void removeChild(LLView* ctrl);
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
S32 getMinWidth() const { return mMinWidth; }
S32 getMinHeight() const { return mMinHeight; }
typedef enum e_animate
{
NO_ANIMATE,
ANIMATE
} EAnimate;
void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
void removePanel(LLPanel* panel);
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
S32 getNumPanels() { return mPanels.size(); }
private:
struct LLEmbeddedPanel;
void updateLayout(BOOL force_resize = FALSE);
void calcMinExtents();
S32 getDefaultHeight(S32 cur_height);
S32 getDefaultWidth(S32 cur_width);
const eLayoutOrientation mOrientation;
typedef std::vector<LLEmbeddedPanel*> e_panel_list_t;
e_panel_list_t mPanels;
LLEmbeddedPanel* findEmbeddedPanel(LLPanel* panelp) const;
S32 mMinWidth;
S32 mMinHeight;
S32 mPanelSpacing;
}; // end class LLLayoutStack
#endif

View File

@@ -42,6 +42,7 @@
#include "llui.h"
#include "lluictrlfactory.h"
#include "lluiimage.h"
#include "llurlaction.h"
#include "llrect.h"
#include "llfocusmgr.h"
#include "lltimer.h"
@@ -96,10 +97,6 @@ const S32 PREEDIT_STANDOUT_THICKNESS = 2;
LLColor4 LLTextEditor::mLinkColor = LLColor4::blue;
void (* LLTextEditor::mURLcallback)(const std::string&) = NULL;
bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL;
bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL;
///////////////////////////////////////////////////////////////////
@@ -4350,11 +4347,15 @@ void LLTextEditor::loadKeywords(const std::string& filename,
std::string name = utf8str_trim(funcs[i]);
mKeywords.addToken(LLKeywordToken::WORD, name, color, tooltips[i] );
}
segment_list_t segment_list;
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor);
mKeywords.findSegments( &mSegments, mWText, mDefaultColor );
llassert( mSegments.front()->getStart() == 0 );
llassert( mSegments.back()->getEnd() == getLength() );
mSegments.clear();
segment_list_t::iterator insert_it = mSegments.begin();
for (segment_list_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
{
insert_it = mSegments.insert(insert_it, *list_it);
}
}
}
@@ -4493,11 +4494,7 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask)
// and launch it if we did.
if (mParseHTML && mHTML.length() > 0)
{
//Special handling for slurls
if ( (mSecondlifeURLcallback!=NULL) && !(*mSecondlifeURLcallback)(mHTML) )
{
if (mURLcallback!=NULL) (*mURLcallback)(mHTML);
}
LLUrlAction::clickAction(mHTML);
mHTML.clear();
}
}

View File

@@ -258,10 +258,6 @@ public:
// Callbacks
static void setLinkColor(LLColor4 color) { mLinkColor = color; }
static void setURLCallbacks(void (*callback1) (const std::string& 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);
@@ -509,9 +505,6 @@ private:
//
LLKeywords mKeywords;
static LLColor4 mLinkColor;
static void (*mURLcallback) (const std::string& url);
static bool (*mSecondlifeURLcallback) (const std::string& url);
static bool (*mSecondlifeURLcallbackRightClick) (const std::string& url);
// Concrete LLTextCmd sub-classes used by the LLTextEditor base class
class LLTextCmdInsert;

View File

@@ -161,19 +161,15 @@ void LLUI::setMousePositionScreen(S32 x, S32 y)
screen_x = llround((F32)x * getScaleFactor().mV[VX]);
screen_y = llround((F32)y * getScaleFactor().mV[VY]);
LLCoordWindow window_point;
LLView::getWindow()->convertCoords(LLCoordGL(screen_x, screen_y), &window_point);
LLView::getWindow()->setCursorPosition(window_point);
LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert());
}
//static
void LLUI::getMousePositionScreen(S32 *x, S32 *y)
{
LLCoordWindow cursor_pos_window;
LLView::getWindow()->getCursorPosition(&cursor_pos_window);
LLCoordGL cursor_pos_gl;
LLView::getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
getWindow()->getCursorPosition(&cursor_pos_window);
LLCoordGL cursor_pos_gl(cursor_pos_window.convert());
*x = llround((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]);
*y = llround((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]);
}

View File

@@ -32,6 +32,7 @@
#include "llcontrol.h"
#include "llcoord.h"
#include "v2math.h"
#include "llregistry.h"
#include "llrender2dutils.h"
#include "llpointer.h"
#include "lluiimage.h"
@@ -102,6 +103,7 @@ public:
static void glRectToScreen(const LLRect& gl, LLRect *screen);
// Returns the control group containing the control name, or the default group
static LLControlGroup& getControlControlGroup (const std::string& controlname);
static LLWindow* getWindow() { return sWindow; }
static void setHtmlHelp(LLHtmlHelp* html_help);
//

View File

@@ -467,6 +467,37 @@ void LLUICtrl::initFromXML(LLXMLNodePtr node, LLView* parent)
setTabStop(has_tab_stop);
std::string str = node->getName()->mString;
std::string attrib_str;
LLXMLNodePtr child_node;
if(node->getChild((str+".commit_callback").c_str(),child_node,false))
{
if(child_node->getAttributeString("function",attrib_str))
{
commit_callback_t* func = (CommitCallbackRegistry::getValue(attrib_str));
if (func)
{
if(child_node->getAttributeString("parameter",attrib_str))
setCommitCallback(boost::bind((*func), this, LLSD(attrib_str)));
else
setCommitCallback(commit_signal_t::slot_type(*func));
}
}
}
if(node->getChild((str+".validate_callback").c_str(),child_node,false))
{
if(child_node->getAttributeString("function",attrib_str))
{
enable_callback_t* func = (EnableCallbackRegistry::getValue(attrib_str));
if (func)
{
if(child_node->getAttributeString("parameter",attrib_str))
setCommitCallback(boost::bind((*func), this, LLSD(attrib_str)));
else
setCommitCallback(commit_signal_t::slot_type(*func));
}
}
}
LLView::initFromXML(node, parent);
}

View File

@@ -40,6 +40,7 @@
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include "llinitparam.h"
#include "llviewmodel.h" // *TODO move dependency to .cpp file
class LLUICtrl
@@ -48,6 +49,7 @@ class LLUICtrl
public:
typedef boost::function<void (LLUICtrl* ctrl, const LLSD& param)> commit_callback_t;
typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> commit_signal_t;
typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t;
typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t;
typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata);
@@ -149,6 +151,13 @@ public:
}
};
template <typename F, typename DERIVED> class CallbackRegistry : public LLRegistrySingleton<std::string, F, DERIVED >
{};
class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{};
// the enable callback registry is also used for visiblity callbacks
class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{};
protected:
commit_signal_t* mCommitSignal;

View File

@@ -285,8 +285,12 @@ void LLUICtrlFactory::buildFloaterInternal(LLFloater *floaterp, LLXMLNodePtr &ro
mFactoryStack.push_front(factory_map);
}
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
floaterp->getCommitCallbackRegistrar().pushScope();
floaterp->getEnableCallbackRegistrar().pushScope();
floaterp->initFloaterXML(root, NULL, this, open); /* Flawfinder: ignore */
floaterp->getCommitCallbackRegistrar().popScope();
floaterp->getEnableCallbackRegistrar().popScope();
if (LLUI::sShowXUINames)
{
floaterp->setToolTip(filename);
@@ -381,8 +385,13 @@ BOOL LLUICtrlFactory::buildPanelInternal(LLPanel* panelp, LLXMLNodePtr &root, co
mFactoryStack.push_front(factory_map);
}
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
panelp->getCommitCallbackRegistrar().pushScope();
panelp->getEnableCallbackRegistrar().pushScope();
didPost = panelp->initPanelXML(root, NULL, this);
panelp->getCommitCallbackRegistrar().popScope();
panelp->getEnableCallbackRegistrar().popScope();
if (LLUI::sShowXUINames)
{
panelp->setToolTip(filename);

159
indra/llui/llurlaction.cpp Normal file
View File

@@ -0,0 +1,159 @@
/**
* @file llurlaction.cpp
* @author Martin Reddy
* @brief A set of actions that can performed on Urls
*
* $LicenseInfo:firstyear=2009&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 "linden_common.h"
#include "llurlaction.h"
#include "llview.h"
#include "llwindow.h"
#include "llurlregistry.h"
// global state for the callback functions
LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback;
LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback;
LLUrlAction::url_callback_t LLUrlAction::sOpenURLExternalCallback;
LLUrlAction::execute_url_callback_t LLUrlAction::sExecuteSLURLCallback;
void LLUrlAction::setOpenURLCallback(url_callback_t cb)
{
sOpenURLCallback = cb;
}
void LLUrlAction::setOpenURLInternalCallback(url_callback_t cb)
{
sOpenURLInternalCallback = cb;
}
void LLUrlAction::setOpenURLExternalCallback(url_callback_t cb)
{
sOpenURLExternalCallback = cb;
}
void LLUrlAction::setExecuteSLURLCallback(execute_url_callback_t cb)
{
sExecuteSLURLCallback = cb;
}
void LLUrlAction::openURL(std::string url)
{
if (sOpenURLCallback)
{
sOpenURLCallback(url);
}
}
void LLUrlAction::openURLInternal(std::string url)
{
if (sOpenURLInternalCallback)
{
sOpenURLInternalCallback(url);
}
}
void LLUrlAction::openURLExternal(std::string url)
{
if (sOpenURLExternalCallback)
{
sOpenURLExternalCallback(url);
}
}
void LLUrlAction::executeSLURL(std::string url)
{
if (sExecuteSLURLCallback)
{
sExecuteSLURLCallback(url);
}
}
void LLUrlAction::clickAction(std::string url)
{
// Try to handle as SLURL first, then http Url
if ( (sExecuteSLURLCallback) && !sExecuteSLURLCallback(url) )
{
if (sOpenURLCallback)
{
sOpenURLCallback(url);
}
}
}
void LLUrlAction::teleportToLocation(std::string url)
{
LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
if (! match.getLocation().empty())
{
executeSLURL("secondlife:///app/teleport/" + match.getLocation());
}
}
}
void LLUrlAction::showLocationOnMap(std::string url)
{
LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
if (! match.getLocation().empty())
{
executeSLURL("secondlife:///app/worldmap/" + match.getLocation());
}
}
}
void LLUrlAction::copyURLToClipboard(std::string url)
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url));
}
void LLUrlAction::copyLabelToClipboard(std::string url)
{
LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(match.getLabel()));
}
}
void LLUrlAction::showProfile(std::string url)
{
// Get id from 'secondlife:///app/{cmd}/{id}/{action}'
// and show its profile
LLURI uri(url);
LLSD path_array = uri.pathArray();
if (path_array.size() == 4)
{
std::string id_str = path_array.get(2).asString();
if (LLUUID::validate(id_str))
{
std::string cmd_str = path_array.get(1).asString();
executeSLURL("secondlife:///app/" + cmd_str + "/" + id_str + "/about");
}
}
}

98
indra/llui/llurlaction.h Normal file
View File

@@ -0,0 +1,98 @@
/**
* @file llurlaction.h
* @author Martin Reddy
* @brief A set of actions that can performed on Urls
*
* $LicenseInfo:firstyear=2009&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$
*/
#ifndef LL_LLURLACTION_H
#define LL_LLURLACTION_H
#include <string>
#include <boost/function.hpp>
///
/// The LLUrlAction class provides a number of static functions that
/// let you open Urls in web browsers, execute SLURLs, and copy Urls
/// to the clipboard. Many of these functions are not available at
/// the llui level, and must be supplied via a set of callbacks.
///
/// N.B. The action functions specifically do not use const ref
/// strings so that a url parameter can be used into a boost::bind()
/// call under situations when that input string is deallocated before
/// the callback is executed.
///
class LLUrlAction
{
public:
LLUrlAction();
/// load a Url in the user's preferred web browser
static void openURL(std::string url);
/// load a Url in the internal Second Life web browser
static void openURLInternal(std::string url);
/// load a Url in the operating system's default web browser
static void openURLExternal(std::string url);
/// execute the given secondlife: SLURL
static void executeSLURL(std::string url);
/// if the Url specifies an SL location, teleport there
static void teleportToLocation(std::string url);
/// if the Url specifies an SL location, show it on a map
static void showLocationOnMap(std::string url);
/// perform the appropriate action for left-clicking on a Url
static void clickAction(std::string url);
/// copy the label for a Url to the clipboard
static void copyLabelToClipboard(std::string url);
/// copy a Url to the clipboard
static void copyURLToClipboard(std::string url);
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url);
/// specify the callbacks to enable this class's functionality
typedef boost::function<void (const std::string&)> url_callback_t;
typedef boost::function<bool(const std::string& url)> execute_url_callback_t;
static void setOpenURLCallback(url_callback_t cb);
static void setOpenURLInternalCallback(url_callback_t cb);
static void setOpenURLExternalCallback(url_callback_t cb);
static void setExecuteSLURLCallback(execute_url_callback_t cb);
private:
// callbacks for operations we can perform on Urls
static url_callback_t sOpenURLCallback;
static url_callback_t sOpenURLInternalCallback;
static url_callback_t sOpenURLExternalCallback;
static execute_url_callback_t sExecuteSLURLCallback;
};
#endif

1188
indra/llui/llurlentry.cpp Normal file

File diff suppressed because it is too large Load Diff

429
indra/llui/llurlentry.h Normal file
View File

@@ -0,0 +1,429 @@
/**
* @file llurlentry.h
* @author Martin Reddy
* @brief Describes the Url types that can be registered in LLUrlRegistry
*
* $LicenseInfo:firstyear=2009&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$
*/
#ifndef LL_LLURLENTRY_H
#define LL_LLURLENTRY_H
#include "lluuid.h"
#include "lluicolor.h"
#include "llstyle.h"
#include "llhost.h" // for resolving parcel name by parcel id
#include <boost/signals2.hpp>
#include <boost/regex.hpp>
#include <string>
#include <map>
class LLAvatarName;
typedef boost::signals2::signal<void (const std::string& url,
const std::string& label,
const std::string& icon)> LLUrlLabelSignal;
typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
///
/// LLUrlEntryBase is the base class of all Url types registered in the
/// LLUrlRegistry. Each derived classes provides a regular expression
/// to match the Url type (e.g., http://... or secondlife://...) along
/// with an optional icon to display next to instances of the Url in
/// a text display and a XUI file to use for any context menu popup.
/// Functions are also provided to compute an appropriate label and
/// tooltip/status bar text for the Url.
///
/// Some derived classes of LLUrlEntryBase may wish to compute an
/// appropriate label for a Url by asking the server for information.
/// You must therefore provide a callback method, so that you can be
/// notified when an updated label has been received from the server.
/// This label should then be used to replace any previous label
/// that you received from getLabel() for the Url in question.
///
class LLUrlEntryBase
{
public:
LLUrlEntryBase();
virtual ~LLUrlEntryBase();
/// Return the regex pattern that matches this Url
boost::regex getPattern() const { return mPattern; }
/// Return the url from a string that matched the regex
virtual std::string getUrl(const std::string &string) const;
/// Given a matched Url, return a label for the Url
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
/// Return an icon that can be displayed next to Urls of this type
virtual std::string getIcon(const std::string &url);
/// Return the style to render the displayed text
//virtual LLStyle::Params getStyle() const;
/// Given a matched Url, return a tooltip string for the hyperlink
virtual std::string getTooltip(const std::string &string) const { return mTooltip; }
/// Return the name of a XUI file containing the context menu items
std::string getMenuName() const { return mMenuName; }
/// Return the name of a SL location described by this Url, if any
virtual std::string getLocation(const std::string &url) const { return ""; }
/// Should this link text be underlined only when mouse is hovered over it?
virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
bool isLinkDisabled() const;
protected:
std::string getIDStringFromUrl(const std::string &url) const;
std::string escapeUrl(const std::string &url) const;
std::string unescapeUrl(const std::string &url) const;
std::string getLabelFromWikiLink(const std::string &url) const;
std::string getUrlFromWikiLink(const std::string &string) const;
void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
virtual void callObservers(const std::string &id, const std::string &label, const std::string& icon);
typedef struct {
std::string url;
LLUrlLabelSignal *signal;
} LLUrlEntryObserver;
boost::regex mPattern;
std::string mIcon;
std::string mMenuName;
std::string mTooltip;
std::multimap<std::string, LLUrlEntryObserver> mObservers;
};
///
/// LLUrlEntryHTTP Describes generic http: and https: Urls
///
class LLUrlEntryHTTP : public LLUrlEntryBase
{
public:
LLUrlEntryHTTP();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
};
///
/// LLUrlEntryHTTPLabel Describes generic http: and https: Urls with custom labels
///
class LLUrlEntryHTTPLabel : public LLUrlEntryBase
{
public:
LLUrlEntryHTTPLabel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getTooltip(const std::string &string) const;
/*virtual*/ std::string getUrl(const std::string &string) const;
};
///
/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
///
class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase
{
public:
LLUrlEntryHTTPNoProtocol();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
};
///
/// LLUrlEntrySLURL Describes http://slurl.com/... Urls
///
class LLUrlEntrySLURL : public LLUrlEntryBase
{
public:
LLUrlEntrySLURL();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getLocation(const std::string &url) const;
};
///
/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
class LLUrlEntryAgent : public LLUrlEntryBase
{
public:
LLUrlEntryAgent();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getIcon(const std::string &url);
/*virtual*/ std::string getTooltip(const std::string &string) const;
//*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
protected:
/*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
private:
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
};
///
/// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
/// that displays various forms of user name
/// This is a base class for the various implementations of name display
class LLUrlEntryAgentName : public LLUrlEntryBase, public boost::signals2::trackable
{
public:
LLUrlEntryAgentName();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
//*virtual*/ LLStyle::Params getStyle() const;
protected:
// override this to pull out relevant name fields
virtual std::string getName(const LLAvatarName& avatar_name) = 0;
private:
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
};
///
/// LLUrlEntryAgentCompleteName Describes a Second Life agent name Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
/// that displays the full display name + user name for an avatar
/// such as "James Linden (james.linden)"
class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName
{
public:
LLUrlEntryAgentCompleteName();
private:
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
/// LLUrlEntryAgentDisplayName Describes a Second Life agent display name Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
/// that displays the just the display name for an avatar
/// such as "James Linden"
class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName
{
public:
LLUrlEntryAgentDisplayName();
private:
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
/// LLUrlEntryAgentUserName Describes a Second Life agent username Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
/// that displays the just the display name for an avatar
/// such as "james.linden"
class LLUrlEntryAgentUserName : public LLUrlEntryAgentName
{
public:
LLUrlEntryAgentUserName();
private:
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
/// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
/// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
///
class LLUrlEntryGroup : public LLUrlEntryBase
{
public:
LLUrlEntryGroup();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
//*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
private:
void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group);
};
///
/// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
/// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
///
class LLUrlEntryInventory : public LLUrlEntryBase
{
public:
LLUrlEntryInventory();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
private:
};
///
/// LLUrlEntryObjectIM Describes a Second Life inspector for the object Url, e.g.,
/// secondlife:///app/objectim/7bcd7864-da6b-e43f-4486-91d28a28d95b?name=Object&owner=3de548e1-57be-cfea-2b78-83ae3ad95998&slurl=Danger!%20Danger!/200/200/30/&groupowned=1
///
class LLUrlEntryObjectIM : public LLUrlEntryBase
{
public:
LLUrlEntryObjectIM();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getLocation(const std::string &url) const;
private:
};
///
/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
///
class LLUrlEntryParcel : public LLUrlEntryBase
{
public:
struct LLParcelData
{
LLUUID parcel_id;
std::string name;
std::string sim_name;
F32 global_x;
F32 global_y;
F32 global_z;
};
LLUrlEntryParcel();
~LLUrlEntryParcel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
// Sends a parcel info request to sim.
void sendParcelInfoRequest(const LLUUID& parcel_id);
// Calls observers of certain parcel id providing them with parcel label.
void onParcelInfoReceived(const std::string &id, const std::string &label);
// Processes parcel label and triggers notifying observers.
static void processParcelInfo(const LLParcelData& parcel_data);
// Next 4 setters are used to update agent and viewer connection information
// upon events like user login, viewer disconnect and user changing region host.
// These setters are made public to be accessible from newview and should not be
// used in other cases.
static void setAgentID(const LLUUID& id) { sAgentID = id; }
static void setSessionID(const LLUUID& id) { sSessionID = id; }
static void setRegionHost(const LLHost& host) { sRegionHost = host; }
static void setDisconnected(bool disconnected) { sDisconnected = disconnected; }
private:
static LLUUID sAgentID;
static LLUUID sSessionID;
static LLHost sRegionHost;
static bool sDisconnected;
static std::set<LLUrlEntryParcel*> sParcelInfoObservers;
};
///
/// LLUrlEntryPlace Describes a Second Life location Url, e.g.,
/// secondlife://Ahern/50/50/50
///
class LLUrlEntryPlace : public LLUrlEntryBase
{
public:
LLUrlEntryPlace();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getLocation(const std::string &url) const;
};
///
/// LLUrlEntryRegion Describes a Second Life location Url, e.g.,
/// secondlife:///app/region/Ahern/128/128/0
///
class LLUrlEntryRegion : public LLUrlEntryBase
{
public:
LLUrlEntryRegion();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getLocation(const std::string &url) const;
};
///
/// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
/// secondlife:///app/teleport/Ahern/50/50/50/
///
class LLUrlEntryTeleport : public LLUrlEntryBase
{
public:
LLUrlEntryTeleport();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getLocation(const std::string &url) const;
};
///
/// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
/// with secondlife:// (used as a catch-all for cases not matched above)
///
class LLUrlEntrySL : public LLUrlEntryBase
{
public:
LLUrlEntrySL();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
};
///
/// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts
/// with secondlife:// with the ability to specify a custom label.
///
class LLUrlEntrySLLabel : public LLUrlEntryBase
{
public:
LLUrlEntrySLLabel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ std::string getTooltip(const std::string &string) const;
/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
};
///
/// LLUrlEntryWorldMap Describes a Second Life worldmap Url, e.g.,
/// secondlife:///app/worldmap/Ahern/50/50/50
///
class LLUrlEntryWorldMap : public LLUrlEntryBase
{
public:
LLUrlEntryWorldMap();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getLocation(const std::string &url) const;
};
///
/// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags
///
class LLUrlEntryNoLink : public LLUrlEntryBase
{
public:
LLUrlEntryNoLink();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
//*virtual*/ LLStyle::Params getStyle() const;
};
///
/// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
///
class LLUrlEntryIcon : public LLUrlEntryBase
{
public:
LLUrlEntryIcon();
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getIcon(const std::string &url);
};
#endif

62
indra/llui/llurlmatch.cpp Normal file
View File

@@ -0,0 +1,62 @@
/**
* @file llurlmatch.cpp
* @author Martin Reddy
* @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
*
* $LicenseInfo:firstyear=2009&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 "linden_common.h"
#include "llurlmatch.h"
LLUrlMatch::LLUrlMatch() :
mStart(0),
mEnd(0),
mUrl(""),
mLabel(""),
mTooltip(""),
mIcon(""),
mMenuName(""),
mLocation(""),
mUnderlineOnHoverOnly(false)
{
}
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, /*const LLStyle::Params& style,*/
const std::string &menu, const std::string &location,
const LLUUID& id, bool underline_on_hover_only)
{
mStart = start;
mEnd = end;
mUrl = url;
mLabel = label;
mTooltip = tooltip;
mIcon = icon;
//mStyle = style;
//mStyle.link_href = url;
mMenuName = menu;
mLocation = location;
mID = id;
mUnderlineOnHoverOnly = underline_on_hover_only;
}

105
indra/llui/llurlmatch.h Normal file
View File

@@ -0,0 +1,105 @@
/**
* @file llurlmatch.h
* @author Martin Reddy
* @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
*
* $LicenseInfo:firstyear=2009&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$
*/
#ifndef LL_LLURLMATCH_H
#define LL_LLURLMATCH_H
//#include "linden_common.h"
#include <string>
#include <vector>
#include "llstyle.h"
///
/// LLUrlMatch describes a single Url that was matched within a string by
/// the LLUrlRegistry::findUrl() method. It includes the actual Url that
/// was matched along with its first/last character offset in the string.
/// An alternate label is also provided for creating a hyperlink, as well
/// as tooltip/status text, an icon, and a XUI file for a context menu
/// that can be used in a popup for a Url (e.g., Open, Copy URL, etc.)
///
class LLUrlMatch
{
public:
LLUrlMatch();
/// return true if this object does not contain a valid Url match yet
bool empty() const { return mUrl.empty(); }
/// return the offset in the string for the first character of the Url
U32 getStart() const { return mStart; }
/// return the offset in the string for the last character of the Url
U32 getEnd() const { return mEnd; }
/// return the Url that has been matched in the input string
std::string getUrl() const { return mUrl; }
/// return a label that can be used for the display of this Url
std::string getLabel() const { return mLabel; }
/// return a message that could be displayed in a tooltip or status bar
std::string getTooltip() const { return mTooltip; }
/// return the filename for an icon that can be displayed next to this Url
std::string getIcon() const { return mIcon; }
/// Return the color to render the displayed text
//LLStyle::Params getStyle() const { return mStyle; }
/// Return the name of a XUI file containing the context menu items
std::string getMenuName() const { return mMenuName; }
/// return the SL location that this Url describes, or "" if none.
std::string getLocation() const { return mLocation; }
/// Should this link text be underlined only when mouse is hovered over it?
bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
/*const LLStyle::Params& style, */const std::string &menu,
const std::string &location, const LLUUID& id,
bool underline_on_hover_only = false );
const LLUUID& getID() const { return mID; }
private:
U32 mStart;
U32 mEnd;
std::string mUrl;
std::string mLabel;
std::string mTooltip;
std::string mIcon;
std::string mMenuName;
std::string mLocation;
LLUUID mID;
//LLStyle::Params mStyle;
bool mUnderlineOnHoverOnly;
};
#endif

View File

@@ -0,0 +1,263 @@
/**
* @file llurlregistry.cpp
* @author Martin Reddy
* @brief Contains a set of Url types that can be matched in a string
*
* $LicenseInfo:firstyear=2009&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 "linden_common.h"
#include "llurlregistry.h"
#include <boost/regex.hpp>
// default dummy callback that ignores any label updates from the server
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
{
}
LLUrlRegistry::LLUrlRegistry()
{
mUrlEntry.reserve(20);
// Urls are matched in the order that they were registered
registerUrl(new LLUrlEntryNoLink());
registerUrl(new LLUrlEntryIcon());
registerUrl(new LLUrlEntrySLURL());
registerUrl(new LLUrlEntryHTTP());
registerUrl(new LLUrlEntryHTTPLabel());
registerUrl(new LLUrlEntryAgentCompleteName());
registerUrl(new LLUrlEntryAgentDisplayName());
registerUrl(new LLUrlEntryAgentUserName());
// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
// LLUrlEntryAgent is a less specific (catchall for agent urls)
registerUrl(new LLUrlEntryAgent());
registerUrl(new LLUrlEntryGroup());
registerUrl(new LLUrlEntryParcel());
registerUrl(new LLUrlEntryTeleport());
registerUrl(new LLUrlEntryRegion());
registerUrl(new LLUrlEntryWorldMap());
registerUrl(new LLUrlEntryObjectIM());
registerUrl(new LLUrlEntryPlace());
registerUrl(new LLUrlEntryInventory());
registerUrl(new LLUrlEntryObjectIM());
//LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern,
//so it should be registered in the end of list
registerUrl(new LLUrlEntrySL());
registerUrl(new LLUrlEntrySLLabel());
// most common pattern is a URL without any protocol,
// e.g., "secondlife.com"
registerUrl(new LLUrlEntryHTTPNoProtocol());
}
LLUrlRegistry::~LLUrlRegistry()
{
// free all of the LLUrlEntryBase objects we are holding
std::vector<LLUrlEntryBase *>::iterator it;
for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
{
delete *it;
}
}
void LLUrlRegistry::registerUrl(LLUrlEntryBase *url, bool force_front)
{
if (url)
{
if (force_front) // IDEVO
mUrlEntry.insert(mUrlEntry.begin(), url);
else
mUrlEntry.push_back(url);
}
}
static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &end)
{
boost::cmatch result;
bool found;
// regex_search can potentially throw an exception, so check for it
try
{
found = boost::regex_search(text, result, regex);
}
catch (std::runtime_error &)
{
return false;
}
if (! found)
{
return false;
}
// return the first/last character offset for the matched substring
start = static_cast<U32>(result[0].first - text);
end = static_cast<U32>(result[0].second - text) - 1;
// we allow certain punctuation to terminate a Url but not match it,
// e.g., "http://foo.com/." should just match "http://foo.com/"
if (text[end] == '.' || text[end] == ',')
{
end--;
}
// ignore a terminating ')' when Url contains no matching '('
// see DEV-19842 for details
else if (text[end] == ')' && std::string(text+start, end-start).find('(') == std::string::npos)
{
end--;
}
return true;
}
static bool stringHasUrl(const std::string &text)
{
// fast heuristic test for a URL in a string. This is used
// to avoid lots of costly regex calls, BUT it needs to be
// kept in sync with the LLUrlEntry regexes we support.
return (text.find("://") != std::string::npos ||
text.find("www.") != std::string::npos ||
text.find(".com") != std::string::npos ||
text.find(".net") != std::string::npos ||
text.find(".edu") != std::string::npos ||
text.find(".org") != std::string::npos ||
text.find("<nolink>") != std::string::npos ||
text.find("<icon") != std::string::npos);
}
bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
{
// avoid costly regexes if there is clearly no URL in the text
if (! stringHasUrl(text))
{
return false;
}
// find the first matching regex from all url entries in the registry
U32 match_start = 0, match_end = 0;
LLUrlEntryBase *match_entry = NULL;
std::vector<LLUrlEntryBase *>::iterator it;
for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
{
LLUrlEntryBase *url_entry = *it;
U32 start = 0, end = 0;
if (matchRegex(text.c_str(), url_entry->getPattern(), start, end))
{
// does this match occur in the string before any other match
if (start < match_start || match_entry == NULL)
{
match_start = start;
match_end = end;
match_entry = url_entry;
}
}
}
// did we find a match? if so, return its details in the match object
if (match_entry)
{
// fill in the LLUrlMatch object and return it
std::string url = text.substr(match_start, match_end - match_start + 1);
match.setValues(match_start, match_end,
match_entry->getUrl(url),
match_entry->getLabel(url, cb),
match_entry->getTooltip(url),
match_entry->getIcon(url),
//match_entry->getStyle(),
match_entry->getMenuName(),
match_entry->getLocation(url),
match_entry->getID(url),
match_entry->underlineOnHoverOnly(url));
return true;
}
return false;
}
bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
{
// boost::regex_search() only works on char or wchar_t
// types, but wchar_t is only 2-bytes on Win32 (not 4).
// So we use UTF-8 to make this work the same everywhere.
std::string utf8_text = wstring_to_utf8str(text);
if (findUrl(utf8_text, match, cb))
{
// we cannot blindly return the start/end offsets from
// the UTF-8 string because it is a variable-length
// character encoding, so we need to update the start
// and end values to be correct for the wide string.
LLWString wurl = utf8str_to_wstring(match.getUrl());
S32 start = text.find(wurl);
if (start == std::string::npos)
{
return false;
}
S32 end = start + wurl.size() - 1;
match.setValues(start, end, match.getUrl(),
match.getLabel(),
match.getTooltip(),
match.getIcon(),
//match.getStyle(),
match.getMenuName(),
match.getLocation(),
match.getID(),
match.underlineOnHoverOnly());
return true;
}
return false;
}
bool LLUrlRegistry::hasUrl(const std::string &text)
{
LLUrlMatch match;
return findUrl(text, match);
}
bool LLUrlRegistry::hasUrl(const LLWString &text)
{
LLUrlMatch match;
return findUrl(text, match);
}
bool LLUrlRegistry::isUrl(const std::string &text)
{
LLUrlMatch match;
if (findUrl(text, match))
{
return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
}
return false;
}
bool LLUrlRegistry::isUrl(const LLWString &text)
{
LLUrlMatch match;
if (findUrl(text, match))
{
return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
}
return false;
}

View File

@@ -0,0 +1,97 @@
/**
* @file llurlregistry.h
* @author Martin Reddy
* @brief Contains a set of Url types that can be matched in a string
*
* $LicenseInfo:firstyear=2009&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$
*/
#ifndef LL_LLURLREGISTRY_H
#define LL_LLURLREGISTRY_H
#include "llurlentry.h"
#include "llurlmatch.h"
#include "llsingleton.h"
#include "llstring.h"
#include <string>
#include <vector>
/// This default callback for findUrl() simply ignores any label updates
void LLUrlRegistryNullCallback(const std::string &url,
const std::string &label,
const std::string &icon);
///
/// LLUrlRegistry is a singleton that contains a set of Url types that
/// can be matched in string. E.g., http:// or secondlife:// Urls.
///
/// Clients call the findUrl() method on a string to locate the first
/// occurence of a supported Urls in that string. If findUrl() returns
/// true, the LLUrlMatch object will be updated to describe the Url
/// that was matched, including a label that can be used to hyperlink
/// the Url, an icon to display next to the Url, and a XUI menu that
/// can be used as a popup context menu for that Url.
///
/// New Url types can be added to the registry with the registerUrl
/// method. E.g., to add support for a new secondlife:///app/ Url.
///
/// Computing the label for a Url could involve a roundtrip request
/// to the server (e.g., to find the actual agent or group name).
/// As such, you can provide a callback method that will get invoked
/// when a new label is available for one of your matched Urls.
///
class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
{
public:
~LLUrlRegistry();
/// add a new Url handler to the registry (will be freed on destruction)
/// optionally force it to the front of the list, making it take
/// priority over other regular expression matches for URLs
void registerUrl(LLUrlEntryBase *url, bool force_front = false);
/// get the next Url in an input string, starting at a given character offset
/// your callback is invoked if the matched Url's label changes in the future
bool findUrl(const std::string &text, LLUrlMatch &match,
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
/// a slightly less efficient version of findUrl for wide strings
bool findUrl(const LLWString &text, LLUrlMatch &match,
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
// return true if the given string contains a URL that findUrl would match
bool hasUrl(const std::string &text);
bool hasUrl(const LLWString &text);
// return true if the given string is a URL that findUrl would match
bool isUrl(const std::string &text);
bool isUrl(const LLWString &text);
private:
LLUrlRegistry();
friend class LLSingleton<LLUrlRegistry>;
std::vector<LLUrlEntryBase *> mUrlEntry;
};
#endif

View File

@@ -332,15 +332,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
break;
case LL_PATH_APP_SETTINGS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "app_settings";
prefix = add(getAppRODataDir(), "app_settings");
break;
case LL_PATH_CHARACTER:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "character";
prefix = add(getAppRODataDir(), "character");
break;
case LL_PATH_HELP:
@@ -352,9 +348,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
break;
case LL_PATH_USER_SETTINGS:
prefix = getOSUserAppDir();
prefix += mDirDelimiter;
prefix += "user_settings";
prefix = add(getOSUserAppDir(), "user_settings");
break;
case LL_PATH_PER_SL_ACCOUNT:
@@ -370,9 +364,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
break;
case LL_PATH_LOGS:
prefix = getOSUserAppDir();
prefix += mDirDelimiter;
prefix += "logs";
prefix = add(getOSUserAppDir(), "logs");
break;
case LL_PATH_TEMP:
@@ -396,9 +388,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
break;
case LL_PATH_LOCAL_ASSETS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "local_assets";
prefix = add(getAppRODataDir(), "local_assets");
break;
case LL_PATH_EXECUTABLE:
@@ -406,9 +396,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
break;
case LL_PATH_FONTS:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "fonts";
prefix = add(getAppRODataDir(), "fonts");
break;
default:
@@ -418,12 +406,12 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
std::string filename = in_filename;
if (!subdir2.empty())
{
filename = subdir2 + mDirDelimiter + filename;
filename = add(subdir2, filename);
}
if (!subdir1.empty())
{
filename = subdir1 + mDirDelimiter + filename;
filename = add(subdir1, filename);
}
if (prefix.empty())
@@ -436,9 +424,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
{
if (!prefix.empty())
{
expanded_filename += prefix;
expanded_filename += mDirDelimiter;
expanded_filename += filename;
expanded_filename = add(prefix, filename);
}
else
{
@@ -530,12 +516,7 @@ std::string LLDir::getTempFilename() const
random_uuid.generate();
random_uuid.toString(uuid_str);
std::string temp_filename = getTempDir();
temp_filename += mDirDelimiter;
temp_filename += uuid_str;
temp_filename += ".tmp";
return temp_filename;
return add(getTempDir(), uuid_str + ".tmp");
}
// static
@@ -572,15 +553,9 @@ void LLDir::setLindenUserDir(const std::string &grid, const std::string &first,
{
// some platforms have case-sensitive filesystems, so be
// utterly consistent with our firstname/lastname case.
std::string firstlower(first);
LLStringUtil::toLower(firstlower);
std::string lastlower(last);
LLStringUtil::toLower(lastlower);
mLindenUserDir = getOSUserAppDir();
mLindenUserDir += mDirDelimiter;
mLindenUserDir += firstlower;
mLindenUserDir += "_";
mLindenUserDir += lastlower;
std::string userlower(first+"_"+last);
LLStringUtil::toLower(userlower);
mLindenUserDir = add(getOSUserAppDir(), userlower);
if (!grid.empty())
{
@@ -617,16 +592,9 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string
{
// some platforms have case-sensitive filesystems, so be
// utterly consistent with our firstname/lastname case.
std::string firstlower(first);
LLStringUtil::toLower(firstlower);
std::string lastlower(last);
LLStringUtil::toLower(lastlower);
mPerAccountChatLogsDir = getChatLogsDir();
mPerAccountChatLogsDir += mDirDelimiter;
mPerAccountChatLogsDir += firstlower;
mPerAccountChatLogsDir += "_";
mPerAccountChatLogsDir += lastlower;
std::string userlower(first+"_"+last);
LLStringUtil::toLower(userlower);
mPerAccountChatLogsDir = add(getChatLogsDir(), userlower);
if (!grid.empty())
{
std::string gridlower(grid);
@@ -644,22 +612,18 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string
void LLDir::setSkinFolder(const std::string &skin_folder)
{
mSkinDir = getSkinBaseDir();
mSkinDir += mDirDelimiter;
mSkinDir += skin_folder;
append(mSkinDir, skin_folder);
// user modifications to current skin
// e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
mUserSkinDir = getOSUserAppDir();
mUserSkinDir += mDirDelimiter;
mUserSkinDir += "skins_sg1";
mUserSkinDir += mDirDelimiter;
mUserSkinDir += skin_folder;
append(mUserSkinDir, "skins_sg1");
append(mUserSkinDir, skin_folder);
// base skin which is used as fallback for all skinned files
// e.g. c:\program files\secondlife\skins\default
mDefaultSkinDir = getSkinBaseDir();
mDefaultSkinDir += mDirDelimiter;
mDefaultSkinDir += "default";
append(mDefaultSkinDir, "default");
}
bool LLDir::setCacheDir(const std::string &path)
@@ -673,7 +637,7 @@ bool LLDir::setCacheDir(const std::string &path)
else
{
LLFile::mkdir(path);
std::string tempname = path + mDirDelimiter + "temp";
std::string tempname = add(path, "temp");
LLFILE* file = LLFile::fopen(tempname,"wt");
if (file)
{
@@ -706,6 +670,57 @@ void LLDir::dumpCurrentDirectories()
LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
}
std::string LLDir::add(const std::string& path, const std::string& name) const
{
std::string destpath(path);
append(destpath, name);
return destpath;
}
void LLDir::append(std::string& destpath, const std::string& name) const
{
// Delegate question of whether we need a separator to helper method.
SepOff sepoff(needSep(destpath, name));
if (sepoff.first) // do we need a separator?
{
destpath += mDirDelimiter;
}
// If destpath ends with a separator, AND name starts with one, skip
// name's leading separator.
destpath += name.substr(sepoff.second);
}
LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const
{
if (path.empty() || name.empty())
{
// If either path or name are empty, we do not need a separator
// between them.
return SepOff(false, 0);
}
// Here we know path and name are both non-empty. But if path already ends
// with a separator, or if name already starts with a separator, we need
// not add one.
std::string::size_type seplen(mDirDelimiter.length());
bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter);
bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter);
if ((! path_ends_sep) && (! name_starts_sep))
{
// If neither path nor name brings a separator to the junction, then
// we need one.
return SepOff(true, 0);
}
if (path_ends_sep && name_starts_sep)
{
// But if BOTH path and name bring a separator, we need not add one.
// Moreover, we should actually skip the leading separator of 'name'.
return SepOff(false, seplen);
}
// Here we know that either path_ends_sep or name_starts_sep is true --
// but not both. So don't add a separator, and don't skip any characters:
// simple concatenation will do the trick.
return SepOff(false, 0);
}
void dir_exists_or_crash(const std::string &dir_name)
{

View File

@@ -140,7 +140,17 @@ class LLDir
// Utility routine
std::string buildSLOSCacheDir() const;
/// Append specified @a name to @a destpath, separated by getDirDelimiter()
/// if both are non-empty.
void append(std::string& destpath, const std::string& name) const;
/// Append specified @a name to @a path, separated by getDirDelimiter()
/// if both are non-empty. Return result, leaving @a path unmodified.
std::string add(const std::string& path, const std::string& name) const;
protected:
// Does an add() or append() call need a directory delimiter?
typedef std::pair<bool, unsigned short> SepOff;
SepOff needSep(const std::string& path, const std::string& name) const;
std::string mAppName; // install directory under progams/ ie "SecondLife"
std::string mExecutablePathAndName; // full path + Filename of .exe
std::string mExecutableFilename; // Filename of .exe

View File

@@ -124,10 +124,9 @@ class LLDragDropWin32Target:
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
window_imp->convertCoords(cursor_coord_window, &gl_coord);
MASK mask = gKeyboard->currentMask(TRUE);
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
switch (result)
@@ -180,10 +179,9 @@ class LLDragDropWin32Target:
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
window_imp->convertCoords(cursor_coord_window, &gl_coord);
MASK mask = gKeyboard->currentMask(TRUE);
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_TRACK, mDropUrl );
switch (result)
@@ -237,15 +235,13 @@ class LLDragDropWin32Target:
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
if ( NULL != window_imp )
{
LLCoordGL gl_coord( 0, 0 );
POINT pt_client;
pt_client.x = pt.x;
pt_client.y = pt.y;
ScreenToClient( mAppWindowHandle, &pt_client );
LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
window_imp->convertCoords(cursor_coord_window, &gl_coord);
LLCoordGL gl_coord(cursor_coord_window.convert());
llinfos << "### (Drop) URL is: " << mDropUrl << llendl;
llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl;
llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl;

View File

@@ -50,14 +50,15 @@ LLSplashScreen *gSplashScreenp = NULL;
BOOL gDebugClicks = FALSE;
BOOL gDebugWindowProc = FALSE;
const S32 gURLProtocolWhitelistCount = 3;
const std::string gURLProtocolWhitelist[] = { "file:", "http:", "https:" };
const S32 gURLProtocolWhitelistCount = 4;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:"/*, "file:"*/ };
// CP: added a handler list - this is what's used to open the protocol and is based on registry entry
// only meaningful difference currently is that file: protocols are opened using http:
// since no protocol handler exists in registry for file:
// Important - these lists should match - protocol to handler
const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
// Maestro: This list isn't referenced anywhere that I could find
//const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
@@ -112,6 +113,8 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
mCursorHidden(FALSE),
mBusyCount(0),
mIsMouseClipping(FALSE),
mMinWindowWidth(0),
mMinWindowHeight(0),
mSwapMethod(SWAP_METHOD_UNDEFINED),
mHideCursorPermanent(FALSE),
mFlags(flags),
@@ -180,6 +183,51 @@ void *LLWindow::getMediaWindow()
return getPlatformWindow();
}
BOOL LLWindow::setSize(LLCoordScreen size)
{
if (!getMaximized())
{
size.mX = llmax(size.mX, mMinWindowWidth);
size.mY = llmax(size.mY, mMinWindowHeight);
}
return setSizeImpl(size);
}
BOOL LLWindow::setSize(LLCoordWindow size)
{
//HACK: we are inconsistently using minimum window dimensions
// in this case, we are constraining the inner "client" rect and other times
// we constrain the outer "window" rect
// There doesn't seem to be a good way to do this consistently without a bunch of platform
// specific code
if (!getMaximized())
{
size.mX = llmax(size.mX, mMinWindowWidth);
size.mY = llmax(size.mY, mMinWindowHeight);
}
return setSizeImpl(size);
}
// virtual
void LLWindow::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
{
mMinWindowWidth = min_width;
mMinWindowHeight = min_height;
if (enforce_immediately)
{
LLCoordScreen cur_size;
if (!getMaximized() && getSize(&cur_size))
{
if (cur_size.mX < mMinWindowWidth || cur_size.mY < mMinWindowHeight)
{
setSizeImpl(LLCoordScreen(llmin(cur_size.mX, mMinWindowWidth), llmin(cur_size.mY, mMinWindowHeight)));
}
}
}
}
//virtual
void LLWindow::processMiscNativeEvents()
{
@@ -209,6 +257,8 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()
return LLWindowWin32::getDynamicFallbackFontList();
#elif LL_DARWIN
return LLWindowMacOSX::getDynamicFallbackFontList();
#elif LL_MESA_HEADLESS
return std::vector<std::string>();
#elif LL_SDL
return LLWindowSDL::getDynamicFallbackFontList();
#else
@@ -350,26 +400,26 @@ LLWindow* LLWindowManager::createWindow(
#if LL_MESA_HEADLESS
new_window = new LLWindowMesaHeadless(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
fullscreen, clearBg, disable_vsync, ignore_pixel_depth);
#elif LL_SDL
new_window = new LLWindowSDL(callbacks,
title, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
fullscreen, clearBg, disable_vsync, ignore_pixel_depth, fsaa_samples);
#elif LL_WINDOWS
new_window = new LLWindowWin32(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
fullscreen, clearBg, disable_vsync, ignore_pixel_depth, fsaa_samples);
#elif LL_DARWIN
new_window = new LLWindowMacOSX(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
fullscreen, clearBg, disable_vsync, ignore_pixel_depth, fsaa_samples);
#endif
}
else
{
new_window = new LLWindowHeadless(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
fullscreen, clearBg, disable_vsync, ignore_pixel_depth);
}
if (FALSE == new_window->isValid())
@@ -404,3 +454,42 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window)
{
return sWindowList.find(window) != sWindowList.end();
}
//coordinate conversion utility funcs that forward to llwindow
LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const
{
const LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this);
LLWindow* windowp = &(*LLWindow::beginInstances());
LLCoordGL out;
windowp->convertCoords(self, &out);
return out.convert();
}
void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from)
{
LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this);
LLWindow* windowp = &(*LLWindow::beginInstances());
LLCoordGL from_gl(from);
windowp->convertCoords(from_gl, &self);
}
LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const
{
const LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this);
LLWindow* windowp = &(*LLWindow::beginInstances());
LLCoordGL out;
windowp->convertCoords(self, &out);
return out.convert();
}
void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from)
{
LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this);
LLWindow* windowp = &(*LLWindow::beginInstances());
LLCoordGL from_gl(from);
windowp->convertCoords(from_gl, &self);
}

View File

@@ -46,7 +46,7 @@ const S32 MIN_WINDOW_HEIGHT = 256;
// Refer to llwindow_test in test/common/llwindow for usage example
class LLWindow
class LLWindow : public LLInstanceTracker<LLWindow>
{
public:
struct LLWindowResolution
@@ -79,7 +79,9 @@ public:
virtual BOOL getSize(LLCoordScreen *size) = 0;
virtual BOOL getSize(LLCoordWindow *size) = 0;
virtual BOOL setPosition(LLCoordScreen position) = 0;
virtual BOOL setSize(LLCoordScreen size) = 0;
BOOL setSize(LLCoordScreen size);
BOOL setSize(LLCoordWindow size);
virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) = 0;
virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
@@ -180,6 +182,9 @@ protected:
// Defaults to true
virtual BOOL canDelete();
virtual BOOL setSizeImpl(LLCoordScreen size) = 0;
virtual BOOL setSizeImpl(LLCoordWindow size) = 0;
protected:
LLWindowCallbacks* mCallbacks;
@@ -200,6 +205,8 @@ protected:
BOOL mHideCursorPermanent;
U32 mFlags;
U16 mHighSurrogate;
S32 mMinWindowWidth;
S32 mMinWindowHeight;
// Handle a UTF-16 encoding unit received from keyboard.
// Converting the series of UTF-16 encoding units to UTF-32 data,
@@ -283,7 +290,7 @@ extern BOOL gDebugWindowProc;
// Protocols, like "http" and "https" we support in URLs
extern const S32 gURLProtocolWhitelistCount;
extern const std::string gURLProtocolWhitelist[];
extern const std::string gURLProtocolWhitelistHandler[];
//extern const std::string gURLProtocolWhitelistHandler[];
void simpleEscapeString ( std::string& stringIn );

View File

@@ -35,7 +35,7 @@
//
LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, BOOL fullscreen, BOOL clear_background,
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
BOOL disable_vsync, BOOL ignore_pixel_depth)
: LLWindow(callbacks, fullscreen, flags)
{
// Initialize a headless keyboard.

View File

@@ -46,7 +46,8 @@ public:
/*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;};
/*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;};
/*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;};
/*virtual*/ BOOL setSize(LLCoordScreen size) {return FALSE;};
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;};
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;};
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
@@ -95,7 +96,7 @@ public:
S32 x, S32 y,
S32 width, S32 height,
U32 flags, BOOL fullscreen, BOOL clear_background,
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
BOOL disable_vsync, BOOL ignore_pixel_depth);
virtual ~LLWindowHeadless();
private:

View File

@@ -3,31 +3,25 @@
* @brief Prototypes for functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
*
* $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.
*
* 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 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.
*
* 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.
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* 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$
*/

View File

@@ -3,31 +3,25 @@
* @brief Definition of functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
*
* $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.
*
* 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 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.
*
* 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.
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* 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$
*/

View File

@@ -210,7 +210,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl,
BOOL disable_vsync,
BOOL ignore_pixel_depth,
U32 fsaa_samples)
: LLWindow(NULL, fullscreen, flags)
@@ -1256,7 +1256,7 @@ BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position)
return TRUE;
}
BOOL LLWindowMacOSX::setSize(const LLCoordScreen size)
BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size)
{
if(mWindow)
{
@@ -1266,6 +1266,31 @@ BOOL LLWindowMacOSX::setSize(const LLCoordScreen size)
return TRUE;
}
BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size)
{
Rect client_rect;
if (mWindow)
{
OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect);
if (err == noErr)
{
client_rect.right = client_rect.left + size.mX;
client_rect.bottom = client_rect.top + size.mY;
err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect);
}
if (err == noErr)
{
return TRUE;
}
else
{
llinfos << "Error setting size" << err << llendl;
return FALSE;
}
}
return FALSE;
}
void LLWindowMacOSX::swapBuffers()
{
aglSwapBuffers(mContext);
@@ -2546,6 +2571,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
// This is where we would constrain move/resize to a particular screen
const S32 MIN_WIDTH = mMinWindowWidth;
const S32 MIN_HEIGHT = mMinWindowHeight;
Rect currentBounds;
Rect previousBounds;
@@ -2570,14 +2598,14 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
mPreviousWindowRect = previousBounds;
}
if ((currentBounds.right - currentBounds.left) < MIN_WINDOW_WIDTH)
if ((currentBounds.right - currentBounds.left) < MIN_WIDTH)
{
currentBounds.right = currentBounds.left + MIN_WINDOW_WIDTH;
currentBounds.right = currentBounds.left + MIN_WIDTH;
}
if ((currentBounds.bottom - currentBounds.top) < MIN_WINDOW_HEIGHT)
if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT)
{
currentBounds.bottom = currentBounds.top + MIN_WINDOW_HEIGHT;
currentBounds.bottom = currentBounds.top + MIN_HEIGHT;
}
SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &currentBounds);

View File

@@ -58,7 +58,8 @@ public:
/*virtual*/ BOOL getSize(LLCoordScreen *size);
/*virtual*/ BOOL getSize(LLCoordWindow *size);
/*virtual*/ BOOL setPosition(LLCoordScreen position);
/*virtual*/ BOOL setSize(LLCoordScreen size);
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
@@ -123,7 +124,7 @@ public:
protected:
LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync,
BOOL ignore_pixel_depth,
U32 fsaa_samples);
~LLWindowMacOSX();

View File

@@ -41,28 +41,25 @@ U16 *gMesaBuffer = NULL;
LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
BOOL disable_vsync, BOOL ignore_pixel_depth)
: LLWindow(callbacks, fullscreen, flags)
{
if (use_gl)
llinfos << "MESA Init" << llendl;
mMesaContext = OSMesaCreateContextExt( GL_RGBA, 32, 0, 0, NULL );
/* Allocate the image buffer */
mMesaBuffer = new unsigned char [width * height * 4 * MESA_CHANNEL_SIZE];
llassert(mMesaBuffer);
gMesaBuffer = (U16*)mMesaBuffer;
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent( mMesaContext, mMesaBuffer, MESA_CHANNEL_TYPE, width, height ))
{
llinfos << "MESA Init" << llendl;
mMesaContext = OSMesaCreateContextExt( GL_RGBA, 32, 0, 0, NULL );
/* Allocate the image buffer */
mMesaBuffer = new unsigned char [width * height * 4 * MESA_CHANNEL_SIZE];
llassert(mMesaBuffer);
gMesaBuffer = (U16*)mMesaBuffer;
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent( mMesaContext, mMesaBuffer, MESA_CHANNEL_TYPE, width, height ))
{
llerrs << "MESA: OSMesaMakeCurrent failed!" << llendl;
}
llverify(gGLManager.initGL());
llerrs << "MESA: OSMesaMakeCurrent failed!" << llendl;
}
llverify(gGLManager.initGL());
}

View File

@@ -50,7 +50,8 @@ public:
/*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;};
/*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;};
/*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;};
/*virtual*/ BOOL setSize(LLCoordScreen size) {return FALSE;};
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;};
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;};
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
@@ -97,7 +98,7 @@ public:
LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
BOOL disable_vsync, BOOL ignore_pixel_depth);
~LLWindowMesaHeadless();
private:

View File

@@ -189,7 +189,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
const std::string& title, S32 x, S32 y, S32 width,
S32 height, U32 flags,
BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl,
BOOL disable_vsync,
BOOL ignore_pixel_depth, U32 fsaa_samples)
: LLWindow(callbacks, fullscreen, flags),
Lock_Display(NULL),
@@ -200,7 +200,6 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
gKeyboard->setCallbacks(callbacks);
// Note that we can't set up key-repeat until after SDL has init'd video
// Ignore use_gl for now, only used for drones on PC
mWindow = NULL;
mNeedsResize = FALSE;
mOverrideAspectRatio = 0.f;
@@ -975,7 +974,7 @@ BOOL LLWindowSDL::setPosition(const LLCoordScreen position)
return TRUE;
}
BOOL LLWindowSDL::setSize(const LLCoordScreen size)
BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size)
{
if(mWindow)
{
@@ -993,6 +992,25 @@ BOOL LLWindowSDL::setSize(const LLCoordScreen size)
return FALSE;
}
BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size)
{
if(mWindow)
{
// Push a resize event onto SDL's queue - we'll handle it
// when it comes out again.
SDL_Event event;
event.type = SDL_VIDEORESIZE;
event.resize.w = size.mX;
event.resize.h = size.mY;
SDL_PushEvent(&event); // copied into queue
return TRUE;
}
return FALSE;
}
void LLWindowSDL::swapBuffers()
{
if (mWindow)
@@ -1045,6 +1063,25 @@ void LLWindowSDL::setMouseClipping( BOOL b )
//SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF);
}
// virtual
void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
{
LLWindow::setMinSize(min_width, min_height, enforce_immediately);
#if LL_X11
// Set the minimum size limits for X11 window
// so the window manager doesn't allow resizing below those limits.
XSizeHints* hints = XAllocSizeHints();
hints->flags |= PMinSize;
hints->min_width = mMinWindowWidth;
hints->min_height = mMinWindowHeight;
XSetWMNormalHints(mSDL_Display, mSDL_XWindowID, hints);
XFree(hints);
#endif
}
BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
{
BOOL result = TRUE;
@@ -1859,8 +1896,8 @@ void LLWindowSDL::gatherInput()
llinfos << "Handling a resize event: " << event.resize.w <<
"x" << event.resize.h << llendl;
S32 width = llmax(event.resize.w, MIN_WINDOW_WIDTH);
S32 height = llmax(event.resize.h, MIN_WINDOW_HEIGHT);
S32 width = llmax(event.resize.w, (S32)mMinWindowWidth);
S32 height = llmax(event.resize.h, (S32)mMinWindowHeight);
if (width != mWindow->w || height != mWindow->h)
{
@@ -2488,6 +2525,23 @@ void exec_cmd(const std::string& cmd, const std::string& arg)
// Must begin with protocol identifier.
void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
{
bool found = false;
S32 i;
for (i = 0; i < gURLProtocolWhitelistCount; i++)
{
if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos)
{
found = true;
break;
}
}
if (!found)
{
llwarns << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << llendl;
return;
}
llinfos << "spawn_web_browser: " << escaped_url << llendl;
#if LL_LINUX || LL_SOLARIS
@@ -2623,9 +2677,9 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
if (sortpat)
{
// Sort the list of system fonts from most-to-least-desirable.
FcResult fresult;
FcResult result;
fs = FcFontSort(NULL, sortpat, elide_unicode_coverage,
NULL, &fresult);
NULL, &result);
FcPatternDestroy(sortpat);
}

View File

@@ -63,7 +63,8 @@ public:
/*virtual*/ BOOL getSize(LLCoordScreen *size);
/*virtual*/ BOOL getSize(LLCoordWindow *size);
/*virtual*/ BOOL setPosition(LLCoordScreen position);
/*virtual*/ BOOL setSize(LLCoordScreen size);
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
@@ -76,6 +77,7 @@ public:
/*virtual*/ void captureMouse();
/*virtual*/ void releaseMouse();
/*virtual*/ void setMouseClipping( BOOL b );
/*virtual*/ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
/*virtual*/ BOOL isClipboardTextAvailable();
/*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
@@ -147,7 +149,7 @@ public:
protected:
LLWindowSDL(LLWindowCallbacks* callbacks,
const std::string& title, int x, int y, int width, int height, U32 flags,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync,
BOOL ignore_pixel_depth, U32 fsaa_samples);
~LLWindowSDL();

View File

@@ -363,11 +363,15 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl,
BOOL disable_vsync,
BOOL ignore_pixel_depth,
U32 fsaa_samples)
: LLWindow(callbacks, fullscreen, flags)
{
//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
LoadLibrary(L"opengl32.dll");
mFSAASamples = fsaa_samples;
mIconResource = gIconResource;
mOverrideAspectRatio = 0.f;
@@ -860,13 +864,11 @@ BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
return FALSE;
}
getSize(&size);
moveWindow(position, size);
return TRUE;
}
BOOL LLWindowWin32::setSize(const LLCoordScreen size)
BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size)
{
LLCoordScreen position;
@@ -876,11 +878,30 @@ BOOL LLWindowWin32::setSize(const LLCoordScreen size)
return FALSE;
}
moveWindow(position, size);
WINDOWPLACEMENT placement;
placement.length = sizeof(WINDOWPLACEMENT);
if (!GetWindowPlacement(mWindowHandle, &placement)) return FALSE;
placement.showCmd = SW_RESTORE;
if (!SetWindowPlacement(mWindowHandle, &placement)) return FALSE;
moveWindow(position, size);
return TRUE;
}
BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size)
{
RECT window_rect = {0, 0, size.mX, size.mY };
DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
DWORD dw_style = WS_OVERLAPPEDWINDOW;
AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
return setSizeImpl(LLCoordScreen(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top));
}
// changing fullscreen resolution
BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
{
@@ -891,12 +912,12 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
DWORD current_refresh;
DWORD dw_ex_style;
DWORD dw_style;
RECT window_rect;
RECT window_rect = {0, 0, 0, 0};
S32 width = size.mX;
S32 height = size.mY;
BOOL auto_show = FALSE;
if (mhRC)
if (mhRC)
{
auto_show = TRUE;
resetDisplayResolution();
@@ -1093,6 +1114,37 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
return FALSE;
}
// (EXP-1765) dump pixel data to see if there is a pattern that leads to unreproducible crash
LL_INFOS("Window") << "--- begin pixel format dump ---" << llendl ;
LL_INFOS("Window") << "pixel_format is " << pixel_format << llendl ;
LL_INFOS("Window") << "pfd.nSize: " << pfd.nSize << llendl ;
LL_INFOS("Window") << "pfd.nVersion: " << pfd.nVersion << llendl ;
LL_INFOS("Window") << "pfd.dwFlags: 0x" << std::hex << pfd.dwFlags << std::dec << llendl ;
LL_INFOS("Window") << "pfd.iPixelType: " << (int)pfd.iPixelType << llendl ;
LL_INFOS("Window") << "pfd.cColorBits: " << (int)pfd.cColorBits << llendl ;
LL_INFOS("Window") << "pfd.cRedBits: " << (int)pfd.cRedBits << llendl ;
LL_INFOS("Window") << "pfd.cRedShift: " << (int)pfd.cRedShift << llendl ;
LL_INFOS("Window") << "pfd.cGreenBits: " << (int)pfd.cGreenBits << llendl ;
LL_INFOS("Window") << "pfd.cGreenShift: " << (int)pfd.cGreenShift << llendl ;
LL_INFOS("Window") << "pfd.cBlueBits: " << (int)pfd.cBlueBits << llendl ;
LL_INFOS("Window") << "pfd.cBlueShift: " << (int)pfd.cBlueShift << llendl ;
LL_INFOS("Window") << "pfd.cAlphaBits: " << (int)pfd.cAlphaBits << llendl ;
LL_INFOS("Window") << "pfd.cAlphaShift: " << (int)pfd.cAlphaShift << llendl ;
LL_INFOS("Window") << "pfd.cAccumBits: " << (int)pfd.cAccumBits << llendl ;
LL_INFOS("Window") << "pfd.cAccumRedBits: " << (int)pfd.cAccumRedBits << llendl ;
LL_INFOS("Window") << "pfd.cAccumGreenBits: " << (int)pfd.cAccumGreenBits << llendl ;
LL_INFOS("Window") << "pfd.cAccumBlueBits: " << (int)pfd.cAccumBlueBits << llendl ;
LL_INFOS("Window") << "pfd.cAccumAlphaBits: " << (int)pfd.cAccumAlphaBits << llendl ;
LL_INFOS("Window") << "pfd.cDepthBits: " << (int)pfd.cDepthBits << llendl ;
LL_INFOS("Window") << "pfd.cStencilBits: " << (int)pfd.cStencilBits << llendl ;
LL_INFOS("Window") << "pfd.cAuxBuffers: " << (int)pfd.cAuxBuffers << llendl ;
LL_INFOS("Window") << "pfd.iLayerType: " << (int)pfd.iLayerType << llendl ;
LL_INFOS("Window") << "pfd.bReserved: " << (int)pfd.bReserved << llendl ;
LL_INFOS("Window") << "pfd.dwLayerMask: " << pfd.dwLayerMask << llendl ;
LL_INFOS("Window") << "pfd.dwVisibleMask: " << pfd.dwVisibleMask << llendl ;
LL_INFOS("Window") << "pfd.dwDamageMask: " << pfd.dwDamageMask << llendl ;
LL_INFOS("Window") << "--- end pixel format dump ---" << llendl ;
if (pfd.cColorBits < 32)
{
close();
@@ -1564,7 +1616,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
}
else
{
llinfos << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << " context." << llendl;
llinfos << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) <<
(LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << llendl;
done = true;
if (LLRender::sGLCoreProfile)
@@ -1675,24 +1728,15 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre
BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
{
LLCoordScreen screen_pos;
mMousePositionModified = TRUE;
if (!mWindowHandle)
{
return FALSE;
}
if (!convertCoords(position, &screen_pos))
{
return FALSE;
}
// Inform the application of the new mouse position (needed for per-frame
// hover/picking to function).
LLCoordGL gl_pos;
convertCoords(position, &gl_pos);
mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
mCallbacks->handleMouseMove(this, position.convert(), (MASK)0);
// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking.
// Because we have preemptively notified the application of the new
@@ -1702,24 +1746,23 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
{ }
return SetCursorPos(screen_pos.mX, screen_pos.mY);
LLCoordScreen screen_pos(position.convert());
return ::SetCursorPos(screen_pos.mX, screen_pos.mY);
}
BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
{
POINT cursor_point;
LLCoordScreen screen_pos;
if (!mWindowHandle ||
!GetCursorPos(&cursor_point))
if (!mWindowHandle
|| !GetCursorPos(&cursor_point)
|| !position)
{
return FALSE;
}
screen_pos.mX = cursor_point.x;
screen_pos.mY = cursor_point.y;
return convertCoords(screen_pos, position);
*position = LLCoordScreen(cursor_point.x, cursor_point.y).convert();
return TRUE;
}
void LLWindowWin32::hideCursor()
@@ -1880,7 +1923,7 @@ void LLWindowWin32::gatherInput()
MSG msg;
int msg_count = 0;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE)
while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput");
TranslateMessage(&msg);
@@ -1936,6 +1979,10 @@ static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse");
LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param)
{
// Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN.
// This helps prevent avatar walking after maximizing the window by double-clicking the title bar.
static bool sHandleLeftMouseUp = true;
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
@@ -2282,10 +2329,20 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
return 0;
case WM_NCLBUTTONDOWN:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_NCLBUTTONDOWN");
// A click in a non-client area, e.g. title bar or window border.
sHandleLeftMouseUp = false;
}
break;
case WM_LBUTTONDOWN:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN");
LLFastTimer t2(FTM_MOUSEHANDLER);
sHandleLeftMouseUp = true;
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
{
window_imp->interruptLanguageTextInput();
@@ -2296,15 +2353,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
window_imp->convertCoords(cursor_coord_window, &gl_coord);
gl_coord = cursor_coord_window.convert();
}
else
{
window_imp->convertCoords(window_coord, &gl_coord);
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2326,15 +2383,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
window_imp->convertCoords(cursor_coord_window, &gl_coord);
gl_coord = cursor_coord_window.convert();
}
else
{
window_imp->convertCoords(window_coord, &gl_coord);
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2350,6 +2407,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP");
LLFastTimer t2(FTM_MOUSEHANDLER);
if (!sHandleLeftMouseUp)
{
sHandleLeftMouseUp = true;
break;
}
//if (gDebugClicks)
//{
// LL_INFOS("Window") << "WndProc left button up" << LL_ENDL;
@@ -2359,15 +2423,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
window_imp->convertCoords(cursor_coord_window, &gl_coord);
gl_coord = cursor_coord_window.convert();
}
else
{
window_imp->convertCoords(window_coord, &gl_coord);
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2394,15 +2458,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
window_imp->convertCoords(cursor_coord_window, &gl_coord);
gl_coord = cursor_coord_window.convert();
}
else
{
window_imp->convertCoords(window_coord, &gl_coord);
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2423,15 +2487,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
window_imp->convertCoords(cursor_coord_window, &gl_coord);
gl_coord = cursor_coord_window.convert();
}
else
{
window_imp->convertCoords(window_coord, &gl_coord);
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2458,15 +2522,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
window_imp->convertCoords(cursor_coord_window, &gl_coord);
gl_coord = cursor_coord_window.convert();
}
else
{
window_imp->convertCoords(window_coord, &gl_coord);
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2487,15 +2551,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
window_imp->convertCoords(cursor_coord_window, &gl_coord);
gl_coord = cursor_coord_window.convert();
}
else
{
window_imp->convertCoords(window_coord, &gl_coord);
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2567,17 +2631,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_MOUSEMOVE:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE");
window_imp->convertCoords(window_coord, &gl_coord);
MASK mask = gKeyboard->currentMask(TRUE);
window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask);
return 0;
}
case WM_GETMINMAXINFO:
{
LPMINMAXINFO min_max = (LPMINMAXINFO)l_param;
min_max->ptMinTrackSize.x = MIN_WINDOW_WIDTH;
min_max->ptMinTrackSize.y = MIN_WINDOW_HEIGHT;
min_max->ptMinTrackSize.x = window_imp->mMinWindowWidth;
min_max->ptMinTrackSize.y = window_imp->mMinWindowHeight;
return 0;
}
@@ -3483,7 +3546,7 @@ void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )
LLWinImm::setCompositionWindow( himc, &ime_form );
sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY );
sWinIMEWindowPosition = win_pos;
}
LLWinImm::releaseContext(mWindowHandle, himc);

View File

@@ -57,7 +57,8 @@ public:
/*virtual*/ BOOL getSize(LLCoordScreen *size);
/*virtual*/ BOOL getSize(LLCoordWindow *size);
/*virtual*/ BOOL setPosition(LLCoordScreen position);
/*virtual*/ BOOL setSize(LLCoordScreen size);
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
@@ -120,7 +121,7 @@ public:
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync,
BOOL ignore_pixel_depth, U32 fsaa_samples);
~LLWindowWin32();

View File

@@ -219,7 +219,6 @@ set(viewer_SOURCE_FILES
llfloaterlandholdings.cpp
llfloaterlandmark.cpp
llfloatermap.cpp
llfloatermediabrowser.cpp
llfloatermemleak.cpp
llfloatermessagelog.cpp
llfloatermodelpreview.cpp
@@ -260,6 +259,7 @@ set(viewer_SOURCE_FILES
llfloaterurlentry.cpp
llfloatervoicedevicesettings.cpp
llfloaterwater.cpp
llfloaterwebcontent.cpp
llfloaterwindlight.cpp
llfloaterworldmap.cpp
llfolderview.cpp
@@ -314,6 +314,7 @@ set(viewer_SOURCE_FILES
llmarketplacefunctions.cpp
llmarketplacenotifications.cpp
llmediactrl.cpp
llmediadataclient.cpp
llmediaremotectrl.cpp
llmenucommands.cpp
llmenuoptionpathfindingrebakenavmesh.cpp
@@ -364,7 +365,6 @@ set(viewer_SOURCE_FILES
llpanellogin.cpp
llpanelmaininventory.cpp
llpanelmarketplaceoutboxinventory.cpp
llpanelmediahud.cpp
llpanelmorph.cpp
llpanelmsgs.cpp
llpanelnetwork.cpp
@@ -373,6 +373,7 @@ set(viewer_SOURCE_FILES
llpanelpermissions.cpp
llpanelpick.cpp
llpanelplace.cpp
llpanelprimmediacontrols.cpp
llpanelprofile.cpp
llpanelskins.cpp
llpanelvolume.cpp
@@ -412,6 +413,7 @@ set(viewer_SOURCE_FILES
llscrollingpanelparambase.cpp
llselectmgr.cpp
llsky.cpp
llslurl.cpp
llspatialpartition.cpp
llsprite.cpp
llstartup.cpp
@@ -479,9 +481,7 @@ set(viewer_SOURCE_FILES
llviewerlayer.cpp
llviewermedia.cpp
llviewermedia_streamingaudio.cpp
llviewermediaeventemitter.cpp
llviewermediafocus.cpp
llviewermediaobserver.cpp
llviewermenu.cpp
llviewermenufile.cpp
llviewermessage.cpp
@@ -716,7 +716,6 @@ set(viewer_HEADER_FILES
llfloaterlandholdings.h
llfloaterlandmark.h
llfloatermap.h
llfloatermediabrowser.h
llfloatermemleak.h
llfloatermessagelog.h
llfloatermodelpreview.h
@@ -757,6 +756,7 @@ set(viewer_HEADER_FILES
llfloaterurlentry.h
llfloatervoicedevicesettings.h
llfloaterwater.h
llfloaterwebcontent.h
llfloaterwindlight.h
llfloaterworldmap.h
llfolderview.h
@@ -811,6 +811,7 @@ set(viewer_HEADER_FILES
llmarketplacefunctions.h
llmarketplacenotifications.h
llmediactrl.h
llmediadataclient.h
llmediaremotectrl.h
llmenucommands.h
llmenuoptionpathfindingrebakenavmesh.h
@@ -861,7 +862,6 @@ set(viewer_HEADER_FILES
llpanellogin.h
llpanelmaininventory.h
llpanelmarketplaceoutboxinventory.h
llpanelmediahud.h
llpanelmorph.h
llpanelmsgs.h
llpanelnetwork.h
@@ -870,6 +870,7 @@ set(viewer_HEADER_FILES
llpanelpermissions.h
llpanelpick.h
llpanelplace.h
llpanelprimmediacontrols.h
llpanelprofile.h
llpanelskins.h
llpanelvolume.h
@@ -911,6 +912,7 @@ set(viewer_HEADER_FILES
llselectmgr.h
llsimplestat.h
llsky.h
llslurl.h
llspatialpartition.h
llsprite.h
llstartup.h
@@ -980,7 +982,6 @@ set(viewer_HEADER_FILES
llviewerkeyboard.h
llviewerlayer.h
llviewermedia.h
llviewermediaeventemitter.h
llviewermediafocus.h
llviewermediaobserver.h
llviewermenu.h

View File

@@ -5430,6 +5430,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DisableTextHyperlinkActions</key>
<map>
<key>Comment</key>
<string>Disable highlighting and linking of URLs in XUI text boxes</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DisableVerticalSync</key>
<map>
<key>Comment</key>
@@ -16430,6 +16441,28 @@ This should be as low as possible, but too low may break functionality</string>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>SLURLDragNDrop</key>
<map>
<key>Comment</key>
<string>Enable drag and drop of SLURLs onto the viewer</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>SLURLPassToOtherInstance</key>
<map>
<key>Comment</key>
<string>Pass execution to prevoius viewer instances if there is a given slurl</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>soundsbeacon</key>
<map>
@@ -16508,6 +16541,19 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>180</integer>
</map>
<key>SLURLTeleportDirectly</key>
<map>
<key>Comment</key>
<string>Clicking on a slurl will teleport you directly instead of opening places panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>UseHTTPInventory</key>
<map>
<key>Comment</key>

View File

@@ -60,6 +60,8 @@
#include "lltooldraganddrop.h"
#include "llinventorymodel.h"
#include "llselectmgr.h"
#include "llslurl.h"
#include "llurlaction.h"
#include <iosfwd>
@@ -374,7 +376,6 @@ bool cmd_line_chat(std::string revised_text, EChatType type)
S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
S32 agent_z = llround( (F32)agentPos.mdV[VZ] );
std::string region_name = LLWeb::escapeURL(revised_text.substr(command.length()+1));
std::string url;
if(!sAscentCmdLineMapToKeepPos)
{
@@ -383,8 +384,8 @@ bool cmd_line_chat(std::string revised_text, EChatType type)
agent_z = 0;
}
url = llformat("secondlife:///app/teleport/%s/%d/%d/%d",region_name.c_str(),agent_x,agent_y,agent_z);
LLURLDispatcher::dispatch(url, NULL, true);
LLSLURL slurl(region_name,LLVector3(agent_x,agent_y,agent_z));
LLUrlAction::teleportToLocation(std::string("secondlife:///app/teleport/")+slurl.getLocationString());
}
return false;
}

View File

@@ -56,6 +56,7 @@
#include "llsdmessage.h"
#include "llsdutil.h"
#include "llsky.h"
#include "llslurl.h"
#include "llsmoothstep.h"
#include "llstartup.h"
#include "llstatusbar.h"
@@ -63,6 +64,8 @@
#include "lltoolpie.h"
#include "lltoolmgr.h"
#include "lltrans.h"
#include "lluictrl.h"
#include "llurlentry.h"
#include "llviewercontrol.h"
#include "llviewerdisplay.h"
#include "llviewerjoystick.h"
@@ -294,6 +297,7 @@ LLAgent::LLAgent() :
mAgentAccess(new LLAgentAccess(gSavedSettings)),
mGodLevelChangeSignal(),
mCanEditParcel(false),
mTeleportSourceSLURL(new LLSLURL),
mTeleportRequest(),
mTeleportFinishedSlot(),
mTeleportFailedSlot(),
@@ -434,6 +438,8 @@ LLAgent::~LLAgent()
mAgentAccess = NULL;
delete mEffectColor;
mEffectColor = NULL;
delete mTeleportSourceSLURL;
mTeleportSourceSLURL = NULL;
}
// Handle any actions that need to be performed when the main app gains focus
@@ -898,24 +904,6 @@ const LLHost& LLAgent::getRegionHost() const
}
}
//-----------------------------------------------------------------------------
// getSLURL()
// returns empty() if getRegion() == NULL
//-----------------------------------------------------------------------------
std::string LLAgent::getSLURL() const
{
std::string slurl;
LLViewerRegion *regionp = getRegion();
if (regionp)
{
LLVector3d agentPos = getPositionGlobal();
S32 x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) );
S32 y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
S32 z = llround( (F32)agentPos.mdV[VZ] );
slurl = LLURLDispatcher::buildSLURL(regionp->getName(), x, y, z);
}
return slurl;
}
//-----------------------------------------------------------------------------
// inPrelude()
@@ -3865,7 +3853,7 @@ bool LLAgent::teleportCore(bool is_local)
LLFloaterLand::hideInstance();
LLViewerParcelMgr::getInstance()->deselectLand();
LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL);
LLViewerMediaFocus::getInstance()->clearFocus();
// Close all pie menus, deselect land, etc.
// Don't change the camera until we know teleport succeeded. JC
@@ -4257,7 +4245,7 @@ void LLAgent::setTeleportState(ETeleportState state)
case TELEPORT_MOVING:
// We're outa here. Save "back" slurl.
mTeleportSourceSLURL = getSLURL();
LLAgentUI::buildSLURL(*mTeleportSourceSLURL);
break;
case TELEPORT_ARRIVING:
@@ -4683,6 +4671,10 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename)
}//end for (all message sets in xml file)
}
const void LLAgent::getTeleportSourceSLURL(LLSLURL& slurl) const
{
slurl = *mTeleportSourceSLURL;
}
void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility )
{
@@ -4736,14 +4728,13 @@ void LLAgent::renderAutoPilotTarget()
}
}
void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity)
void LLAgent::showLureDestination(const std::string fromname, U64& handle, U32 x, U32 y, U32 z)
{
const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0));
LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(posglobal);
LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
if(mPendingLure)
delete mPendingLure;
mPendingLure = new SHLureRequest(fromname,posglobal,x,y,z);
mPendingLure = new SHLureRequest(fromname,handle,x,y,z);
if(siminfo) //We already have an entry? Go right on to displaying it.
{
@@ -4751,8 +4742,8 @@ void LLAgent::showLureDestination(const std::string fromname, const int global_x
}
else
{
U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS);
U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS);
U32 grid_x, grid_y;
grid_from_region_handle(handle,&grid_x,&grid_y);
LLWorldMapMessage::getInstance()->sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); //Will call onFoundLureDestination on response
}
}
@@ -4763,7 +4754,7 @@ void LLAgent::onFoundLureDestination(LLSimInfo *siminfo)
return;
if(!siminfo)
siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(mPendingLure->mPosGlobal);
siminfo = LLWorldMap::getInstance()->simInfoFromHandle(mPendingLure->mRegionHandle);
if(siminfo)
{
const std::string sim_name = siminfo->getName();
@@ -4772,7 +4763,7 @@ void LLAgent::onFoundLureDestination(LLSimInfo *siminfo)
llinfos << mPendingLure->mAvatarName << "'s teleport lure is to " << sim_name << " (" << maturity << ")" << llendl;
LLStringUtil::format_map_t args;
args["[NAME]"] = mPendingLure->mAvatarName;
args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name, (S32)mPendingLure->mPosLocal[0], (S32)mPendingLure->mPosLocal[1], (S32)mPendingLure->mPosLocal[2] );
args["[DESTINATION]"] = LLSLURL(sim_name,mPendingLure->mPosLocal).getSLURLString();
std::string msg = LLTrans::getString("TeleportOfferMaturity", args);
if (!maturity.empty())
{

View File

@@ -68,6 +68,7 @@ class LLPickInfo;
class LLViewerObject;
class LLAgentDropGroupViewerNode;
class LLAgentAccess;
class LLSLURL;
class LLSimInfo;
class LLTeleportRequest;
@@ -245,20 +246,18 @@ public:
LLViewerRegion *getRegion() const { return mRegionp; }
const LLHost& getRegionHost() const;
BOOL inPrelude();
std::string getSLURL() const; //Return uri for current region
// <edit>
struct SHLureRequest
{
SHLureRequest(const std::string& avatar_name, const LLVector3d& pos_global, const int x, const int y, const int z) :
mAvatarName(avatar_name), mPosGlobal(pos_global)
{ mPosLocal[0] = x; mPosLocal[1] = y; mPosLocal[2] = z;}
SHLureRequest(const std::string& avatar_name, U64& handle, const U32 x, const U32 y, const U32 z) :
mAvatarName(avatar_name), mRegionHandle(handle), mPosLocal(x,y,z) {}
const std::string mAvatarName;
const LLVector3d mPosGlobal;
int mPosLocal[3];
const U64 mRegionHandle;
LLVector3 mPosLocal;
};
SHLureRequest *mPendingLure;
void showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity);
void showLureDestination(const std::string fromname, U64& handle, U32 x, U32 y, U32 z);
void onFoundLureDestination(LLSimInfo *siminfo = NULL);
// </edit>
@@ -568,13 +567,14 @@ public:
public:
static void parseTeleportMessages(const std::string& xml_filename);
const std::string& getTeleportSourceSLURL() const { return mTeleportSourceSLURL; }
const void getTeleportSourceSLURL(LLSLURL& slurl) const;
public:
// ! TODO ! Define ERROR and PROGRESS enums here instead of exposing the mappings.
static std::map<std::string, std::string> sTeleportErrorMessages;
static std::map<std::string, std::string> sTeleportProgressMessages;
public:
std::string mTeleportSourceSLURL; // SLURL where last TP began.
private:
LLSLURL * mTeleportSourceSLURL; // SLURL where last TP began
//--------------------------------------------------------------------
// Teleport Actions
//--------------------------------------------------------------------

View File

@@ -37,6 +37,7 @@
#include "llviewerregion.h"
#include "llviewerparcelmgr.h"
#include "llvoavatarself.h"
#include "llslurl.h"
// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d)
#include "rlvhandler.h"
// [/RLVa:KB]
@@ -48,9 +49,8 @@ void LLAgentUI::buildFullname(std::string& name)
name = gAgentAvatarp->getFullname();
}
/*
//static
void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /= true/ )
void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /*= true*/)
{
LLSLURL return_slurl;
LLViewerRegion *regionp = gAgent.getRegion();
@@ -59,7 +59,7 @@ void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /= true/ )
return_slurl = LLSLURL(regionp->getName(), gAgent.getPositionGlobal());
}
slurl = return_slurl;
}*/
}
//static
BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)

View File

@@ -56,6 +56,7 @@
#include "llmodaldialog.h"
#include "llpumpio.h"
#include "llmimetypes.h"
#include "llslurl.h"
#include "llstartup.h"
#include "llfocusmgr.h"
#include "llviewerjoystick.h"
@@ -80,6 +81,7 @@
#include "llvector4a.h"
#include "llimpanel.h" // For LLVoiceClient and LLVoiceChannel
#include "llvoavatarself.h"
#include "llurlmatch.h"
#include "llprogressview.h"
#include "llvocache.h"
#include "llvopartgroup.h"
@@ -94,6 +96,8 @@
#include "llimagej2c.h"
#include "llmemory.h"
#include "llprimitive.h"
#include "llurlaction.h"
#include "llurlentry.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include <boost/bind.hpp>
@@ -149,7 +153,6 @@
#include "llworld.h"
#include "llhudeffecttrail.h"
#include "llvectorperfoptions.h"
#include "llurlsimstring.h"
#include "llwatchdog.h"
// Included so that constants/settings might be initialized
@@ -755,9 +758,11 @@ bool LLAppViewer::init()
LLWeb::initClass(); // do this after LLUI
LLTextEditor::setURLCallbacks(&LLWeb::loadURL,
&LLURLDispatcher::dispatchFromTextEditor,
&LLURLDispatcher::dispatchFromTextEditor);
// Provide the text fields with callbacks for opening Urls
LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null));
LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
@@ -1779,7 +1784,6 @@ bool LLAppViewer::cleanup()
//Note:
//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
//because some new image might be generated during cleaning up media. --bao
LLViewerMediaFocus::cleanupClass();
LLViewerMedia::cleanupClass();
LLViewerParcelMedia::cleanupClass();
gTextureList.shutdown(); // shutdown again in case a callback added something
@@ -2329,30 +2333,17 @@ bool LLAppViewer::initConfiguration()
// injection and steal passwords. Phoenix. SL-55321
if(clp.hasOption("url"))
{
std::string slurl = clp.getOption("url")[0];
if (LLURLDispatcher::isSLURLCommand(slurl))
{
LLStartUp::sSLURLCommand = slurl;
}
else
{
LLURLSimString::setString(slurl);
}
LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION)
{
gHippoGridManager->setCurrentGrid(LLStartUp::getStartSLURL().getGrid());
}
}
else if(clp.hasOption("slurl"))
{
std::string slurl = clp.getOption("slurl")[0];
if(LLURLDispatcher::isSLURL(slurl))
{
if (LLURLDispatcher::isSLURLCommand(slurl))
{
LLStartUp::sSLURLCommand = slurl;
}
else
{
LLURLSimString::setString(slurl);
}
}
LLSLURL start_slurl(clp.getOption("slurl")[0]);
LLStartUp::setStartSLURL(start_slurl);
}
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
@@ -2431,18 +2422,11 @@ bool LLAppViewer::initConfiguration()
// don't call anotherInstanceRunning() when doing URL handoff, as
// it relies on checking a marker file which will not work when running
// out of different directories
std::string slurl;
if (!LLStartUp::sSLURLCommand.empty())
if (LLStartUp::getStartSLURL().isValid() &&
(gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
{
slurl = LLStartUp::sSLURLCommand;
}
else if (LLURLSimString::parse())
{
slurl = LLURLSimString::getURL();
}
if (!slurl.empty())
{
if (sendURLToOtherInstance(slurl))
if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString()))
{
// successfully handed off URL to existing instance, exit
return false;
@@ -2498,9 +2482,10 @@ bool LLAppViewer::initConfiguration()
// need to do this here - need to have initialized global settings first
std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
if ( nextLoginLocation.length() )
if ( !nextLoginLocation.empty() )
{
LLURLSimString::setString( nextLoginLocation );
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
}
gLastRunVersion = gSavedSettings.getString("LastRunVersion");

View File

@@ -43,7 +43,6 @@
#include "llviewernetwork.h"
#include "llviewercontrol.h"
#include "llmd5.h"
#include "llurlsimstring.h"
#include "llfloaterworldmap.h"
#include "llurldispatcher.h"
#include <Carbon/Carbon.h>

View File

@@ -896,7 +896,7 @@ class LLChatHandler : public LLCommandHandler
{
public:
// not allowed from outside the app
LLChatHandler() : LLCommandHandler("chat", true) { }
LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,

View File

@@ -4,46 +4,47 @@
* which manipulate user interface. For example, the command
* "agent (uuid) about" will open the UI for an avatar's profile.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2007&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.
*
* 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 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.
*
* 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.
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* 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 "llcommandhandler.h"
#include "llnotificationsutil.h"
//#include "llcommanddispatcherlistener.h"
#include "stringize.h"
// system includes
#include <boost/tokenizer.hpp>
#define THROTTLE_PERIOD 5 // required seconds between throttled commands
//static LLCommandDispatcherListener sCommandDispatcherListener;
//---------------------------------------------------------------------------
// Underlying registry for command handlers, not directly accessible.
//---------------------------------------------------------------------------
struct LLCommandHandlerInfo
{
bool mRequireTrustedBrowser;
LLCommandHandler::EUntrustedAccess mUntrustedBrowserAccess;
LLCommandHandler* mHandler; // safe, all of these are static objects
};
@@ -51,14 +52,18 @@ class LLCommandHandlerRegistry
{
public:
static LLCommandHandlerRegistry& instance();
void add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler);
void add(const char* cmd,
LLCommandHandler::EUntrustedAccess untrusted_access,
LLCommandHandler* handler);
bool dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser);
private:
friend LLSD LLCommandDispatcher::enumerate();
std::map<std::string, LLCommandHandlerInfo> mMap;
};
@@ -72,10 +77,12 @@ LLCommandHandlerRegistry& LLCommandHandlerRegistry::instance()
return instance;
}
void LLCommandHandlerRegistry::add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler)
void LLCommandHandlerRegistry::add(const char* cmd,
LLCommandHandler::EUntrustedAccess untrusted_access,
LLCommandHandler* handler)
{
LLCommandHandlerInfo info;
info.mRequireTrustedBrowser = require_trusted_browser;
info.mUntrustedBrowserAccess = untrusted_access;
info.mHandler = handler;
mMap[cmd] = info;
@@ -85,17 +92,60 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser)
{
static bool slurl_blocked = false;
static bool slurl_throttled = false;
static F64 last_throttle_time = 0.0;
F64 cur_time = 0.0;
std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd);
if (it == mMap.end()) return false;
const LLCommandHandlerInfo& info = it->second;
if (!trusted_browser && info.mRequireTrustedBrowser)
if (!trusted_browser)
{
// block request from external browser, but report as
// "handled" because it was well formatted.
LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
return true;
switch (info.mUntrustedBrowserAccess)
{
case LLCommandHandler::UNTRUSTED_ALLOW:
// fall through and let the command be handled
break;
case LLCommandHandler::UNTRUSTED_BLOCK:
// block request from external browser, but report as
// "handled" because it was well formatted.
LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
if (! slurl_blocked)
{
LLNotificationsUtil::add("BlockedSLURL");
slurl_blocked = true;
}
return true;
case LLCommandHandler::UNTRUSTED_THROTTLE:
// if users actually click on a link, we don't need to throttle it
// (throttling mechanism is used to prevent an avalanche of clicks via
// javascript
if ( nav_type == "clicked" )
{
break;
}
cur_time = LLTimer::getElapsedSeconds();
if (cur_time < last_throttle_time + THROTTLE_PERIOD)
{
// block request from external browser if it happened
// within THROTTLE_PERIOD seconds of the last command
LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
if (! slurl_throttled)
{
LLNotificationsUtil::add("ThrottledSLURL");
slurl_throttled = true;
}
return true;
}
last_throttle_time = cur_time;
break;
}
}
if (!info.mHandler) return false;
return info.mHandler->handle(params, query_map, web);
@@ -106,10 +156,9 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
//---------------------------------------------------------------------------
LLCommandHandler::LLCommandHandler(const char* cmd,
bool require_trusted_browser)
EUntrustedAccess untrusted_access)
{
LLCommandHandlerRegistry::instance().add(
cmd, require_trusted_browser, this);
LLCommandHandlerRegistry::instance().add(cmd, untrusted_access, this);
}
LLCommandHandler::~LLCommandHandler()
@@ -127,8 +176,62 @@ bool LLCommandDispatcher::dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser)
{
return LLCommandHandlerRegistry::instance().dispatch(
cmd, params, query_map, web, trusted_browser);
cmd, params, query_map, web, nav_type, trusted_browser);
}
static std::string lookup(LLCommandHandler::EUntrustedAccess value);
LLSD LLCommandDispatcher::enumerate()
{
LLSD response;
LLCommandHandlerRegistry& registry(LLCommandHandlerRegistry::instance());
for (std::map<std::string, LLCommandHandlerInfo>::const_iterator chi(registry.mMap.begin()),
chend(registry.mMap.end());
chi != chend; ++chi)
{
LLSD info;
info["untrusted"] = chi->second.mUntrustedBrowserAccess;
info["untrusted_str"] = lookup(chi->second.mUntrustedBrowserAccess);
response[chi->first] = info;
}
return response;
}
/*------------------------------ lookup stuff ------------------------------*/
struct symbol_info
{
const char* name;
LLCommandHandler::EUntrustedAccess value;
};
#define ent(SYMBOL) \
{ \
#SYMBOL + 28, /* skip "LLCommandHandler::UNTRUSTED_" prefix */ \
SYMBOL \
}
symbol_info symbols[] =
{
ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers
ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers
ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min.
};
#undef ent
static std::string lookup(LLCommandHandler::EUntrustedAccess value)
{
for (symbol_info *sii(symbols), *siend(symbols + (sizeof(symbols)/sizeof(symbols[0])));
sii != siend; ++sii)
{
if (sii->value == value)
{
return sii->name;
}
}
return STRINGIZE("UNTRUSTED_" << value);
}

View File

@@ -4,36 +4,32 @@
* which manipulate user interface. For example, the command
* "agent (uuid) about" will open the UI for an avatar's profile.
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2007&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.
*
* 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 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.
*
* 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.
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* 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$
*/
#ifndef LLCOMMANDHANDLER_H
#define LLCOMMANDHANDLER_H
#include "llsd.h"
/* Example: secondlife:///app/foo/<uuid>
Command "foo" that takes one parameter, a UUID.
@@ -43,7 +39,7 @@ public:
// Inform the system you handle commands starting
// with "foo" and they are only allowed from
// "trusted" (pointed at Linden content) browsers
LLFooHandler() : LLCommandHandler("foo", true) { }
LLFooHandler() : LLCommandHandler("foo", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
@@ -65,7 +61,14 @@ class LLMediaCtrl;
class LLCommandHandler
{
public:
LLCommandHandler(const char* command, bool allow_from_untrusted_browser);
enum EUntrustedAccess
{
UNTRUSTED_ALLOW, // allow commands from untrusted browsers
UNTRUSTED_BLOCK, // ignore commands from untrusted browsers
UNTRUSTED_THROTTLE // allow untrusted, but only a few per min.
};
LLCommandHandler(const char* command, EUntrustedAccess untrusted_access);
// Automatically registers object to get called when
// command is executed. All commands can be processed
// in links from LLMediaCtrl, but some (like teleport)
@@ -92,10 +95,14 @@ public:
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type,
bool trusted_browser);
// Execute a command registered via the above mechanism,
// passing string parameters.
// Returns true if command was found and executed correctly.
/// Return an LLSD::Map of registered LLCommandHandlers and associated
/// info (e.g. EUntrustedAccess).
static LLSD enumerate();
};
#endif

View File

@@ -190,8 +190,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mImportanceToCamera = 0.f ;
mBoundingSphereRadius = 0.0f ;
}
mHasMedia = FALSE ;
}
void LLFace::destroy()
{
@@ -2065,6 +2066,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
return TRUE;
}
//check if the face has a media
BOOL LLFace::hasMedia() const
{
if(mHasMedia)
{
return TRUE ;
}
if(mTexture.notNull())
{
return mTexture->hasParcelMedia() ; //if has a parcel media
}
return FALSE ; //no media.
}
const F32 LEAST_IMPORTANCE = 0.05f ;
const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
@@ -2134,7 +2149,7 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
t.load3(camera->getOrigin().mV);
lookAt.setSub(center, t);
F32 dist = lookAt.getLength3().getF32();
dist = llmax(dist-size.getLength3().getF32(), 0.f);
dist = llmax(dist-size.getLength3().getF32(), 0.001f);
lookAt.normalize3fast() ;
//get area of circle around node
@@ -2145,9 +2160,33 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
x_axis.load3(camera->getXAxis().mV);
cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32();
//if has media, check if the face is out of the view frustum.
if(hasMedia())
{
if(!camera->AABBInFrustum(center, size))
{
mImportanceToCamera = 0.f ;
return false ;
}
if(cos_angle_to_view_dir > camera->getCosHalfFov()) //the center is within the view frustum
{
cos_angle_to_view_dir = 1.0f ;
}
else
{
LLVector4a d;
d.setSub(lookAt, x_axis);
if(dist * dist * d.dot3(d) < size_squared)
{
cos_angle_to_view_dir = 1.0f ;
}
}
}
if(dist < mBoundingSphereRadius) //camera is very close
{
cos_angle_to_view_dir = 1.0f;
cos_angle_to_view_dir = 1.0f ;
mImportanceToCamera = 1.0f;
}
else

View File

@@ -224,6 +224,9 @@ public:
F32 getTextureVirtualSize() ;
F32 getImportanceToCamera()const {return mImportanceToCamera ;}
void setHasMedia(bool has_media) { mHasMedia = has_media ;}
BOOL hasMedia() const ;
//vertex buffer tracking
void setVertexBuffer(LLVertexBuffer* buffer);
void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL
@@ -289,6 +292,7 @@ private:
//based on the distance from the face to the view point and the angle from the face center to the view direction.
F32 mImportanceToCamera ;
F32 mBoundingSphereRadius ;
bool mHasMedia ;
protected:
static BOOL sSafeRenderSelect;

View File

@@ -97,7 +97,7 @@ public:
}
// requires trusted browser to trigger
LLAgentHandler() : LLCommandHandler("agent", true) { }
LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)

View File

@@ -55,7 +55,7 @@ class LLClassifiedHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLClassifiedHandler() : LLCommandHandler("classified", true) { }
LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{

View File

@@ -56,7 +56,7 @@ class LLEventHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLEventHandler() : LLCommandHandler("event", true) { }
LLEventHandler() : LLCommandHandler("event", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{

View File

@@ -54,11 +54,12 @@ const LLRect FGI_RECT(0, 530, 420, 0);
//
std::map<LLUUID, LLFloaterGroupInfo*> LLFloaterGroupInfo::sInstances;
//moved to llgroupactions.cpp in v2
class LLGroupHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLGroupHandler() : LLCommandHandler("group", true) { }
LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{

View File

@@ -38,7 +38,7 @@ class LLFloaterHandler
: public LLCommandHandler
{
public:
LLFloaterHandler() : LLCommandHandler("floater", true) { }
LLFloaterHandler() : LLCommandHandler("floater", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web);
};

View File

@@ -63,5 +63,5 @@ void LLFloaterHtmlSimple::navigateTo(const std::string &url)
void LLFloaterHtmlSimple::setTrusted(bool trusted)
{
LLMediaCtrl* web = getChild<LLMediaCtrl>("browser");
web->setTrusted(trusted);
web->setTrustedContent(trusted);
}

View File

@@ -78,7 +78,7 @@ LLFloaterHUD::LLFloaterHUD()
if (mWebBrowser)
{
// Open links in internal browser
mWebBrowser->setOpenInExternalBrowser(false);
//mWebBrowser->setOpenInExternalBrowser(false);
// This is a "chrome" floater, so we don't want anything to
// take focus (as the user needs to be able to walk with

View File

@@ -34,6 +34,7 @@
#define LL_LLFLOATER_NOTIFICATIONS_CONSOLE_H
#include "llfloater.h"
#include "lllayoutstack.h"
#include "llnotifications.h"
class LLFloaterNotificationConsole :

View File

@@ -42,10 +42,13 @@
#include "llfloatergroupinfo.h"
#include "llfloatermute.h"
#include "llmutelist.h"
#include "llsdutil.h"
#include "llslurl.h"
#include "lltrans.h"
#include "llui.h"
#include "lluictrl.h"
#include "lluictrlfactory.h"
#include "llurldispatcher.h"
#include "llviewercontrol.h"
#include "llurlaction.h"
#include "llweb.h"
// [RLVa:KB] - Version: 1.23.4
#include "rlvhandler.h"
@@ -61,7 +64,7 @@ public:
BOOL postBuild(void);
void update(const LLUUID& id, const std::string& name, const std::string& slurl, const LLUUID& owner, bool owner_is_group);
void update(LLSD& payload);
// UI Handlers
static void onClickMap(void* data);
@@ -72,15 +75,14 @@ public:
private:
LLUUID mObjectID;
std::string mObjectName;
std::string mSlurl;
LLUUID mOwnerID;
std::string mOwnerName;
bool mOwnerIsGroup;
std::string mSLurl;
std::string mName;
bool mGroupOwned;
};
LLFloaterObjectIMInfo::LLFloaterObjectIMInfo(const LLSD& seed)
: mObjectID(), mObjectName(), mSlurl(), mOwnerID(), mOwnerName(), mOwnerIsGroup(false)
: mObjectID(), mName(), mSLurl(), mOwnerID(), mGroupOwned(false)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_object_im_info.xml");
@@ -100,34 +102,37 @@ BOOL LLFloaterObjectIMInfo::postBuild(void)
return true;
}
void LLFloaterObjectIMInfo::update(const LLUUID& object_id, const std::string& name, const std::string& slurl, const LLUUID& owner_id, bool owner_is_group)
void LLFloaterObjectIMInfo::update(LLSD& data)
{
// Extract appropriate object information from input LLSD
// (Eventually, it might be nice to query server for details
// rather than require caller to pass in the information.)
mObjectID = data["object_id"].asUUID();
mName = data["name"].asString();
mOwnerID = data["owner_id"].asUUID();
mGroupOwned = data["group_owned"].asBoolean();
mSLurl = data["slurl"].asString();
// When talking to an old region we won't have a slurl.
// The object id isn't really the object id either but we don't use it so who cares.
//bool have_slurl = !slurl.empty();
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-04 (RLVa-1.0.0a) | Added: RLVa-0.2.0g
bool have_slurl = (!slurl.empty()) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC));
bool have_slurl = (!mSLurl.empty()) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC));
// [/RLVa:KB]
childSetVisible("Unknown_Slurl",!have_slurl);
childSetVisible("Slurl",have_slurl);
childSetText("ObjectName",name);
childSetText("Slurl",slurl);
childSetText("ObjectName",mName);
childSetText("Slurl",mSLurl);
childSetText("OwnerName",std::string(""));
// bool my_object = (owner_id == gAgentID);
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0g
bool my_object = (owner_id == gAgentID) || ((gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(owner_id)));
bool my_object = (mOwnerID == gAgentID) || ((gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(mOwnerID)));
// [/RLVa:KB]
childSetEnabled("Mute",!my_object);
mObjectID = object_id;
mObjectName = name;
mSlurl = slurl;
mOwnerID = owner_id;
mOwnerIsGroup = owner_is_group;
if (gCacheName) gCacheName->get(owner_id,owner_is_group,boost::bind(&LLFloaterObjectIMInfo::nameCallback,this,_1,_2,_3));
if (gCacheName) gCacheName->get(mOwnerID,mGroupOwned,boost::bind(&LLFloaterObjectIMInfo::nameCallback,this,_1,_2,_3));
}
//static
@@ -135,17 +140,15 @@ void LLFloaterObjectIMInfo::onClickMap(void* data)
{
LLFloaterObjectIMInfo* self = (LLFloaterObjectIMInfo*)data;
std::ostringstream link;
link << "secondlife://" << self->mSlurl;
class LLMediaCtrl* web = NULL;
LLURLDispatcher::dispatch(link.str(), web, true);
std::string url = "secondlife://" + self->mSLurl;
LLUrlAction::showLocationOnMap(url);
}
//static
void LLFloaterObjectIMInfo::onClickOwner(void* data)
{
LLFloaterObjectIMInfo* self = (LLFloaterObjectIMInfo*)data;
if (self->mOwnerIsGroup)
if (self->mGroupOwned)
{
LLFloaterGroupInfo::showFromUUID(self->mOwnerID);
}
@@ -163,7 +166,7 @@ void LLFloaterObjectIMInfo::onClickMute(void* data)
{
LLFloaterObjectIMInfo* self = (LLFloaterObjectIMInfo*)data;
LLMute::EType mute_type = (self->mOwnerIsGroup) ? LLMute::GROUP : LLMute::AGENT;
LLMute::EType mute_type = (self->mGroupOwned) ? LLMute::GROUP : LLMute::AGENT;
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0g
if ( (LLMute::GROUP != mute_type) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(self->mOwnerID)) )
{
@@ -171,7 +174,7 @@ void LLFloaterObjectIMInfo::onClickMute(void* data)
}
// [/RLVa:KB]
LLMute mute(self->mOwnerID, self->mOwnerName, mute_type);
LLMute mute(self->mOwnerID, self->mName, mute_type);
LLMuteList::getInstance()->add(mute);
LLFloaterMute::showInstance();
self->close();
@@ -180,49 +183,50 @@ void LLFloaterObjectIMInfo::onClickMute(void* data)
//static
void LLFloaterObjectIMInfo::nameCallback(const LLUUID& id, const std::string& full_name, bool is_group)
{
mOwnerName = full_name;
mName = full_name;
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0g
if ( (!is_group) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(id)) )
{
mOwnerName = RlvStrings::getAnonym(mOwnerName);
mName = RlvStrings::getAnonym(mName);
}
// [/RLVa:KB]
childSetText("OwnerName", mOwnerName);
}
////////////////////////////////////////////////////////////////////////////
// LLObjectIMInfo
void LLObjectIMInfo::show(const LLUUID &object_id, const std::string &name, const std::string &location, const LLUUID &owner_id, bool owner_is_group)
{
LLFloaterObjectIMInfo* im_info_floater = LLFloaterObjectIMInfo::showInstance();
im_info_floater->update(object_id,name,location,owner_id,owner_is_group);
childSetText("OwnerName", mName);
}
////////////////////////////////////////////////////////////////////////////
// LLObjectIMInfoHandler
//moved to llchathistory.cpp in v2
class LLObjectIMInfoHandler : public LLCommandHandler
{
public:
LLObjectIMInfoHandler() : LLCommandHandler("objectim", true) { }
LLObjectIMInfoHandler() : LLCommandHandler("objectim", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web);
bool handle(const LLSD& params, const LLSD& query_map,LLMediaCtrl* web)
{
if (params.size() < 1)
{
return false;
}
LLUUID object_id;
if (!object_id.set(params[0], FALSE))
{
return false;
}
LLSD payload;
payload["object_id"] = object_id;
payload["owner_id"] = query_map["owner"];
payload["name"] = query_map["name"];
payload["slurl"] = LLWeb::escapeURL(query_map["slurl"]);
payload["group_owned"] = query_map["groupowned"];
LLFloaterObjectIMInfo::showInstance()->update(payload);
return true;
}
};
// Creating the object registers with the dispatcher.
LLObjectIMInfoHandler gObjectIMHandler;
// ex. secondlife:///app/objectim/9426adfc-9c17-8765-5f09-fdf19957d003?owner=a112d245-9095-4e9c-ace4-ffa31717f934&groupowned=true&slurl=ahern/123/123/123&name=Object
bool LLObjectIMInfoHandler::handle(const LLSD &tokens, const LLSD &query_map, LLMediaCtrl* web)
{
LLUUID task_id = tokens[0].asUUID();
std::string name = query_map["name"].asString();
std::string slurl = query_map["slurl"].asString();
LLUUID owner = query_map["owner"].asUUID();
bool group_owned = query_map.has("groupowned");
LLObjectIMInfo::show(task_id,name,slurl,owner,group_owned);
return true;
}

View File

@@ -49,11 +49,12 @@
LLMap< const LLUUID, LLFloaterParcelInfo* > gPlaceInfoInstances;
//moved to llpanelplaces.cpp in v2
class LLParcelHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLParcelHandler() : LLCommandHandler("parcel", true) { }
LLParcelHandler() : LLCommandHandler("parcel", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{

View File

@@ -93,7 +93,7 @@ class LLPreferencesHandler : public LLCommandHandler
{
public:
// requires trusted browser
LLPreferencesHandler() : LLCommandHandler("preferences", true) { }
LLPreferencesHandler() : LLCommandHandler("preferences", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{
@@ -469,7 +469,7 @@ void LLFloaterPreference::onBtnOK( void* userdata )
llinfos << "Can't close preferences!" << llendl;
}
LLPanelLogin::refreshLocation( false );
LLPanelLogin::updateLocationSelectorsVisibility();
}
@@ -480,14 +480,14 @@ void LLFloaterPreference::onBtnApply( void* userdata )
if (fp->hasFocus())
{
LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
if (cur_focus->acceptsTextInput())
if (cur_focus && cur_focus->acceptsTextInput())
{
cur_focus->onCommit();
}
}
fp->apply();
LLPanelLogin::refreshLocation( false );
LLPanelLogin::updateLocationSelectorsVisibility();
}

View File

@@ -51,9 +51,11 @@
// viewer project includes
#include "llagent.h"
#include "llagentui.h"
#include "llbutton.h"
#include "lltexturectrl.h"
#include "llscrolllistctrl.h"
#include "llslurl.h"
#include "lldispatcher.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
@@ -122,7 +124,9 @@ void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
// virtual
BOOL LLFloaterReporter::postBuild()
{
getChild<LLUICtrl>("abuse_location_edit")->setValue(gAgent.getSLURL());
LLSLURL slurl;
LLAgentUI::buildSLURL(slurl);
getChild<LLUICtrl>("abuse_location_edit")->setValue(slurl.getSLURLString());
enableControls(TRUE);

View File

@@ -44,15 +44,17 @@
#include "llappviewer.h"
#include "llfloaterteleporthistory.h"
#include "llfloaterworldmap.h"
#include "llslurl.h"
#include "lltimer.h"
#include "lluictrlfactory.h"
#include "llurldispatcher.h"
#include "llurlsimstring.h"
#include "llviewercontrol.h"
#include "llviewerwindow.h"
#include "llwindow.h"
#include "llweb.h"
#include "llsdserialize.h"
#include "llurlaction.h"
// [RLVa:KB]
#include "rlvhandler.h"
// [/RLVa:KB]
@@ -137,12 +139,12 @@ void LLFloaterTeleportHistory::addPendingEntry(std::string regionName, S16 x, S1
// Set pending position
mPendingPosition = llformat("%d, %d, %d", x, y, z);
LLSLURL slurl(regionName, LLVector3(x, y, z));
// prepare simstring for later parsing
mPendingSimString = regionName + llformat("/%d/%d/%d", x, y, z);
mPendingSimString = LLWeb::escapeURL(mPendingSimString);
mPendingSimString = LLWeb::escapeURL(slurl.getLocationString());
// Prepare the SLURL
mPendingSLURL = LLURLDispatcher::buildSLURL(regionName, x, y, z);
mPendingSLURL = slurl.getSLURLString();
}
void LLFloaterTeleportHistory::addEntry(std::string parcelName)
@@ -332,9 +334,8 @@ void LLFloaterTeleportHistory::onTeleport(void* data)
LLFloaterTeleportHistory* self = (LLFloaterTeleportHistory*) data;
// build secondlife::/app link from simstring for instant teleport to destination
std::string slapp = "secondlife:///app/teleport/" + self->mPlacesList->getFirstSelected()->getColumn(LIST_SIMSTRING)->getValue().asString();
LLMediaCtrl* web = NULL;
LLURLDispatcher::dispatch(slapp, web, TRUE);
std::string slapp = "secondlife:///app/teleport/" + self->mPlacesList->getFirstSelected()->getColumn(LIST_SLURL)->getValue().asString();
LLUrlAction::teleportToLocation(slapp);
}
// static
@@ -344,15 +345,11 @@ void LLFloaterTeleportHistory::onShowOnMap(void* data)
// get simstring from selected entry and parse it for its components
std::string simString = self->mPlacesList->getFirstSelected()->getColumn(LIST_SIMSTRING)->getValue().asString();
std::string region = "";
S32 x = 128;
S32 y = 128;
S32 z = 20;
LLURLSimString::parse(simString, &region, &x, &y, &z);
LLSLURL slurl(simString);
// point world map at position
gFloaterWorldMap->trackURL(region, x, y, z);
gFloaterWorldMap->trackURL(slurl.getRegion(), slurl.getPosition().mV[VX], slurl.getPosition().mV[VY], slurl.getPosition().mV[VZ]);
LLFloaterWorldMap::show(true);
}

View File

@@ -32,12 +32,15 @@
#include "llviewerprecompiledheaders.h"
#include "llhttpclient.h"
#include "llfloaterurlentry.h"
#include "llpanellandmedia.h"
#include "llpanelface.h"
// project includes
#include "llcombobox.h"
#include "llmimetypes.h"
#include "llnotificationsutil.h"
#include "llurlhistory.h"
#include "lluictrlfactory.h"
@@ -83,7 +86,7 @@ public:
{
// Set empty type to none/none. Empty string is reserved for legacy parcels
// which have no mime type set.
std::string resolved_mime_type = ! mime_type.empty() ? mime_type : "none/none";
std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType();
LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get();
if ( floater_url_entry )
floater_url_entry->headerFetchComplete( status, resolved_mime_type );
@@ -165,6 +168,16 @@ void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_
panel_media->setMediaType(mime_type);
panel_media->setMediaURL(mMediaURLEdit->getValue().asString());
}
else
{
LLPanelFace* panel_face = dynamic_cast<LLPanelFace*>(mPanelLandMediaHandle.get());
if(panel_face)
{
panel_face->setMediaType(mime_type);
panel_face->setMediaURL(mMediaURLEdit->getValue().asString());
}
}
// Decrement the cursor
getWindow()->decBusyCount();
getChildView("loading_label")->setVisible( false);
@@ -172,26 +185,18 @@ void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_
}
// static
LLHandle<LLFloater> LLFloaterURLEntry::show(LLHandle<LLPanel> parent)
LLHandle<LLFloater> LLFloaterURLEntry::show(LLHandle<LLPanel> parent, const std::string media_url)
{
if (!sInstance)
{
sInstance = new LLFloaterURLEntry(parent);
}
sInstance->open();
sInstance->updateFromLandMediaPanel();
sInstance->addURLToCombobox(media_url);
return sInstance->getHandle();
}
void LLFloaterURLEntry::updateFromLandMediaPanel()
{
LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get();
if (panel_media)
{
std::string media_url = panel_media->getMediaURL();
addURLToCombobox(media_url);
}
}
bool LLFloaterURLEntry::addURLToCombobox(const std::string& media_url)
{

View File

@@ -44,10 +44,8 @@ class LLFloaterURLEntry : public LLFloater
public:
// Can only be shown by LLPanelLandMedia, and pushes data back into
// that panel via the handle.
static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle);
static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle, const std::string media_url);
/*virtual*/ BOOL postBuild();
void updateFromLandMediaPanel();
void headerFetchComplete(U32 status, const std::string& mime_type);
bool addURLToCombobox(const std::string& media_url);

View File

@@ -0,0 +1,517 @@
/**
* @file llfloaterwebcontent.cpp
* @brief floater for displaying web content - e.g. profiles and search (eventually)
*
* $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 "llcombobox.h"
#include "lliconctrl.h"
#include "lllayoutstack.h"
#include "llpluginclassmedia.h"
#include "llprogressbar.h"
#include "lltextbox.h"
#include "llurlhistory.h"
#include "llviewercontrol.h"
#include "llweb.h"
#include "llwindow.h"
#include "lluictrlfactory.h"
#include "llfloaterwebcontent.h"
LLFloaterWebContent::_Params::_Params()
: url("url"),
target("target"),
id("id"),
window_class("window_class", "web_content"),
show_chrome("show_chrome", true),
allow_address_entry("allow_address_entry", true),
preferred_media_size("preferred_media_size"),
trusted_content("trusted_content", false),
show_page_title("show_page_title", true)
{}
LLFloaterWebContent::LLFloaterWebContent( const Params& params )
: LLFloater( params.id ),
LLInstanceTracker<LLFloaterWebContent, std::string>(params.id()),
mWebBrowser(NULL),
mAddressCombo(NULL),
mSecureLockIcon(NULL),
mStatusBarText(NULL),
mStatusBarProgress(NULL),
mBtnBack(NULL),
mBtnForward(NULL),
mBtnReload(NULL),
mBtnStop(NULL),
mUUID(params.id()),
mShowPageTitle(params.show_page_title),
mKey(params)
{
mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_browser.xml");
mAgeTimer.reset();
}
BOOL LLFloaterWebContent::postBuild()
{
// these are used in a bunch of places so cache them
mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" );
mAddressCombo = getChild< LLComboBox >( "address" );
mStatusBarText = getChild< LLTextBox >( "statusbartext" );
mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" );
mBtnBack = getChildView( "back" );
mBtnForward = getChildView( "forward" );
mBtnReload = getChildView( "reload" );
mBtnStop = getChildView( "stop" );
// observe browser events
mWebBrowser->addObserver( this );
// these buttons are always enabled
mBtnReload->setEnabled( true );
getChildView("popexternal")->setEnabled( true );
// cache image for secure browsing
mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag");
// initialize the URL history using the system URL History manager
initializeURLHistory();
return TRUE;
}
void LLFloaterWebContent::initializeURLHistory()
{
// start with an empty list
LLCtrlListInterface* url_list = childGetListInterface("address");
if (url_list)
{
url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
// Get all of the entries in the "browser" collection
LLSD browser_history = LLURLHistory::getURLHistory("browser");
LLSD::array_iterator iter_history = browser_history.beginArray();
LLSD::array_iterator end_history = browser_history.endArray();
for(; iter_history != end_history; ++iter_history)
{
std::string url = (*iter_history).asString();
if(! url.empty())
url_list->addSimpleElement(url);
}
}
bool LLFloaterWebContent::matchesKey(const LLSD& key)
{
Params p(mKey);
Params other_p(key);
if (!other_p.target().empty() && other_p.target() != "_blank")
{
return other_p.target() == p.target();
}
else
{
return other_p.id() == p.id();
}
}
//static
void LLFloaterWebContent::showInstance(const std::string& window_class, Params& p)
{
p.window_class(window_class);
LLSD key = p;
instance_iter it = beginInstances();
for(;it!=endInstances();++it)
{
if(it->mKey["window_class"].asString() == window_class)
{
if(it->matchesKey(key))
{
it->mKey = key;
it->setKey(p.id());
it->mAgeTimer.reset();
it->open();
return;
}
}
}
LLFloaterWebContent* old_inst = getInstance(p.id());
if(old_inst)
{
llwarns << "Replacing unexpected duplicate floater: " << p.id() << llendl;
old_inst->mKey = key;
old_inst->mAgeTimer.reset();
old_inst->open();
}
assert(!old_inst);
if(!old_inst)
LLFloaterWebContent::create(p);
}
//static
LLFloater* LLFloaterWebContent::create( Params p)
{
preCreate(p);
return new LLFloaterWebContent(p);
}
//static
void LLFloaterWebContent::closeRequest(const std::string &uuid)
{
LLFloaterWebContent* floaterp = instance_tracker_t::getInstance(uuid);
if (floaterp)
{
floaterp->close();
}
}
//static
void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height)
{
LLFloaterWebContent* floaterp = instance_tracker_t::getInstance(uuid);
if (floaterp)
{
floaterp->geometryChanged(x, y, width, height);
}
}
void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
{
// Make sure the layout of the browser control is updated, so this calculation is correct.
getChild<LLLayoutStack>("stack1")->updateLayout();
// TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc.
LLCoordWindow window_size;
getWindow()->getSize(&window_size);
// Adjust width and height for the size of the chrome on the web Browser window.
LLRect browser_rect;
mWebBrowser->localRectToOtherView(mWebBrowser->getLocalRect(), &browser_rect, this);
S32 requested_browser_bottom = window_size.mY - (y + height);
LLRect geom;
geom.setOriginAndSize(x - browser_rect.mLeft,
requested_browser_bottom - browser_rect.mBottom,
width + getRect().getWidth() - browser_rect.getWidth(),
height + getRect().getHeight() - browser_rect.getHeight());
lldebugs << "geometry change: " << geom << llendl;
LLRect new_rect;
getParent()->screenRectToLocal(geom, &new_rect);
setShape(new_rect);
}
// static
void LLFloaterWebContent::preCreate(LLFloaterWebContent::Params& p)
{
lldebugs << "url = " << p.url() << ", target = " << p.target() << ", uuid = " << p.id() << llendl;
if (!p.id.isProvided())
{
p.id = LLUUID::generateNewID().asString();
}
if(p.target().empty() || p.target() == "_blank")
{
p.target = p.id();
}
S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit");
if(browser_window_limit != 0)
{
// showInstance will open a new window. Figure out how many web browsers are already open,
// and close the least recently opened one if this will put us over the limit.
std::vector<LLFloaterWebContent*> instances;
instances.reserve(instanceCount());
instance_iter it = beginInstances();
for(;it!=endInstances();++it)
{
if(it->mKey["window_class"].asString() == p.window_class.getValue())
instances.push_back(&*it);
}
std::sort(instances.begin(), instances.end(), CompareAgeDescending());
//LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList(p.window_class);
lldebugs << "total instance count is " << instances.size() << llendl;
for(std::vector<LLFloaterWebContent*>::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
{
lldebugs << " " << (*iter)->mKey["target"] << llendl;
}
if(instances.size() >= (size_t)browser_window_limit)
{
// Destroy the least recently opened instance
(*instances.begin())->close();
}
}
}
void LLFloaterWebContent::open_media(const Params& p)
{
// Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
LLViewerMedia::proxyWindowOpened(p.target(), p.id());
mWebBrowser->setHomePageUrl(p.url, "text/html");
mWebBrowser->setTarget(p.target);
mWebBrowser->navigateTo(p.url, "text/html");
set_current_url(p.url);
getChild<LLPanel>("status_bar")->setVisible(p.show_chrome);
getChild<LLPanel>("nav_controls")->setVisible(p.show_chrome);
bool address_entry_enabled = p.allow_address_entry && !p.trusted_content;
getChildView("address")->setEnabled(address_entry_enabled);
getChildView("popexternal")->setEnabled(address_entry_enabled);
if (!address_entry_enabled)
{
mWebBrowser->setFocus(TRUE);
}
if (!p.show_chrome)
{
setResizeLimits(100, 100);
}
if (!p.preferred_media_size().isEmpty())
{
getChild<LLLayoutStack>("stack1")->updateLayout();
LLRect browser_rect = mWebBrowser->calcScreenRect();
LLCoordWindow window_size;
getWindow()->getSize(&window_size);
geometryChanged(browser_rect.mLeft, window_size.mY - browser_rect.mTop, p.preferred_media_size().getWidth(), p.preferred_media_size().getHeight());
}
}
void LLFloaterWebContent::onOpen()
{
Params params(mKey);
if (!params.validateBlock())
{
close();
return;
}
mWebBrowser->setTrustedContent(params.trusted_content);
// tell the browser instance to load the specified URL
open_media(params);
}
//virtual
void LLFloaterWebContent::onClose(bool app_quitting)
{
LLViewerMedia::proxyWindowClosed(mUUID);
destroy();
}
// virtual
void LLFloaterWebContent::draw()
{
// this is asynchronous so we need to keep checking
mBtnBack->setEnabled( mWebBrowser->canNavigateBack() );
mBtnForward->setEnabled( mWebBrowser->canNavigateForward() );
LLFloater::draw();
}
// virtual
void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
{
if(event == MEDIA_EVENT_LOCATION_CHANGED)
{
const std::string url = self->getLocation();
if ( url.length() )
mStatusBarText->setText( url );
set_current_url( url );
}
else if(event == MEDIA_EVENT_NAVIGATE_BEGIN)
{
// flags are sent with this event
mBtnBack->setEnabled( self->getHistoryBackAvailable() );
mBtnForward->setEnabled( self->getHistoryForwardAvailable() );
// toggle visibility of these buttons based on browser state
mBtnReload->setVisible( false );
mBtnStop->setVisible( true );
// turn "on" progress bar now we're about to start loading
mStatusBarProgress->setVisible( true );
}
else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
{
// flags are sent with this event
mBtnBack->setEnabled( self->getHistoryBackAvailable() );
mBtnForward->setEnabled( self->getHistoryForwardAvailable() );
// toggle visibility of these buttons based on browser state
mBtnReload->setVisible( true );
mBtnStop->setVisible( false );
// turn "off" progress bar now we're loaded
mStatusBarProgress->setVisible( false );
// we populate the status bar with URLs as they change so clear it now we're done
const std::string end_str = "";
mStatusBarText->setText( end_str );
// decide if secure browsing icon should be displayed
std::string prefix = std::string("https://");
std::string test_prefix = mCurrentURL.substr(0, prefix.length());
LLStringUtil::toLower(test_prefix);
if(test_prefix == prefix)
{
mSecureLockIcon->setVisible(true);
}
else
{
mSecureLockIcon->setVisible(false);
}
}
else if(event == MEDIA_EVENT_CLOSE_REQUEST)
{
// The browser instance wants its window closed.
close();
}
else if(event == MEDIA_EVENT_GEOMETRY_CHANGE)
{
geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight());
}
else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED )
{
const std::string text = self->getStatusText();
if ( text.length() )
mStatusBarText->setText( text );
}
else if(event == MEDIA_EVENT_PROGRESS_UPDATED )
{
int percent = (int)self->getProgressPercent();
mStatusBarProgress->setValue( percent );
}
else if(event == MEDIA_EVENT_NAME_CHANGED )
{
std::string page_title = self->getMediaName();
// simulate browser behavior - title is empty, use the current URL
if (mShowPageTitle)
{
if ( page_title.length() > 0 )
setTitle( page_title );
else
setTitle( mCurrentURL );
}
}
else if(event == MEDIA_EVENT_LINK_HOVERED )
{
const std::string link = self->getHoverLink();
mStatusBarText->setText( link );
}
}
void LLFloaterWebContent::set_current_url(const std::string& url)
{
mCurrentURL = url;
// serialize url history into the system URL History manager
LLURLHistory::removeURL("browser", mCurrentURL);
LLURLHistory::addURL("browser", mCurrentURL);
mAddressCombo->remove( mCurrentURL );
mAddressCombo->add( mCurrentURL );
mAddressCombo->selectByValue( mCurrentURL );
}
void LLFloaterWebContent::onClickForward()
{
mWebBrowser->navigateForward();
}
void LLFloaterWebContent::onClickBack()
{
mWebBrowser->navigateBack();
}
void LLFloaterWebContent::onClickReload()
{
if( mWebBrowser->getMediaPlugin() )
{
bool ignore_cache = true;
mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache );
}
else
{
mWebBrowser->navigateTo(mCurrentURL);
}
}
void LLFloaterWebContent::onClickStop()
{
if( mWebBrowser->getMediaPlugin() )
mWebBrowser->getMediaPlugin()->browse_stop();
// still should happen when we catch the navigate complete event
// but sometimes (don't know why) that event isn't sent from Qt
// and we ghetto a point where the stop button stays active.
mBtnReload->setVisible( true );
mBtnStop->setVisible( false );
}
void LLFloaterWebContent::onEnterAddress()
{
// make sure there is at least something there.
// (perhaps this test should be for minimum length of a URL)
std::string url = mAddressCombo->getValue().asString();
if ( url.length() > 0 )
{
mWebBrowser->navigateTo( url, "text/html");
};
}
void LLFloaterWebContent::onPopExternal()
{
// make sure there is at least something there.
// (perhaps this test should be for minimum length of a URL)
std::string url = mAddressCombo->getValue().asString();
if ( url.length() > 0 )
{
LLWeb::loadURLExternal( url );
};
}

View File

@@ -0,0 +1,125 @@
/**
* @file llfloaterwebcontent.h
* @brief floater for displaying web content - e.g. profiles and search (eventually)
*
* $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$
*/
#ifndef LL_LLFLOATERWEBCONTENT_H
#define LL_LLFLOATERWEBCONTENT_H
#include "llfloater.h"
#include "llmediactrl.h"
#include "llsdparam.h"
class LLMediaCtrl;
class LLComboBox;
class LLTextBox;
class LLProgressBar;
class LLIconCtrl;
class LLFloaterWebContent :
public LLFloater,
public LLViewerMediaObserver,
public LLInstanceTracker<LLFloaterWebContent, std::string>
{
public:
typedef LLInstanceTracker<LLFloaterWebContent, std::string> instance_tracker_t;
LOG_CLASS(LLFloaterWebContent);
struct _Params : public LLInitParam::Block<_Params>
{
Optional<std::string> url,
target,
window_class,
id;
Optional<bool> show_chrome,
allow_address_entry,
trusted_content,
show_page_title;
Optional<LLRect> preferred_media_size;
_Params();
};
typedef LLSDParamAdapter<_Params> Params;
LLFloaterWebContent(const Params& params);
void initializeURLHistory();
static LLFloater* create(Params);
static void showInstance(const std::string& window_class, Params& p);
static void closeRequest(const std::string &uuid);
static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
void geometryChanged(S32 x, S32 y, S32 width, S32 height);
/* virtual */ BOOL postBuild();
/* virtual */ void onOpen();
/* virtual */ bool matchesKey(const LLSD& key);
/* virtual */ void onClose(bool app_quitting);
/* virtual */ void draw();
protected:
// inherited from LLViewerMediaObserver
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
void onClickBack();
void onClickForward();
void onClickReload();
void onClickStop();
void onEnterAddress();
void onPopExternal();
static void preCreate(Params& p);
void open_media(const Params& );
void set_current_url(const std::string& url);
LLMediaCtrl* mWebBrowser;
LLComboBox* mAddressCombo;
LLIconCtrl* mSecureLockIcon;
LLTextBox* mStatusBarText;
LLProgressBar* mStatusBarProgress;
LLView* mBtnBack;
LLView* mBtnForward;
LLView* mBtnReload;
LLView* mBtnStop;
std::string mCurrentURL;
std::string mUUID;
bool mShowPageTitle;
LLSD mKey;
LLTimer mAgeTimer;
struct CompareAgeDescending
{
bool operator()(const LLFloaterWebContent* const& lhs, const LLFloaterWebContent* const& rhs)
{
return lhs->mAgeTimer.getElapsedTimeF64() > lhs->mAgeTimer.getElapsedTimeF64();
}
};
};
#endif // LL_LLFLOATERWEBCONTENT_H

View File

@@ -75,6 +75,7 @@
#include "llmapimagetype.h"
#include "llweb.h"
#include "llwindow.h" // copyTextToClipboard()
#include "llslurl.h"
// [RLVa:KB]
@@ -728,7 +729,7 @@ void LLFloaterWorldMap::updateLocation()
// Figure out where user is
// Set the current SLURL
mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, x, y, z);
mSLURL = LLSLURL(agent_sim_name, LLVector3(x, y, z)).getSLURLString();
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
@@ -774,7 +775,7 @@ void LLFloaterWorldMap::updateLocation()
S32 x = llround( (F32)fmod( (F32)coord_pos[VX], (F32)REGION_WIDTH_METERS ) );
S32 y = llround( (F32)fmod( (F32)coord_pos[VY], (F32)REGION_WIDTH_METERS ) );
S32 z = llround( (F32)coord_pos[VZ] );
mSLURL = LLURLDispatcher::buildSLURL(sim_name, x, y, z);
mSLURL = LLSLURL(sim_name, LLVector3(x, y, z)).getSLURLString();
}
else
{ // Empty SLURL will disable the "Copy SLURL to clipboard" button

View File

@@ -36,8 +36,8 @@
// viewer includes
#include "llpanellogin.h" // save_password_to_disk()
#include "llslurl.h"
#include "llstartup.h" // getStartupState()
#include "llurlsimstring.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewernetwork.h" // EGridInfo
@@ -79,17 +79,15 @@ void LLLoginHandler::parse(const LLSD& queryMap)
if (startLocation == "specify")
{
LLURLSimString::setString(queryMap["region"].asString());
LLStartUp::setStartSLURL(queryMap["region"].asString());
}
else if (startLocation == "home")
{
gSavedSettings.setBOOL("LoginLastLocation", FALSE);
LLURLSimString::setString(LLStringUtil::null);
LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
}
else if (startLocation == "last")
{
gSavedSettings.setBOOL("LoginLastLocation", TRUE);
LLURLSimString::setString(LLStringUtil::null);
LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST));
}
}

View File

@@ -39,7 +39,7 @@ class LLLoginHandler : public LLCommandHandler
{
public:
// allow from external browsers
LLLoginHandler() : LLCommandHandler("login", false) { }
LLLoginHandler() : LLCommandHandler("login", UNTRUSTED_ALLOW) { }
/*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web);
// Fill in our internal fields from a SLURL like

File diff suppressed because it is too large Load Diff

View File

@@ -34,25 +34,50 @@
#define LL_LLMediaCtrl_H
#include "llviewermedia.h"
#include "llviewermediaobserver.h"
#include "lluictrl.h"
#include "llframetimer.h"
#include "lldynamictexture.h"
class LLViewBorder;
class LLWebBrowserTexture;
class LLUICtrlFactory;
////////////////////////////////////////////////////////////////////////////////
//
class LLMediaCtrl :
public LLUICtrl,
public LLPanel,
public LLViewerMediaObserver,
public LLViewerMediaEventEmitter,
public LLInstanceTracker<LLMediaCtrl, LLUUID>
{
public:
LLMediaCtrl( const std::string& name, const LLRect& rect );
LOG_CLASS(LLMediaCtrl);
public:
struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
Optional<std::string> start_url;
Optional<bool> border_visible,
hide_loading,
decouple_texture_size,
trusted_content,
focus_on_click;
Optional<S32> texture_width,
texture_height;
Optional<LLUIColor> caret_color;
Optional<std::string> initial_mime_type;
Optional<std::string> media_id;
Optional<std::string> error_page_url;
Params();
};
protected:
LLMediaCtrl(const Params&);
friend class LLUICtrlFactory;
public:
virtual ~LLMediaCtrl();
void setBorderVisible( BOOL border_visible );
@@ -74,6 +99,7 @@ class LLMediaCtrl :
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen);
// navigation
void navigateTo( std::string url_in, std::string mime_type = "");
@@ -83,8 +109,6 @@ class LLMediaCtrl :
void navigateToLocalPage( const std::string& subdir, const std::string& filename_in );
bool canNavigateBack();
bool canNavigateForward();
void setOpenInExternalBrowser( bool valIn );
void setOpenInInternalBrowser( bool valIn );
std::string getCurrentNavUrl();
// By default, we do not handle "secondlife:///app/" SLURLs, because
@@ -93,12 +117,17 @@ class LLMediaCtrl :
// Javascript or some other mechanism. However, we need the search
// floater and login page to handle these URLs. Those are safe
// because we control the page content. See DEV-9530. JC.
void setTrusted( bool valIn );
void setHomePageUrl( const std::string urlIn );
void setHomePageUrl( const std::string& urlIn, const std::string& mime_type = LLStringUtil::null );
std::string getHomePageUrl();
// set/clear URL to visit when a 404 page is reached
void setTarget(const std::string& target);
void setErrorPageURL(const std::string& url);
const std::string& getErrorPageURL();
// Clear the browser cache when the instance gets loaded
void clearCache();
void set404RedirectUrl( std::string redirect_url );
void clr404RedirectUrl();
@@ -106,9 +135,6 @@ class LLMediaCtrl :
bool getFrequentUpdates() { return mFrequentUpdates; };
void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; };
void setIgnoreUIScale(bool ignore) { mIgnoreUIScale = ignore; }
bool getIgnoreUIScale() { return mIgnoreUIScale; }
void setAlwaysRefresh(bool refresh) { mAlwaysRefresh = refresh; }
bool getAlwaysRefresh() { return mAlwaysRefresh; }
@@ -127,6 +153,11 @@ class LLMediaCtrl :
void setTextureSize(S32 width, S32 height);
void showNotification(boost::shared_ptr<class LLNotification> notify);
void hideNotification();
void setTrustedContent(bool trusted);
// over-rides
virtual BOOL handleKeyHere( KEY key, MASK mask);
virtual void handleVisibilityChange ( BOOL new_visibility );
@@ -142,80 +173,42 @@ class LLMediaCtrl :
// Incoming media event dispatcher
virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
// handlers for individual events (could be done inside the switch in handleMediaEvent, they're just individual functions for clarity)
void onClickLinkHref( LLPluginClassMedia* self );
void onClickLinkNoFollow( LLPluginClassMedia* self );
// right click debugging item
void onOpenWebInspector();
LLUUID getTextureID() {return mMediaTextureID;}
protected:
void convertInputCoords(S32& x, S32& y);
private:
void onVisibilityChange ( const LLSD& new_visibility );
static bool onClickLinkExternalTarget( const LLSD&, const LLSD& );
bool onPopup(const LLSD& notification, const LLSD& response);
const S32 mTextureDepthBytes;
LLUUID mMediaTextureID;
LLPointer<LLWebBrowserTexture> mWebBrowserImage;
LLViewBorder* mBorder;
bool mFrequentUpdates;
bool mForceUpdate;
bool mOpenLinksInExternalBrowser;
bool mOpenLinksInInternalBrowser;
bool mTrusted;
std::string mHomePageUrl;
std::string mExternalUrl;
std::string mCurrentNavUrl;
bool mIgnoreUIScale;
bool mAlwaysRefresh;
viewer_media_t mMediaSource;
bool mTakeFocusOnClick;
ECursorType mLastSetCursor;
bool mStretchToFill;
bool mMaintainAspectRatio;
bool mHideLoading;
bool mHidingInitialLoad;
bool mDecoupleTextureSize;
S32 mTextureWidth;
S32 mTextureHeight;
};
////////////////////////////////////////////////////////////////////////////////
//
class LLWebBrowserTexture : public LLViewerDynamicTexture
{
LOG_CLASS(LLWebBrowserTexture);
public:
LLWebBrowserTexture( S32 width, S32 height, LLMediaCtrl* browserCtrl, viewer_media_t media_source );
virtual ~LLWebBrowserTexture();
virtual BOOL needsRender();
virtual void preRender( BOOL clear_depth = TRUE ) {};
virtual void postRender( BOOL success ) {};
virtual BOOL render();
bool adjustSize();
S32 getMediaWidth();
S32 getMediaHeight();
bool getNeedsUpdate();
void setNeedsUpdate();
bool getTextureCoordsOpenGL();
void resize( S32 new_width, S32 new_height );
bool updateBrowserTexture();
protected:
S32 mMediaWidth;
S32 mMediaHeight;
bool mNeedsUpdate;
bool mNeedsResize;
bool mTextureCoordsOpenGL;
LLFrameTimer mElapsedTime;
LLMediaCtrl* mWebBrowserCtrl;
bool mFrequentUpdates,
mForceUpdate,
mTrusted,
mAlwaysRefresh,
mTakeFocusOnClick,
mStretchToFill,
mMaintainAspectRatio,
mHideLoading,
mHidingInitialLoad,
mClearCache,
mHoverTextChanged,
mDecoupleTextureSize;
std::string mHomePageUrl,
mHomePageMimeType,
mCurrentNavUrl,
mErrorPageURL,
mTarget;
viewer_media_t mMediaSource;
S32 mTextureWidth,
mTextureHeight;
};
#endif // LL_LLMediaCtrl_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,416 @@
/**
* @file llmediadataclient.h
* @brief class for queueing up requests to the media service
*
* $LicenseInfo:firstyear=2007&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$
*/
#ifndef LL_LLMEDIADATACLIENT_H
#define LL_LLMEDIADATACLIENT_H
#include "llhttpclient.h"
#include <set>
#include "llrefcount.h"
#include "llpointer.h"
#include "lleventtimer.h"
extern AIHTTPTimeoutPolicy mediaDataClientResponder_timeout;
// Link seam for LLVOVolume
class LLMediaDataClientObject : public LLRefCount
{
public:
// Get the number of media data items
virtual U8 getMediaDataCount() const = 0;
// Get the media data at index, as an LLSD
virtual LLSD getMediaDataLLSD(U8 index) const = 0;
// Return true if the current URL for the face in the media data matches the specified URL.
virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const = 0;
// Get this object's UUID
virtual LLUUID getID() const = 0;
// Navigate back to previous URL
virtual void mediaNavigateBounceBack(U8 index) = 0;
// Does this object have media?
virtual bool hasMedia() const = 0;
// Update the object's media data to the given array
virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0;
// Return the total "interest" of the media (on-screen area)
virtual F64 getMediaInterest() const = 0;
// Return the given cap url
virtual std::string getCapabilityUrl(const std::string &name) const = 0;
// Return whether the object has been marked dead
virtual bool isDead() const = 0;
// Returns a media version number for the object
virtual U32 getMediaVersion() const = 0;
// Returns whether the object is "interesting enough" to fetch
virtual bool isInterestingEnough() const = 0;
// Returns whether we've seen this object yet or not
virtual bool isNew() const = 0;
// smart pointer
typedef LLPointer<LLMediaDataClientObject> ptr_t;
};
// This object creates a priority queue for requests.
// Abstracts the Cap URL, the request, and the responder
class LLMediaDataClient : public LLRefCount
{
public:
LOG_CLASS(LLMediaDataClient);
const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
const static U32 MAX_RETRIES;// = 4;
const static U32 MAX_SORTED_QUEUE_SIZE;// = 10000;
const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000;
// Constructor
LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
U32 max_retries = MAX_RETRIES,
U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE);
F32 getRetryTimerDelay() const { return mRetryTimerDelay; }
// Returns true iff the queue is empty
virtual bool isEmpty() const;
// Returns true iff the given object is in the queue
virtual bool isInQueue(const LLMediaDataClientObject::ptr_t &object);
// Remove the given object from the queue. Returns true iff the given object is removed.
virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t &object);
// Called only by the Queue timer and tests (potentially)
virtual bool processQueueTimer();
protected:
// Destructor
virtual ~LLMediaDataClient(); // use unref
class Responder;
// Request (pure virtual base class for requests in the queue)
class Request : public LLRefCount
{
public:
// Subclasses must implement this to build a payload for their request type.
virtual LLSD getPayload() const = 0;
// and must create the correct type of responder.
virtual Responder *createResponder() = 0;
virtual std::string getURL() { return ""; }
enum Type {
GET,
UPDATE,
NAVIGATE,
ANY
};
protected:
// The only way to create one of these is through a subclass.
Request(Type in_type, LLMediaDataClientObject *obj, LLMediaDataClient *mdc, S32 face = -1);
public:
LLMediaDataClientObject *getObject() const { return mObject; }
U32 getNum() const { return mNum; }
U32 getRetryCount() const { return mRetryCount; }
void incRetryCount() { mRetryCount++; }
Type getType() const { return mType; }
F64 getScore() const { return mScore; }
// Note: may return empty string!
std::string getCapability() const;
const char *getCapName() const;
const char *getTypeAsString() const;
// Re-enqueue thyself
void reEnqueue();
F32 getRetryTimerDelay() const;
U32 getMaxNumRetries() const;
bool isObjectValid() const { return mObject.notNull() && (!mObject->isDead()); }
bool isNew() const { return isObjectValid() && mObject->isNew(); }
void updateScore();
void markDead();
bool isDead();
void startTracking();
void stopTracking();
friend std::ostream& operator<<(std::ostream &s, const Request &q);
const LLUUID &getID() const { return mObjectID; }
S32 getFace() const { return mFace; }
bool isMatch (const Request* other, Type match_type = ANY) const
{
return ((match_type == ANY) || (mType == other->mType)) &&
(mFace == other->mFace) &&
(mObjectID == other->mObjectID);
}
protected:
LLMediaDataClientObject::ptr_t mObject;
private:
Type mType;
// Simple tracking
U32 mNum;
static U32 sNum;
U32 mRetryCount;
F64 mScore;
LLUUID mObjectID;
S32 mFace;
// Back pointer to the MDC...not a ref!
LLMediaDataClient *mMDC;
};
typedef LLPointer<Request> request_ptr_t;
// Responder
class Responder : public LLHTTPClient::ResponderWithResult
{
public:
Responder(const request_ptr_t &request);
//If we get back an error (not found, etc...), handle it here
virtual void error(U32 status, const std::string& reason);
//If we get back a normal response, handle it here. Default just logs it.
virtual void result(const LLSD& content);
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return mediaDataClientResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "LLMediaDataClientResponder"; }
request_ptr_t &getRequest() { return mRequest; }
private:
request_ptr_t mRequest;
};
class RetryTimer : public LLEventTimer
{
public:
RetryTimer(F32 time, request_ptr_t);
virtual BOOL tick();
private:
// back-pointer
request_ptr_t mRequest;
};
protected:
typedef std::list<request_ptr_t> request_queue_t;
typedef std::set<request_ptr_t> request_set_t;
// Subclasses must override to return a cap name
virtual const char *getCapabilityName() const = 0;
// Puts the request into a queue, appropriately handling duplicates, etc.
virtual void enqueue(Request*) = 0;
virtual void serviceQueue();
virtual request_queue_t *getQueue() { return &mQueue; };
// Gets the next request, removing it from the queue
virtual request_ptr_t dequeue();
virtual bool canServiceRequest(request_ptr_t request) { return true; };
// Returns a request to the head of the queue (should only be used for requests that came from dequeue
virtual void pushBack(request_ptr_t request);
void trackRequest(request_ptr_t request);
void stopTrackingRequest(request_ptr_t request);
request_queue_t mQueue;
const F32 mQueueTimerDelay;
const F32 mRetryTimerDelay;
const U32 mMaxNumRetries;
const U32 mMaxSortedQueueSize;
const U32 mMaxRoundRobinQueueSize;
// Set for keeping track of requests that aren't in either queue. This includes:
// Requests that have been sent and are awaiting a response (pointer held by the Responder)
// Requests that are waiting for their retry timers to fire (pointer held by the retry timer)
request_set_t mUnQueuedRequests;
void startQueueTimer();
void stopQueueTimer();
private:
static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj);
friend std::ostream& operator<<(std::ostream &s, const Request &q);
friend std::ostream& operator<<(std::ostream &s, const request_queue_t &q);
class QueueTimer : public LLEventTimer
{
public:
QueueTimer(F32 time, LLMediaDataClient *mdc);
virtual BOOL tick();
private:
// back-pointer
LLPointer<LLMediaDataClient> mMDC;
};
void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
bool mQueueTimerIsRunning;
template <typename T> friend typename T::iterator find_matching_request(T &c, const LLMediaDataClient::Request *request, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY);
template <typename T> friend typename T::iterator find_matching_request(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY);
template <typename T> friend void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type = LLMediaDataClient::Request::ANY);
};
// MediaDataClient specific for the ObjectMedia cap
class LLObjectMediaDataClient : public LLMediaDataClient
{
public:
LOG_CLASS(LLObjectMediaDataClient);
LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
U32 max_retries = MAX_RETRIES,
U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries),
mCurrentQueueIsTheSortedQueue(true)
{}
void fetchMedia(LLMediaDataClientObject *object);
void updateMedia(LLMediaDataClientObject *object);
class RequestGet: public Request
{
public:
RequestGet(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
/*virtual*/ LLSD getPayload() const;
/*virtual*/ Responder *createResponder();
};
class RequestUpdate: public Request
{
public:
RequestUpdate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
/*virtual*/ LLSD getPayload() const;
/*virtual*/ Responder *createResponder();
};
// Returns true iff the queue is empty
virtual bool isEmpty() const;
// Returns true iff the given object is in the queue
virtual bool isInQueue(const LLMediaDataClientObject::ptr_t &object);
// Remove the given object from the queue. Returns true iff the given object is removed.
virtual void removeFromQueue(const LLMediaDataClientObject::ptr_t &object);
virtual bool processQueueTimer();
virtual bool canServiceRequest(request_ptr_t request);
protected:
// Subclasses must override to return a cap name
virtual const char *getCapabilityName() const;
virtual request_queue_t *getQueue();
// Puts the request into the appropriate queue
virtual void enqueue(Request*);
class Responder : public LLMediaDataClient::Responder
{
public:
Responder(const request_ptr_t &request)
: LLMediaDataClient::Responder(request) {}
virtual void result(const LLSD &content);
};
private:
// The Get/Update data client needs a second queue to avoid object updates starving load-ins.
void swapCurrentQueue();
request_queue_t mRoundRobinQueue;
bool mCurrentQueueIsTheSortedQueue;
// Comparator for sorting
static bool compareRequestScores(const request_ptr_t &o1, const request_ptr_t &o2);
void sortQueue();
};
// MediaDataClient specific for the ObjectMediaNavigate cap
class LLObjectMediaNavigateClient : public LLMediaDataClient
{
public:
LOG_CLASS(LLObjectMediaNavigateClient);
// NOTE: from llmediaservice.h
static const int ERROR_PERMISSION_DENIED_CODE = 8002;
LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
U32 max_retries = MAX_RETRIES,
U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
{}
void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
// Puts the request into the appropriate queue
virtual void enqueue(Request*);
class RequestNavigate: public Request
{
public:
RequestNavigate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc, U8 texture_index, const std::string &url);
/*virtual*/ LLSD getPayload() const;
/*virtual*/ Responder *createResponder();
/*virtual*/ std::string getURL() { return mURL; }
private:
std::string mURL;
};
protected:
// Subclasses must override to return a cap name
virtual const char *getCapabilityName() const;
class Responder : public LLMediaDataClient::Responder
{
public:
Responder(const request_ptr_t &request)
: LLMediaDataClient::Responder(request) {}
virtual void error(U32 status, const std::string& reason);
virtual void result(const LLSD &content);
private:
void mediaNavigateBounceBack();
};
};
#endif // LL_LLMEDIADATACLIENT_H

View File

@@ -610,7 +610,7 @@ BOOL LLPanelAvatarWeb::postBuild(void)
mWebBrowser->addObserver(this);
// links open in internally
mWebBrowser->setOpenInExternalBrowser( false );
//mWebBrowser->setOpenInExternalBrowser( false );
return TRUE;
}

View File

@@ -151,13 +151,9 @@ BOOL LLPanelDirFind::postBuild()
if (mWebBrowser)
{
mWebBrowser->addObserver(this);
// new pages appear in same window as the results page now
mWebBrowser->setOpenInInternalBrowser( false );
mWebBrowser->setOpenInExternalBrowser( false );
// need to handle secondlife:///app/ URLs for direct teleports
mWebBrowser->setTrusted( true );
mWebBrowser->setTrustedContent( true );
// redirect 404 pages from S3 somewhere else
mWebBrowser->set404RedirectUrl( getString("redirect_404_url") );

View File

@@ -53,6 +53,8 @@
#include "llface.h"
#include "llinventorymodel.h" //Perms check for texture params
#include "lllineeditor.h"
#include "llmediaentry.h"
#include "llnotificationsutil.h"
#include "llresmgr.h"
#include "llselectmgr.h"
#include "llspinctrl.h"
@@ -66,8 +68,10 @@
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llvovolume.h"
#include "lluictrlfactory.h"
#include "llpluginclassmedia.h"
#include "llviewertexturelist.h"
//
// Methods
@@ -549,20 +553,43 @@ void LLPanelFace::getState()
LLUUID id;
struct f1 : public LLSelectedTEGetFunctor<LLUUID>
{
LLUUID get(LLViewerObject* object, S32 te)
LLUUID get(LLViewerObject* object, S32 te_index)
{
LLUUID id;
//LLViewerTexture* image = object->getTEImage(te);
LLTextureEntry* image = object->getTE(te); //Singu Note: Use this instead of the above.
//The above actually returns LLViewerFetchedTexture::sDefaultImagep when
//the texture id is null, which gives us IMG_DEFAULT, not LLUUID::null
//Such behavior prevents the 'None' button from ever greying out in the face panel.
return image ? image->getID() : LLUUID::null;
LLTextureEntry* image = object->getTE(te_index); //Singu Note: Use this instead of the above.
//The above actually returns LLViewerFetchedTexture::sDefaultImagep when
//the texture id is null, which gives us IMG_DEFAULT, not LLUUID::null
//Such behavior prevents the 'None' button from ever greying out in the face panel.
if (image) id = image->getID();
if (!id.isNull() && LLViewerMedia::textureHasMedia(id))
{
LLTextureEntry *te = object->getTE(te_index);
if (te)
{
LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ;
if(!tex)
{
tex = LLViewerFetchedTexture::sDefaultImagep;
}
if (tex)
{
id = tex->getID();
}
}
}
return id;
}
} func;
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id );
if(LLViewerMedia::textureHasMedia(id))
{
getChildView("textbox autofix")->setEnabled(editable);
getChildView("button align")->setEnabled(editable);
}
if (identical)
{
// All selected have the same texture
@@ -593,13 +620,6 @@ void LLPanelFace::getState()
}
}
}
if(LLViewerMedia::textureHasMedia(id))
{
childSetEnabled("textbox autofix",editable);
childSetEnabled("button align",editable);
}
}
@@ -1149,9 +1169,21 @@ struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor
{
virtual bool apply(LLViewerObject* object, S32 te)
{
// TODO: the media impl pointer should actually be stored by the texture
viewer_media_t pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(object->getTE ( te )->getID());
// only do this if it's a media texture
viewer_media_t pMediaImpl;
const LLTextureEntry* tep = object->getTE(te);
const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
if ( mep )
{
pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
}
if ( pMediaImpl.isNull())
{
// If we didn't find face media for this face, check whether this face is showing parcel media.
pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(tep->getID());
}
if ( pMediaImpl.notNull())
{
LLPluginClassMedia *media = pMediaImpl->getMediaPlugin();
@@ -1183,6 +1215,17 @@ void LLPanelFace::onClickAutoFix(void* userdata)
LLPanelFaceSendFunctor sendfunc;
LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
}
// TODO: I don't know who put these in or what these are for???
void LLPanelFace::setMediaURL(const std::string& url)
{
}
void LLPanelFace::setMediaType(const std::string& mime_type)
{
}
// static
void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata)
{

View File

@@ -56,6 +56,8 @@ public:
virtual ~LLPanelFace();
void refresh();
void setMediaURL(const std::string& url);
void setMediaType(const std::string& mime_type);
protected:
void getState();
@@ -69,6 +71,7 @@ protected:
void sendShiny(); // applies and sends shininess
void sendFullbright(); // applies and sends full bright
void sendGlow();
void sendMedia();
// this function is to return TRUE if the dra should succeed.
static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item, void* ud);

View File

@@ -39,7 +39,6 @@
#include "llcolorswatch.h"
#include "llcombobox.h"
#include "lluictrlfactory.h"
#include "llurlsimstring.h"
#include "llviewercontrol.h"
#include "llagent.h"
@@ -165,8 +164,6 @@ void LLPanelGeneral::apply()
gSavedSettings.setBOOL("UIAutoScale", childGetValue("ui_auto_scale"));
gSavedSettings.setString("Language", childGetValue("language_combobox"));
LLURLSimString::setString(childGetValue("location_combobox"));
LLComboBox* crash_behavior_combobox = getChild<LLComboBox>("crash_behavior_combobox");
gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, crash_behavior_combobox->getCurrentIndex());
}

View File

@@ -92,6 +92,7 @@ BOOL LLPanelLandMedia::postBuild()
mMediaTextureCtrl->setCallbackUserData( this );
mMediaTextureCtrl->setAllowNoTexture ( TRUE );
mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mMediaTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mMediaAutoScaleCheck = getChild<LLCheckBoxCtrl>("media_auto_scale");
@@ -157,7 +158,7 @@ void LLPanelLandMedia::refresh()
std::string mime_type = parcel->getMediaType();
if (mime_type.empty())
{
mime_type = "none/none";
mime_type = LLMIMETypes::getDefaultMimeType();
}
setMediaType(mime_type);
mMediaTypeCombo->setEnabled( can_change_media );
@@ -203,17 +204,17 @@ void LLPanelLandMedia::refresh()
mSetURLButton->setEnabled( can_change_media );
mResetURLButton->setEnabled( can_change_media );
LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get();
/*LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get();
if (floater_url_entry)
{
floater_url_entry->updateFromLandMediaPanel();
}
}*/
}
}
void LLPanelLandMedia::populateMIMECombo()
{
std::string default_mime_type = "none/none";
std::string default_mime_type = LLMIMETypes::getDefaultMimeType();
std::string default_label;
LLMIMETypes::mime_widget_set_map_t::const_iterator it;
for (it = LLMIMETypes::sWidgetMap.begin(); it != LLMIMETypes::sWidgetMap.end(); ++it)
@@ -327,7 +328,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata)
void LLPanelLandMedia::onSetBtn(void *userdata)
{
LLPanelLandMedia *self = (LLPanelLandMedia *)userdata;
self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle() );
self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle(), self->getMediaURL() );
LLFloater* parent_floater = gFloaterView->getParentFloater(self);
if (parent_floater)
{

View File

@@ -45,6 +45,7 @@
#include "sgversion.h"
#include "v4color.h"
#include "llappviewer.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcommandhandler.h" // for secondlife:///app/login/
@@ -61,20 +62,17 @@
#include "llui.h"
#include "lluiconstants.h"
#include "llurlhistory.h" // OGPX : regionuri text box has a history of region uris (if FN/LN are loaded at startup)
#include "llurlsimstring.h"
#include "llviewerbuild.h"
#include "llviewertexturelist.h"
#include "llviewermenu.h" // for handle_preferences()
#include "llviewernetwork.h"
#include "llviewerwindow.h" // to link into child list
#include "llnotify.h"
#include "llurlsimstring.h"
#include "lluictrlfactory.h"
#include "llhttpclient.h"
#include "llweb.h"
#include "llmediactrl.h"
#include "llfloatermediabrowser.h"
#include "llfloatertos.h"
#include "llglheaders.h"
@@ -84,7 +82,6 @@
// [/RLVa:KB]
// <edit>
#include "llappviewer.h"
#include "llspinctrl.h"
#include "llviewermessage.h"
#include <boost/lexical_cast.hpp>
@@ -93,8 +90,6 @@
#include "llstring.h"
#include <cctype>
#define USE_VIEWER_AUTH 0
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy iamHereLogin_timeout;
@@ -149,7 +144,7 @@ class LLLoginRefreshHandler : public LLCommandHandler
{
public:
// don't allow from external browsers
LLLoginRefreshHandler() : LLCommandHandler("login_refresh", true) { }
LLLoginRefreshHandler() : LLCommandHandler("login_refresh", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
{
if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
@@ -202,11 +197,6 @@ namespace {
boost::intrusive_ptr< LLIamHereLogin > gResponsePtr = 0;
};
void set_start_location(LLUICtrl* ctrl, void* data)
{
LLURLSimString::setString(ctrl->getValue().asString());
}
//---------------------------------------------------------------------------
// Public methods
//---------------------------------------------------------------------------
@@ -216,8 +206,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
: LLPanel(std::string("panel_login"), LLRect(0,600,800,0), FALSE), // not bordered
mLogoImage(),
mCallback(callback),
mCallbackData(cb_data),
mHtmlAvailable( TRUE )
mCallbackData(cb_data)
{
setFocusRoot(TRUE);
@@ -244,13 +233,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_login.xml");
#if USE_VIEWER_AUTH
//leave room for the login menu bar
setRect(LLRect(0, rect.getHeight()-18, rect.getWidth(), 0));
#endif
reshape(rect.getWidth(), rect.getHeight());
#if !USE_VIEWER_AUTH
LLComboBox* name_combo = sInstance->getChild<LLComboBox>("name_combo");
name_combo->setCommitCallback(onSelectLoginEntry);
name_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLoginComboLostFocus, this, name_combo));
@@ -270,38 +254,41 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
sendChildToBack(getChildView("channel_text"));
sendChildToBack(getChildView("forgot_password_text"));
//OGPX : This keeps the uris in a history file
//OGPX TODO: should this be inside an OGP only check?
LLComboBox* regioncombo = getChild<LLComboBox>("regionuri_edit");
regioncombo->setAllowTextEntry(TRUE, 256, FALSE);
std::string current_regionuri = gSavedSettings.getString("CmdLineRegionURI");
// iterate on uri list adding to combobox (couldn't figure out how to add them all in one call)
// ... and also append the command line value we might have gotten to the URLHistory
LLSD regionuri_history = LLURLHistory::getURLHistory("regionuri");
LLSD::array_iterator iter_history = regionuri_history.beginArray();
LLSD::array_iterator iter_end = regionuri_history.endArray();
for (; iter_history != iter_end; ++iter_history)
{
regioncombo->addSimpleElement((*iter_history).asString());
}
if ( LLURLHistory::appendToURLCollection("regionuri",current_regionuri))
{
// since we are in login, another read of urlhistory file is going to happen
// so we need to persist the new value we just added (or maybe we should do it in startup.cpp?)
// since URL history only populated on create of sInstance, add to combo list directly
regioncombo->addSimpleElement(current_regionuri);
}
// select which is displayed if we have a current URL.
regioncombo->setSelectedByValue(LLSD(current_regionuri),TRUE);
//llinfos << " url history: " << LLSDOStreamer<LLSDXMLFormatter>(LLURLHistory::getURLHistory("regionuri")) << llendl;
LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
combo->setAllowTextEntry(TRUE, 128, FALSE);
LLComboBox* location_combo = getChild<LLComboBox>("start_location_combo");
updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
location_combo->setAllowTextEntry(TRUE, 128, FALSE);
location_combo->setFocusLostCallback( boost::bind(&LLPanelLogin::onLocationSLURL, this) );
LLComboBox *server_choice_combo = getChild<LLComboBox>("grids_combo");
server_choice_combo->setCommitCallback(boost::bind(&LLPanelLogin::onSelectGrid, _1));
// Load all of the grids, sorted, and then add a bar and the current grid at the top
updateGridCombo();
LLSLURL start_slurl(LLStartUp::getStartSLURL());
if ( !start_slurl.isSpatial() ) // has a start been established by the command line or NextLoginLocation ?
{
// no, so get the preference setting
std::string defaultStartLocation = gSavedSettings.getString("LoginLocation");
LL_INFOS("AppInit")<<"default LoginLocation '"<<defaultStartLocation<<"'"<<LL_ENDL;
LLSLURL defaultStart(defaultStartLocation);
if ( defaultStart.isSpatial() )
{
LLStartUp::setStartSLURL(defaultStart);
}
else
{
LL_INFOS("AppInit")<<"no valid LoginLocation, using home"<<LL_ENDL;
LLSLURL homeStart(LLSLURL::SIM_LOCATION_HOME);
LLStartUp::setStartSLURL(homeStart);
}
}
else
{
LLPanelLogin::onUpdateStartSLURL(start_slurl); // updates grid if needed
}
// The XML file loads the combo with the following labels:
// 0 - "My Home"
@@ -309,33 +296,29 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
// 2 - "<Type region name>"
BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation");
std::string sim_string = LLURLSimString::sInstance.mSimString;
std::string sim_string = start_slurl.getRegion();
if (!sim_string.empty())
{
// Replace "<Type region name>" with this region name
combo->remove(2);
combo->add( sim_string );
combo->setTextEntry(sim_string);
combo->setCurrentByIndex( 2 );
location_combo->remove(2);
location_combo->add( sim_string );
location_combo->setTextEntry(sim_string);
location_combo->setCurrentByIndex( 2 );
}
else if (login_last)
{
combo->setCurrentByIndex( 1 );
location_combo->setCurrentByIndex( 1 );
}
else
{
combo->setCurrentByIndex( 0 );
location_combo->setCurrentByIndex( 0 );
}
combo->setCommitCallback( &set_start_location );
childSetAction("connect_btn", onClickConnect, this);
setDefaultBtn("connect_btn");
// childSetAction("quit_btn", onClickQuit, this);
childSetAction("grids_btn", onClickGrids, this);
childSetCommitCallback("grids_combo", onSelectGrid, this);
std::string channel = gVersionChannel;
@@ -355,26 +338,13 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
LLTextBox* create_new_account_text = getChild<LLTextBox>("create_new_account_text");
create_new_account_text->setClickedCallback(boost::bind(&onClickNewAccount));
#endif
// get the web browser control
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
web_browser->addObserver(this);
// Need to handle login secondlife:///app/ URLs
web_browser->setTrusted( true );
// don't make it a tab stop until SL-27594 is fixed
web_browser->setTabStop(FALSE);
// web_browser->navigateToLocalPage( "loading", "loading.html" );
// make links open in external browser
web_browser->setOpenInExternalBrowser( true );
reshapeBrowser();
updateGridCombo();
childSetVisible("create_new_account_text",
!gHippoGridManager->getConnectedGrid()->getRegisterUrl().empty());
childSetVisible("forgot_password_text",
@@ -382,11 +352,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
loadLoginPage();
#if !USE_VIEWER_AUTH
// Initialize visibility (and don't force visibility - use prefs)
refreshLocation( false );
#endif
}
void LLPanelLogin::setSiteIsAlive( bool alive )
@@ -400,33 +365,16 @@ void LLPanelLogin::setSiteIsAlive( bool alive )
loadLoginPage();
web_browser->setVisible(true);
// mark as available
mHtmlAvailable = TRUE;
}
}
else
// the site is not available (missing page, server down, other badness)
{
#if !USE_VIEWER_AUTH
if ( web_browser )
{
// hide browser control (revealing default one)
web_browser->setVisible( FALSE );
// mark as unavailable
mHtmlAvailable = FALSE;
}
#else
if ( web_browser )
{
web_browser->navigateToLocalPage( "loading-error" , "index.html" );
// mark as available
mHtmlAvailable = TRUE;
}
#endif
}
}
@@ -454,13 +402,8 @@ void LLPanelLogin::reshapeBrowser()
LLRect rect = gViewerWindow->getWindowRectScaled();
LLRect html_rect;
html_rect.setCenterAndSize(
#if USE_VIEWER_AUTH
rect.getCenterX() - 2, rect.getCenterY(),
rect.getWidth() + 6, rect.getHeight());
#else
rect.getCenterX() - 2, rect.getCenterY() + 40,
rect.getWidth() + 6, rect.getHeight() - 78 );
#endif
rect.getCenterX() - 2, rect.getCenterY() + 40,
rect.getWidth() + 6, rect.getHeight() - 78 );
web_browser->setRect( html_rect );
web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE );
reshape( rect.getWidth(), rect.getHeight(), 1 );
@@ -474,9 +417,6 @@ LLPanelLogin::~LLPanelLogin()
if ( gResponsePtr )
gResponsePtr->setParent( 0 );
//// We know we're done with the image, so be rid of it.
//gTextureList.deleteImage( mLogoImage );
if ( gFocusMgr.getDefaultKeyboardFocus() == this )
{
gFocusMgr.setDefaultKeyboardFocus(NULL);
@@ -518,14 +458,13 @@ void LLPanelLogin::draw()
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
if ( mHtmlAvailable )
if ( getChild<LLView>("login_html")->getVisible())
{
#if !USE_VIEWER_AUTH
// draw a background box in black
gl_rect_2d( 0, height - 264, width, 264, LLColor4( 0.0f, 0.0f, 0.0f, 1.f ) );
// draw the bottom part of the background image - just the blue background to the native client UI
gl_rect_2d( 0, height - 264, width, 264, LLColor4::black );
// draw the bottom part of the background image
// just the blue background to the native client UI
mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight());
#endif
}
else
{
@@ -560,12 +499,13 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask)
return TRUE;
}
if ( KEY_F1 == key )
//Singu TODO: Re-implement f1 help.
/*if ( KEY_F1 == key )
{
llinfos << "Spawning HTML help window" << llendl;
gViewerHtmlHelp.show();
return TRUE;
}
}*/
# if !LL_RELEASE_FOR_DOWNLOAD
if ( KEY_F2 == key )
@@ -605,12 +545,6 @@ void LLPanelLogin::setFocus(BOOL b)
// static
void LLPanelLogin::giveFocus()
{
#if USE_VIEWER_AUTH
if (sInstance)
{
sInstance->setFocus(TRUE);
}
#else
if( sInstance )
{
// Grab focus and move cursor to first blank input field
@@ -621,12 +555,9 @@ void LLPanelLogin::giveFocus()
BOOL have_pass = !pass.empty();
LLLineEditor* edit = NULL;
LLUICtrl* combo = NULL;
if (have_username)
LLComboBox* combo = NULL;
if (have_username && !have_pass)
{
if(have_pass)
combo = sInstance->getChild<LLButton>("connect_btn");
else
// User saved his name but not his password. Move
// focus to password field.
edit = sInstance->getChild<LLLineEditor>("password_edit");
@@ -647,7 +578,6 @@ void LLPanelLogin::giveFocus()
combo->setFocus(TRUE);
}
}
#endif
}
@@ -770,7 +700,7 @@ void LLPanelLogin::getFields(std::string *firstname,
}
// static
void LLPanelLogin::getLocation(std::string &location)
/*void LLPanelLogin::getLocation(std::string &location)
{
if (!sInstance)
{
@@ -780,33 +710,14 @@ void LLPanelLogin::getLocation(std::string &location)
LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
location = combo->getValue().asString();
}
}*/
// static
void LLPanelLogin::refreshLocation( bool force_visible )
void LLPanelLogin::updateLocationSelectorsVisibility()
{
if (!sInstance) return;
#if USE_VIEWER_AUTH
loadLoginPage();
#else
LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
if (LLURLSimString::parse())
if (sInstance)
{
combo->setCurrentByIndex( 3 ); // BUG? Maybe 2?
combo->setTextEntry(LLURLSimString::sInstance.mSimString);
}
else
{
BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation");
combo->setCurrentByIndex( login_last ? 1 : 0 );
}
BOOL show_start = TRUE;
if ( ! force_visible )
show_start = gSavedSettings.getBOOL("ShowStartLocation");
BOOL show_start = gSavedSettings.getBOOL("ShowStartLocation");
// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-08 (RLVa-1.0.0e)
// TODO-RLVa: figure out some way to make this work with RLV_EXTENSION_STARTLOCATION
@@ -818,11 +729,61 @@ void LLPanelLogin::refreshLocation( bool force_visible )
#endif // RLV_EXTENSION_STARTLOCATION
// [/RLVa:KB]
sInstance->childSetVisible("start_location_combo", show_start); // maintain ShowStartLocation if legacy
sInstance->childSetVisible("start_location_text", show_start);
sInstance->childSetVisible("regionuri_edit",FALSE); // Do Not show regionuri box if legacy
sInstance->getChild<LLComboBox>("start_location_combo")->setVisible(show_start); // maintain ShowStartLocation if legacy
sInstance->getChild<LLTextBox>("start_location_text")->setVisible(show_start);
bool show_server = true;
sInstance->getChild<LLComboBox>("grids_combo")->setVisible(show_server);
sInstance->getChild<LLTextBox>("grids_text")->setVisible(show_server);
sInstance->getChild<LLButton>("grids_btn")->setVisible(show_server);
}
}
#endif
// static
void LLPanelLogin::onUpdateStartSLURL(const LLSLURL& new_start_slurl)
{
if (!sInstance) return;
LL_DEBUGS("AppInit")<<new_start_slurl.asString()<<LL_ENDL;
LLComboBox* location_combo = sInstance->getChild<LLComboBox>("start_location_combo");
/*
* Determine whether or not the new_start_slurl modifies the grid.
*
* Note that some forms that could be in the slurl are grid-agnostic.,
* such as "home". Other forms, such as
* https://grid.example.com/region/Party%20Town/20/30/5
* specify a particular grid; in those cases we want to change the grid
* and the grid selector to match the new value.
*/
enum LLSLURL::SLURL_TYPE new_slurl_type = new_start_slurl.getType();
switch ( new_slurl_type )
{
case LLSLURL::LOCATION:
{
location_combo->setCurrentByIndex( 2 );
location_combo->setTextEntry(new_start_slurl.getLocationString());
}
case LLSLURL::HOME_LOCATION:
location_combo->setCurrentByIndex( 0 ); // home location
break;
case LLSLURL::LAST_LOCATION:
location_combo->setCurrentByIndex( 1 ); // last location
break;
default:
LL_WARNS("AppInit")<<"invalid login slurl, using home"<<LL_ENDL;
location_combo->setCurrentByIndex(1); // home location
break;
}
updateLocationSelectorsVisibility();
}
void LLPanelLogin::setLocation(const LLSLURL& slurl)
{
LL_DEBUGS("AppInit")<<"setting Location "<<slurl.asString()<<LL_ENDL;
LLStartUp::setStartSLURL(slurl); // calls onUpdateStartSLURL, above
}
// static
@@ -830,9 +791,7 @@ void LLPanelLogin::close()
{
if (sInstance)
{
gViewerWindow->getRootView()->removeChild( LLPanelLogin::sInstance );
gFocusMgr.setDefaultKeyboardFocus(NULL);
LLPanelLogin::sInstance->getParent()->removeChild( LLPanelLogin::sInstance );
delete sInstance;
sInstance = NULL;
@@ -880,70 +839,39 @@ void LLPanelLogin::updateGridCombo()
}
}
// static
void LLPanelLogin::refreshLoginPage()
{
if (!sInstance || (LLStartUp::getStartupState() >= STATE_LOGIN_CLEANUP))
return;
sInstance->updateGridCombo();
sInstance->childSetVisible("create_new_account_text",
!gHippoGridManager->getConnectedGrid()->getRegisterUrl().empty());
sInstance->childSetVisible("forgot_password_text",
!gHippoGridManager->getConnectedGrid()->getPasswordUrl().empty());
// kick off a request to grab the url manually
gResponsePtr = LLIamHereLogin::build(sInstance);
std::string login_page = gHippoGridManager->getConnectedGrid()->getLoginPage();
if (!login_page.empty()) {
LLHTTPClient::head(login_page, gResponsePtr.get());
} else {
sInstance->setSiteIsAlive(false);
}
}
void LLPanelLogin::loadLoginPage()
{
if (!sInstance) return;
sInstance->updateGridCombo();
std::ostringstream login_uri;
sInstance->updateGridCombo();
std::string login_page = gHippoGridManager->getConnectedGrid()->getLoginPage();
if (login_page.empty())
std::string login_page_str = gHippoGridManager->getConnectedGrid()->getLoginPage();
if (login_page_str.empty())
{
sInstance->setSiteIsAlive(false);
return;
}
login_uri << login_page;
// Use the right delimeter depending on how LLURI parses the URL
LLURI login_page_uri = LLURI(login_page);
std::string first_query_delimiter = "&";
if (login_page_uri.queryMap().size() == 0)
LLURI login_page = LLURI(login_page_str);
LLSD params(login_page.queryMap());
LL_DEBUGS("AppInit") << "login_page: " << login_page << LL_ENDL;
// Language
params["lang"] = LLUI::getLanguage();
// First Login?
if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
{
first_query_delimiter = "?";
}
// Language
std::string language = LLUI::getLanguage();
login_uri << first_query_delimiter<<"lang=" << language;
// First Login?
if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
params["firstlogin"] = "TRUE"; // not bool: server expects string TRUE
}
if(login_page_str.find("secondlife.com") == -1)
{
login_uri << "&firstlogin=TRUE";
}
std::string version = llformat("%d.%d.%d (%d)",
gVersionMajor, gVersionMinor, gVersionPatch, gVersionBuild);
if(login_page.find("secondlife.com") == -1) {
login_uri << "&channel=" << LLWeb::curlEscape(gVersionChannel);
login_uri << "&version=" << LLWeb::curlEscape(version);
params["version"]= llformat("%d.%d.%d (%d)",
gVersionMajor, gVersionMinor, gVersionPatch, gVersionBuild);
params["channel"] = gVersionChannel;
}
// Grid
@@ -960,109 +888,35 @@ void LLPanelLogin::loadLoginPage()
i = tmp.rfind('/');
if (i != std::string::npos) {
tmp = tmp.substr(i+1);
login_uri << "&grid=" << LLWeb::curlEscape(tmp);
params["grid"] = tmp;
}
}
}
else if (gHippoGridManager->getConnectedGrid()->isOpenSimulator()){
login_uri << "&grid=" << gHippoGridManager->getConnectedGrid()->getGridNick();
else if (gHippoGridManager->getConnectedGrid()->isOpenSimulator())
{
params["grid"] = gHippoGridManager->getConnectedGrid()->getGridNick();
}
else if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_AURORA)
{
login_uri << "&grid=" << LLWeb::curlEscape(LLViewerLogin::getInstance()->getGridLabel());
params["grid"] = LLViewerLogin::getInstance()->getGridLabel();
}
// add OS info
params["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
// Make an LLURI with this augmented info
LLURI login_uri(LLURI::buildHTTP(login_page.authority(),
login_page.path(),
params));
gViewerWindow->setMenuBackgroundColor(false, !LLViewerLogin::getInstance()->isInProductionGrid());
gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
#if USE_VIEWER_AUTH
LLURLSimString::sInstance.parse();
std::string location;
std::string region;
std::string password;
if (LLURLSimString::parse())
{
std::ostringstream oRegionStr;
location = "specify";
oRegionStr << LLURLSimString::sInstance.mSimName << "/" << LLURLSimString::sInstance.mX << "/"
<< LLURLSimString::sInstance.mY << "/"
<< LLURLSimString::sInstance.mZ;
region = oRegionStr.str();
}
else
{
if (gSavedSettings.getBOOL("LoginLastLocation"))
{
location = "last";
}
else
{
location = "home";
}
}
std::string firstname, lastname;
if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
{
LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
firstname = cmd_line_login[0].asString();
lastname = cmd_line_login[1].asString();
password = cmd_line_login[2].asString();
}
if (firstname.empty())
{
firstname = gSavedSettings.getString("FirstName");
}
if (lastname.empty())
{
lastname = gSavedSettings.getString("LastName");
}
std::string curl_region = LLWeb::curlEscape(region);
login_uri <<"firstname=" << firstname <<
"&lastname=" << lastname << "&location=" << location << "&region=" << curl_region;
if (!password.empty())
{
login_uri << "&password=" << password;
}
else if (!(password = load_password_from_disk()).empty())
{
login_uri << "&password=$1$" << password;
}
if (gAutoLogin)
{
login_uri << "&auto_login=TRUE";
}
if (gSavedSettings.getBOOL("ShowStartLocation"))
{
login_uri << "&show_start_location=TRUE";
}
if (gSavedSettings.getBOOL("RememberPassword"))
{
login_uri << "&remember_password=TRUE";
}
BOOL show_server = sInstance ? sInstance->mShowServerCombo : FALSE;
if (show_server || gSavedSettings.getBOOL("ForceShowGrid"))
{
login_uri << "&show_grid=TRUE";
}
#endif
LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
if (web_browser->getCurrentNavUrl() != login_uri.str())
if (web_browser->getCurrentNavUrl() != login_uri.asString())
{
LL_DEBUGS("AppInit") << "loading: " << login_uri << LL_ENDL;
web_browser->navigateTo( login_uri.str(), "text/html" );
web_browser->navigateTo( login_uri.asString(), "text/html" );
}
}
@@ -1165,29 +1019,6 @@ void LLPanelLogin::onClickGrids(void*)
LLFloaterPreference::switchTab(LLPreferenceCore::TAB_GRIDS);
}
// static
void LLPanelLogin::onSelectGrid(LLUICtrl *ctrl, void*)
{
gHippoGridManager->setCurrentGrid(ctrl->getValue());
LLPanelLogin::refreshLoginPage();
}
// *NOTE: This function is dead as of 2008 August. I left it here in case
// we suddenly decide to put the Quit button back. JC
// static
void LLPanelLogin::onClickQuit(void*)
{
if (sInstance && sInstance->mCallback)
{
// tell the responder we're not here anymore
if ( gResponsePtr )
gResponsePtr->setParent( 0 );
sInstance->mCallback(1, sInstance->mCallbackData);
}
}
// static
void LLPanelLogin::onClickVersion(void*)
{
@@ -1218,6 +1049,49 @@ void LLPanelLogin::onPassKey(LLLineEditor* caller)
}
}
// static
//void LLPanelLogin::updateServer()
void LLPanelLogin::refreshLoginPage()
{
if (!sInstance || (LLStartUp::getStartupState() >= STATE_LOGIN_CLEANUP))
return;
sInstance->updateGridCombo();
sInstance->childSetVisible("create_new_account_text",
!gHippoGridManager->getConnectedGrid()->getRegisterUrl().empty());
sInstance->childSetVisible("forgot_password_text",
!gHippoGridManager->getConnectedGrid()->getPasswordUrl().empty());
// kick off a request to grab the url manually
gResponsePtr = LLIamHereLogin::build(sInstance);
std::string login_page = gHippoGridManager->getConnectedGrid()->getLoginPage();
if (!login_page.empty()) {
LLHTTPClient::head(login_page, gResponsePtr.get());
} else {
sInstance->setSiteIsAlive(false);
}
}
// static
//void LLPanelLogin::onSelectServer()
void LLPanelLogin::onSelectGrid(LLUICtrl *ctrl)
{
gHippoGridManager->setCurrentGrid(ctrl->getValue());
LLPanelLogin::refreshLoginPage();
}
void LLPanelLogin::onLocationSLURL()
{
LLComboBox* location_combo = getChild<LLComboBox>("start_location_combo");
std::string location = location_combo->getValue().asString();
LL_DEBUGS("AppInit")<<location<<LL_ENDL;
LLStartUp::setStartSLURL(location); // calls onUpdateStartSLURL, above
}
//Special handling of name combobox. Facilitates grid-changing by account selection.
// static
void LLPanelLogin::onSelectLoginEntry(LLUICtrl* ctrl, void* data)
{

View File

@@ -37,6 +37,7 @@
#include "llmemory.h" // LLPointer<>
#include "llmediactrl.h" // LLMediaCtrlObserver
#include "llsavedlogins.h"
#include "llslurl.h"
class LLUIImage;
class LLComboBox;
@@ -78,14 +79,12 @@ public:
*/
static void setFields(const LLSavedLoginEntry& entry, bool takeFocus = false);
//static void addServer(const std::string& server, S32 domain_name);
static void refreshLocation( bool force_visible );
static void getFields(std::string *firstname, std::string *lastname, std::string *password);
static void getFields(std::string *firstname, std::string *lastname,
std::string *password);
//static BOOL isGridComboDirty();
static void getLocation(std::string &location);
static void setLocation(const LLSLURL& slurl);
/// Call when preferences that control visibility may have changed
static void updateLocationSelectorsVisibility();
static void close();
@@ -102,19 +101,21 @@ public:
// inherited from LLViewerMediaObserver
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
/// to be called from LLStartUp::setStartSLURL
static void onUpdateStartSLURL(const LLSLURL& new_start_slurl);
private:
void reshapeBrowser();
void onLocationSLURL();
static void onClickConnect(void*);
static void onClickNewAccount();
static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response);
static void onClickGrids(void*);
static void onSelectGrid(LLUICtrl *ctrl, void*);
static void onClickQuit(void*);
static void onSelectGrid(LLUICtrl *ctrl);
static void onClickVersion(void*);
static void onClickForgotPassword();
static void onPassKey(LLLineEditor* caller);
//static void onSelectServer(LLUICtrl*, void*);
//static void onServerComboLostFocus(LLFocusableElement*, void*);
static void onSelectLoginEntry(LLUICtrl*, void*);
void onLoginComboLostFocus(LLComboBox* combo_box);
static void onNameCheckChanged(LLUICtrl* ctrl, void* data);
@@ -154,7 +155,6 @@ private:
static LLPanelLogin* sInstance;
static BOOL sCapslockDidNotification;
BOOL mHtmlAvailable;
LLSavedLogins mLoginHistoryData;
};

View File

@@ -1,664 +0,0 @@
/**
* @file llpanelmsgs.cpp
* @brief Message popup preferences panel
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* 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
*
* 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
*
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
//LLPanelMediaHUD
#include "llagent.h"
#include "llagentcamera.h"
#include "llparcel.h"
#include "llpanel.h"
#include "llselectmgr.h"
#include "llrender.h"
#include "lldrawable.h"
#include "llviewerwindow.h"
#include "llwindow.h"
#include "lluictrlfactory.h"
#include "llbutton.h"
#include "llface.h"
#include "llhudview.h"
#include "lliconctrl.h"
#include "lltoolpie.h"
#include "llviewercamera.h"
#include "llpanelmediahud.h"
#include "llpluginclassmedia.h"
#include "llviewercontrol.h"
#include "llviewerparcelmgr.h"
#include "llviewermedia.h"
#include "llviewermediafocus.h"
#include "llvovolume.h"
#include "llweb.h"
glh::matrix4f glh_get_current_modelview();
glh::matrix4f glh_get_current_projection();
const F32 ZOOM_NEAR_PADDING = 1.0f;
const F32 ZOOM_MEDIUM_PADDING = 1.2f;
const F32 ZOOM_FAR_PADDING = 1.5f;
//
// LLPanelMediaHUD
//
LLPanelMediaHUD::LLPanelMediaHUD(viewer_media_t media_impl)
: mMediaImpl(media_impl)
{
mMediaFocus = false;
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_hud.xml");
mMouseMoveTimer.reset();
mFadeTimer.stop();
mCurrentZoom = ZOOM_NONE;
mScrollState = SCROLL_NONE;
}
LLPanelMediaHUD::~LLPanelMediaHUD()
{
mMediaImpl = NULL;
}
BOOL LLPanelMediaHUD::postBuild()
{
LLButton* close_btn = getChild<LLButton>("close");
close_btn->setClickedCallback(onClickClose, this);
LLButton* back_btn = getChild<LLButton>("back");
back_btn->setClickedCallback(onClickBack, this);
LLButton* fwd_btn = getChild<LLButton>("fwd");
fwd_btn->setClickedCallback(onClickForward, this);
LLButton* home_btn = getChild<LLButton>("home");
home_btn->setClickedCallback(onClickHome, this);
LLButton* stop_btn = getChild<LLButton>("stop");
stop_btn->setClickedCallback(onClickStop, this);
LLButton* media_stop_btn = getChild<LLButton>("media_stop");
media_stop_btn->setClickedCallback(onClickStop, this);
LLButton* reload_btn = getChild<LLButton>("reload");
reload_btn->setClickedCallback(onClickReload, this);
LLButton* play_btn = getChild<LLButton>("play");
play_btn->setClickedCallback(onClickPlay, this);
LLButton* pause_btn = getChild<LLButton>("pause");
pause_btn->setClickedCallback(onClickPause, this);
LLButton* open_btn = getChild<LLButton>("new_window");
open_btn->setClickedCallback(onClickOpen, this);
LLButton* zoom_btn = getChild<LLButton>("zoom_frame");
zoom_btn->setClickedCallback(onClickZoom, this);
LLButton* open_btn_h = getChild<LLButton>("new_window_hover");
open_btn_h->setClickedCallback(onClickOpen, this);
LLButton* zoom_btn_h = getChild<LLButton>("zoom_frame_hover");
zoom_btn_h->setClickedCallback(onClickZoom, this);
LLButton* scroll_up_btn = getChild<LLButton>("scrollup");
scroll_up_btn->setClickedCallback(onScrollUp, this);
scroll_up_btn->setHeldDownCallback(onScrollUpHeld, this);
scroll_up_btn->setMouseUpCallback(onScrollStop, this);
LLButton* scroll_left_btn = getChild<LLButton>("scrollleft");
scroll_left_btn->setClickedCallback(onScrollLeft, this);
scroll_left_btn->setHeldDownCallback(onScrollLeftHeld, this);
scroll_left_btn->setMouseUpCallback(onScrollStop, this);
LLButton* scroll_right_btn = getChild<LLButton>("scrollright");
scroll_right_btn->setClickedCallback(onScrollRight, this);
scroll_right_btn->setHeldDownCallback(onScrollLeftHeld, this);
scroll_right_btn->setMouseUpCallback(onScrollStop, this);
LLButton* scroll_down_btn = getChild<LLButton>("scrolldown");
scroll_down_btn->setClickedCallback(onScrollDown, this);
scroll_down_btn->setHeldDownCallback(onScrollDownHeld, this);
scroll_down_btn->setMouseUpCallback(onScrollStop, this);
mMouseInactiveTime = gSavedSettings.getF32("MediaControlTimeout");
mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime");
mCurrentZoom = ZOOM_NONE;
// clicks on HUD buttons do not remove keyboard focus from media
setIsChrome(TRUE);
return TRUE;
}
void LLPanelMediaHUD::updateShape()
{
const S32 MIN_HUD_WIDTH=200;
const S32 MIN_HUD_HEIGHT=120;
LLPluginClassMedia* media_plugin = NULL;
if(mMediaImpl.notNull() && mMediaImpl->hasMedia())
{
media_plugin = mMediaImpl->getMediaPlugin();
}
// Early out for no media plugin
if(media_plugin == NULL)
{
setVisible(FALSE);
return;
}
LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
bool can_navigate = parcel->getMediaAllowNavigate();
// LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection();
LLSelectNode* nodep = mMediaFocus ? LLSelectMgr::getInstance()->getSelection()->getFirstNode() : LLSelectMgr::getInstance()->getHoverNode();
if(! nodep)
{
return;
}
setVisible(FALSE);
LLViewerObject* objectp = nodep->getObject();
if (objectp)
{
// Set the state of the buttons
LLButton* back_btn = getChild<LLButton>("back");
LLButton* fwd_btn = getChild<LLButton>("fwd");
LLButton* reload_btn = getChild<LLButton>("reload");
LLButton* play_btn = getChild<LLButton>("play");
LLButton* pause_btn = getChild<LLButton>("pause");
LLButton* stop_btn = getChild<LLButton>("stop");
LLButton* media_stop_btn = getChild<LLButton>("media_stop");
LLButton* home_btn = getChild<LLButton>("home");
LLButton* close_btn = getChild<LLButton>("close");
LLButton* open_btn = getChild<LLButton>("new_window");
LLPanel* media_focused_panel = getChild<LLPanel>("media_focused_controls");
LLPanel* media_hover_panel = getChild<LLPanel>("media_hover_controls");
back_btn->setVisible(true);
fwd_btn->setVisible(true);
reload_btn->setVisible(true);
stop_btn->setVisible(false);
home_btn->setVisible(true);
close_btn->setVisible(true);
open_btn->setVisible(true);
if(mMediaFocus)
{
back_btn->setEnabled(mMediaImpl->canNavigateBack() && can_navigate);
fwd_btn->setEnabled(mMediaImpl->canNavigateForward() && can_navigate);
stop_btn->setEnabled(can_navigate);
home_btn->setEnabled(can_navigate);
LLPluginClassMediaOwner::EMediaStatus result = media_plugin->getStatus();
if(media_plugin->pluginSupportsMediaTime())
{
reload_btn->setEnabled(FALSE);
reload_btn->setVisible(FALSE);
media_stop_btn->setVisible(TRUE);
home_btn->setVisible(FALSE);
back_btn->setEnabled(TRUE);
fwd_btn->setEnabled(TRUE);
switch(result)
{
case LLPluginClassMediaOwner::MEDIA_PLAYING:
play_btn->setEnabled(FALSE);
play_btn->setVisible(FALSE);
pause_btn->setEnabled(TRUE);
pause_btn->setVisible(TRUE);
media_stop_btn->setEnabled(TRUE);
break;
case LLPluginClassMediaOwner::MEDIA_PAUSED:
default:
pause_btn->setEnabled(FALSE);
pause_btn->setVisible(FALSE);
play_btn->setEnabled(TRUE);
play_btn->setVisible(TRUE);
media_stop_btn->setEnabled(FALSE);
break;
}
}
else
{
play_btn->setVisible(FALSE);
pause_btn->setVisible(FALSE);
media_stop_btn->setVisible(FALSE);
if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
{
reload_btn->setEnabled(FALSE);
reload_btn->setVisible(FALSE);
stop_btn->setEnabled(TRUE);
stop_btn->setVisible(TRUE);
}
else
{
reload_btn->setEnabled(TRUE);
reload_btn->setVisible(TRUE);
stop_btn->setEnabled(FALSE);
stop_btn->setVisible(FALSE);
}
}
}
media_focused_panel->setVisible(mMediaFocus);
media_hover_panel->setVisible(!mMediaFocus);
if(media_plugin == NULL)
// Handle Scrolling
switch (mScrollState)
{
case SCROLL_UP:
media_plugin->scrollEvent(0, -1, MASK_NONE);
break;
case SCROLL_DOWN:
media_plugin->scrollEvent(0, 1, MASK_NONE);
break;
case SCROLL_LEFT:
mMediaImpl->handleKeyHere(KEY_LEFT, MASK_NONE);
break;
case SCROLL_RIGHT:
mMediaImpl->handleKeyHere(KEY_RIGHT, MASK_NONE);
break;
case SCROLL_NONE:
default:
break;
}
LLBBox screen_bbox;
setVisible(TRUE);
glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview();
std::vector<LLVector3>::iterator vert_it;
std::vector<LLVector3>::iterator vert_end;
std::vector<LLVector3> vect_face;
LLVolume* volume = objectp->getVolume();
if (volume)
{
const LLVolumeFace& vf = volume->getVolumeFace(nodep->getLastSelectedTE());
const LLVector3* ext = (LLVector3*)vf.mExtents->getF32ptr();
LLVector3 center = (ext[0]+ext[1])*0.5f;
LLVector3 size = (ext[1]-ext[0])*0.5f;
LLVector3 vert[] =
{
center + size.scaledVec(LLVector3(1,1,1)),
center + size.scaledVec(LLVector3(-1,1,1)),
center + size.scaledVec(LLVector3(1,-1,1)),
center + size.scaledVec(LLVector3(-1,-1,1)),
center + size.scaledVec(LLVector3(1,1,-1)),
center + size.scaledVec(LLVector3(-1,1,-1)),
center + size.scaledVec(LLVector3(1,-1,-1)),
center + size.scaledVec(LLVector3(-1,-1,-1)),
};
LLVOVolume* vo = (LLVOVolume*) objectp;
for (U32 i = 0; i < 8; i++)
{
vect_face.push_back(vo->volumePositionToAgent(vert[i]));
}
}
vert_it = vect_face.begin();
vert_end = vect_face.end();
LLVector3 min = LLVector3(1,1,1);
LLVector3 max = LLVector3(-1,-1,-1);
for(; vert_it != vert_end; ++vert_it)
{
// project silhouette vertices into screen space
glh::vec3f screen_vert = glh::vec3f(vert_it->mV);
mat.mult_matrix_vec(screen_vert);
// add to screenspace bounding box
update_min_max(min, max, LLVector3(screen_vert.v));
}
LLCoordGL screen_min;
screen_min.mX = llround((F32)gViewerWindow->getWindowWidth() * (min.mV[VX] + 1.f) * 0.5f);
screen_min.mY = llround((F32)gViewerWindow->getWindowHeight() * (min.mV[VY] + 1.f) * 0.5f);
LLCoordGL screen_max;
screen_max.mX = llround((F32)gViewerWindow->getWindowWidth() * (max.mV[VX] + 1.f) * 0.5f);
screen_max.mY = llround((F32)gViewerWindow->getWindowHeight() * (max.mV[VY] + 1.f) * 0.5f);
// grow panel so that screenspace bounding box fits inside "media_region" element of HUD
LLRect media_hud_rect;
getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_hud_rect);
LLView* media_region = getChild<LLView>("media_region");
media_hud_rect.mLeft -= media_region->getRect().mLeft;
media_hud_rect.mBottom -= media_region->getRect().mBottom;
media_hud_rect.mTop += getRect().getHeight() - media_region->getRect().mTop;
media_hud_rect.mRight += getRect().getWidth() - media_region->getRect().mRight;
// keep all parts of HUD on-screen
media_hud_rect.intersectWith(getParent()->getLocalRect());
// If we had to clip the rect, don't display the border
childSetVisible("bg_image", false);
// clamp to minimum size, keeping centered
media_hud_rect.setCenterAndSize(media_hud_rect.getCenterX(), media_hud_rect.getCenterY(),
llmax(MIN_HUD_WIDTH, media_hud_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_hud_rect.getHeight()));
setShape(media_hud_rect);
// Test mouse position to see if the cursor is stationary
LLCoordWindow cursor_pos_window;
getWindow()->getCursorPosition(&cursor_pos_window);
// If last pos is not equal to current pos, the mouse has moved
// We need to reset the timer, and make sure the panel is visible
if(cursor_pos_window.mX != mLastCursorPos.mX ||
cursor_pos_window.mY != mLastCursorPos.mY ||
mScrollState != SCROLL_NONE)
{
mMouseMoveTimer.start();
mLastCursorPos = cursor_pos_window;
}
// Mouse has been stationary, but not for long enough to fade the UI
if(mMouseMoveTimer.getElapsedTimeF32() < mMouseInactiveTime)
{
// If we have started fading, reset the alpha values
if(mFadeTimer.getStarted())
{
F32 alpha = 1.0f;
setAlpha(alpha);
mFadeTimer.stop();
}
}
// If we need to start fading the UI (and we have not already started)
else if (!mFadeTimer.getStarted())
{
mFadeTimer.start();
}
}
}
/*virtual*/
void LLPanelMediaHUD::draw()
{
if(mFadeTimer.getStarted())
{
if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime)
{
setVisible(FALSE);
}
else
{
F32 time = mFadeTimer.getElapsedTimeF32();
F32 alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f);
setAlpha(alpha);
}
}
LLPanel::draw();
}
void LLPanelMediaHUD::setAlpha(F32 alpha)
{
LLViewQuery query;
LLView* query_view = mMediaFocus ? getChildView("media_focused_controls") : getChildView("media_hover_controls");
viewList_t children = query(query_view);
for (viewList_t::iterator child_iter = children.begin();
child_iter != children.end(); ++child_iter)
{
LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(*child_iter);
if (ctrl)
ctrl->setAlpha(alpha);
}
LLPanel::setAlpha(alpha);
}
BOOL LLPanelMediaHUD::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
}
bool LLPanelMediaHUD::isMouseOver()
{
if( ! getVisible() )
{
return false;
}
LLRect screen_rect;
LLCoordWindow cursor_pos_window;
getWindow()->getCursorPosition(&cursor_pos_window);
localRectToScreen(getLocalRect(), &screen_rect);
// screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
if(screen_rect.pointInRect(cursor_pos_window.mX, cursor_pos_window.mY))
{
return true;
}
return false;
}
//static
void LLPanelMediaHUD::onClickClose(void* user_data)
{
LLViewerMediaFocus::getInstance()->setFocusFace(FALSE, NULL, 0, NULL);
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if(this_panel->mCurrentZoom != ZOOM_NONE)
{
// gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
this_panel->mCurrentZoom = ZOOM_NONE;
}
this_panel->setVisible(FALSE);
}
//static
void LLPanelMediaHUD::onClickBack(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia())
{
if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime())
{
this_panel->mMediaImpl->getMediaPlugin()->start(-2.0);
}
else
{
this_panel->mMediaImpl->getMediaPlugin()->browse_back();
}
}
}
//static
void LLPanelMediaHUD::onClickForward(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia())
{
if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime())
{
this_panel->mMediaImpl->getMediaPlugin()->start(2.0);
}
else
{
this_panel->mMediaImpl->getMediaPlugin()->browse_forward();
}
}
}
//static
void LLPanelMediaHUD::onClickHome(void* user_data)
{
//LLViewerMedia::navigateHome();
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if(this_panel->mMediaImpl.notNull())
{
this_panel->mMediaImpl->navigateHome();
}
}
//static
void LLPanelMediaHUD::onClickOpen(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if(this_panel->mMediaImpl.notNull())
{
LLWeb::loadURL(this_panel->mMediaImpl->getMediaURL());
}
}
//static
void LLPanelMediaHUD::onClickReload(void* user_data)
{
//LLViewerMedia::navigateHome();
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
if(objectp && this_panel->mMediaImpl.notNull())
{
this_panel->mMediaImpl->navigateTo(objectp->getMediaURL());
}
}
//static
void LLPanelMediaHUD::onClickPlay(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia())
{
this_panel->mMediaImpl->getMediaPlugin()->start();
}
}
//static
void LLPanelMediaHUD::onClickPause(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia())
{
this_panel->mMediaImpl->getMediaPlugin()->pause();
}
}
//static
void LLPanelMediaHUD::onClickStop(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia())
{
if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime())
{
this_panel->mMediaImpl->getMediaPlugin()->stop();
}
else
{
this_panel->mMediaImpl->getMediaPlugin()->browse_stop();
}
}
}
//static
void LLPanelMediaHUD::onClickZoom(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
this_panel->nextZoomLevel();
}
void LLPanelMediaHUD::nextZoomLevel()
{
F32 zoom_padding = 0.0f;
S32 last_zoom_level = (S32)mCurrentZoom;
mCurrentZoom = (EZoomLevel)((last_zoom_level + 1) % (S32)ZOOM_END);
switch (mCurrentZoom)
{
case ZOOM_NONE:
{
gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
break;
}
case ZOOM_MEDIUM:
{
zoom_padding = ZOOM_MEDIUM_PADDING;
break;
}
default:
{
gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
break;
}
}
if (zoom_padding > 0.0f)
LLViewerMediaFocus::getInstance()->setCameraZoom(zoom_padding);
}
void LLPanelMediaHUD::onScrollUp(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if(this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia())
{
this_panel->mMediaImpl->getMediaPlugin()->scrollEvent(0, -1, MASK_NONE);
}
}
void LLPanelMediaHUD::onScrollUpHeld(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
this_panel->mScrollState = SCROLL_UP;
}
void LLPanelMediaHUD::onScrollRight(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if(this_panel->mMediaImpl.notNull())
{
this_panel->mMediaImpl->handleKeyHere(KEY_RIGHT, MASK_NONE);
}
}
void LLPanelMediaHUD::onScrollRightHeld(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
this_panel->mScrollState = SCROLL_RIGHT;
}
void LLPanelMediaHUD::onScrollLeft(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if(this_panel->mMediaImpl.notNull())
{
this_panel->mMediaImpl->handleKeyHere(KEY_LEFT, MASK_NONE);
}
}
void LLPanelMediaHUD::onScrollLeftHeld(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
this_panel->mScrollState = SCROLL_LEFT;
}
void LLPanelMediaHUD::onScrollDown(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
if(this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia())
{
this_panel->mMediaImpl->getMediaPlugin()->scrollEvent(0, 1, MASK_NONE);
}
}
void LLPanelMediaHUD::onScrollDownHeld(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
this_panel->mScrollState = SCROLL_DOWN;
}
void LLPanelMediaHUD::onScrollStop(void* user_data)
{
LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data);
this_panel->mScrollState = SCROLL_NONE;
}

View File

@@ -1,111 +0,0 @@
/**
* @file llpanelmediahud.h
* @brief Media hud panel
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* 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
*
* 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
*
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_PANELMEDIAHUD_H
#define LL_PANELMEDIAHUD_H
#include "llpanel.h"
#include "llviewermedia.h"
#include "llcoord.h"
class LLViewerMediaImpl;
class LLPanelMediaHUD : public LLPanel
{
public:
LLPanelMediaHUD(viewer_media_t media_impl);
virtual ~LLPanelMediaHUD();
/*virtual*/ BOOL postBuild();
virtual void draw();
virtual void setAlpha(F32 alpha);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
void updateShape();
bool isMouseOver();
void setMediaFocus(bool b) { mMediaFocus = b; }
void nextZoomLevel();
void resetZoomLevel() { mCurrentZoom = ZOOM_NONE; }
LLHandle<LLPanelMediaHUD> getHandle() const { return getDerivedHandle<LLPanelMediaHUD>(); }
void setMediaImpl(viewer_media_t media_impl) { mMediaImpl = media_impl; }
enum EZoomLevel
{
ZOOM_NONE = 0,
ZOOM_MEDIUM = 1,
ZOOM_END
};
enum EScrollDir
{
SCROLL_UP = 0,
SCROLL_DOWN,
SCROLL_LEFT,
SCROLL_RIGHT,
SCROLL_NONE
};
private:
static void onClickClose(void* user_data);
static void onClickBack(void* user_data);
static void onClickForward(void* user_data);
static void onClickHome(void* user_data);
static void onClickOpen(void* user_data);
static void onClickReload(void* user_data);
static void onClickPlay(void* user_data);
static void onClickPause(void* user_data);
static void onClickStop(void* user_data);
static void onClickZoom(void* user_data);
static void onScrollUp(void* user_data);
static void onScrollUpHeld(void* user_data);
static void onScrollLeft(void* user_data);
static void onScrollLeftHeld(void* user_data);
static void onScrollRight(void* user_data);
static void onScrollRightHeld(void* user_data);
static void onScrollDown(void* user_data);
static void onScrollDownHeld(void* user_data);
static void onScrollStop(void* user_data);
bool mMediaFocus;
LLMatrix4 mLastCameraMat;
EZoomLevel mCurrentZoom;
EScrollDir mScrollState;
LLCoordWindow mLastCursorPos;
LLFrameTimer mMouseMoveTimer;
LLFrameTimer mFadeTimer;
F32 mMouseInactiveTime;
F32 mControlFadeTime;
viewer_media_t mMediaImpl;
};
#endif // LL_PANELMEDIAHUD_H

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More