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:
@@ -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
356
indra/llcommon/llregistry.h
Normal 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
|
||||
342
indra/llcommon/llsdparam.cpp
Normal file
342
indra/llcommon/llsdparam.cpp
Normal 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
126
indra/llcommon/llsdparam.h
Normal 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
|
||||
|
||||
@@ -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/");
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -917,6 +917,7 @@ P(MPImportGetResponder);
|
||||
P(MPImportPostResponder);
|
||||
P(mapLayerResponder);
|
||||
P2(maturityPreferences, transfer_30s);
|
||||
P(mediaDataClientResponder);
|
||||
P(mediaTypeResponder);
|
||||
P(meshDecompositionResponder);
|
||||
P(meshHeaderResponder);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
682
indra/llui/lllayoutstack.cpp
Normal file
682
indra/llui/lllayoutstack.cpp
Normal 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
113
indra/llui/lllayoutstack.h
Normal 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
|
||||
@@ -1562,4 +1562,3 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
|
||||
s << notification.summarize();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
//
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
159
indra/llui/llurlaction.cpp
Normal 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
98
indra/llui/llurlaction.h
Normal 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
1188
indra/llui/llurlentry.cpp
Normal file
File diff suppressed because it is too large
Load Diff
429
indra/llui/llurlentry.h
Normal file
429
indra/llui/llurlentry.h
Normal 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
62
indra/llui/llurlmatch.cpp
Normal 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
105
indra/llui/llurlmatch.h
Normal 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
|
||||
263
indra/llui/llurlregistry.cpp
Normal file
263
indra/llui/llurlregistry.cpp
Normal 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;
|
||||
}
|
||||
97
indra/llui/llurlregistry.h
Normal file
97
indra/llui/llurlregistry.h
Normal 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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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$
|
||||
*/
|
||||
|
||||
|
||||
@@ -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$
|
||||
*/
|
||||
|
||||
|
||||
@@ -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), ¤tBounds);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define LL_LLFLOATER_NOTIFICATIONS_CONSOLE_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lllayoutstack.h"
|
||||
#include "llnotifications.h"
|
||||
|
||||
class LLFloaterNotificationConsole :
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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, ®ion, &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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
517
indra/newview/llfloaterwebcontent.cpp
Normal file
517
indra/newview/llfloaterwebcontent.cpp
Normal 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 );
|
||||
};
|
||||
}
|
||||
125
indra/newview/llfloaterwebcontent.h
Normal file
125
indra/newview/llfloaterwebcontent.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
1070
indra/newview/llmediadataclient.cpp
Normal file
1070
indra/newview/llmediadataclient.cpp
Normal file
File diff suppressed because it is too large
Load Diff
416
indra/newview/llmediadataclient.h
Normal file
416
indra/newview/llmediadataclient.h
Normal 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
|
||||
@@ -610,7 +610,7 @@ BOOL LLPanelAvatarWeb::postBuild(void)
|
||||
mWebBrowser->addObserver(this);
|
||||
|
||||
// links open in internally
|
||||
mWebBrowser->setOpenInExternalBrowser( false );
|
||||
//mWebBrowser->setOpenInExternalBrowser( false );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -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") );
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 << "®ion=" << 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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
1335
indra/newview/llpanelprimmediacontrols.cpp
Normal file
1335
indra/newview/llpanelprimmediacontrols.cpp
Normal file
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
Reference in New Issue
Block a user