Merge remote-tracking branch 'lirusaito/VoiceUpdate'

This commit is contained in:
Latif Khalifa
2013-06-27 23:31:46 +02:00
358 changed files with 27556 additions and 7624 deletions

View File

@@ -718,7 +718,14 @@
<key>UploadBakedTexture</key>
<boolean>true</boolean>
</map>
<key>ObjectMedia</key>
<boolean>false</boolean>
<key>ObjectMediaNavigate</key>
<boolean>false</boolean>
</map>
<key>messageBans</key>
<map>

View File

@@ -126,7 +126,7 @@ bool LLAudioEngine::init(const S32 num_channels, void* userdata)
// Initialize the decode manager
gAudioDecodeMgrp = new LLAudioDecodeMgr;
llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
LL_INFOS("AudioEngine") << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
return true;
}
@@ -228,6 +228,28 @@ std::string LLAudioEngine::getInternetStreamURL()
else return std::string();
}
void LLAudioEngine::checkStates()
{
#ifdef SHOW_ASSERT
for (S32 i = 0; i < MAX_BUFFERS; i++)
{
if (mBuffers[i])
{
bool buf_has_ref = false;
for (S32 j = 0; j < MAX_CHANNELS; j++)
{
if (mChannels[j])
{
if(mChannels[j]->mCurrentBufferp == mBuffers[i])
buf_has_ref = true;
}
}
if(buf_has_ref)
llassert(mBuffers[i]->mInUse);
}
}
#endif //SHOW_ASSERT
}
void LLAudioEngine::updateChannels()
{
@@ -239,8 +261,31 @@ void LLAudioEngine::updateChannels()
mChannels[i]->updateBuffer();
mChannels[i]->update3DPosition();
mChannels[i]->updateLoop();
#ifdef SHOW_ASSERT
if(mChannels[i]->getSource())
llassert(mChannels[i]->mCurrentBufferp == mChannels[i]->getSource()->getCurrentBuffer());
if(mChannels[i]->mCurrentBufferp)
{
bool found_buffer = false;
for (S32 j = 0; j < MAX_BUFFERS; j++)
{
if (mBuffers[j])
{
if(mChannels[i]->mCurrentBufferp == mBuffers[j])
found_buffer = true;
}
}
llassert(found_buffer);
if(!mChannels[i]->mCurrentBufferp->mInUse)
{
llassert(!mChannels[i]->isPlaying());
llassert(!mChannels[i]->isWaiting());
}
}
#endif //SHOW_ASSERT
}
}
checkStates();
}
static const F32 default_max_decode_time = .002f; // 2 ms
@@ -311,9 +356,15 @@ void LLAudioEngine::idle(F32 max_decode_time)
LLAudioChannel *channelp = getFreeChannel(max_priority);
if (channelp)
{
//llinfos << "Replacing source in channel due to priority!" << llendl;
max_sourcep->setChannel(channelp);
LL_DEBUGS("AudioEngine") << "Replacing source in channel due to priority!" << llendl;
llassert(max_sourcep->getChannel() == NULL);
llassert(channelp->mCurrentBufferp == NULL);
channelp->setSource(max_sourcep);
llassert(max_sourcep == channelp->getSource());
llassert(channelp->mCurrentBufferp == max_sourcep->getCurrentBuffer());
if (max_sourcep->isSyncSlave())
{
// A sync slave, it doesn't start playing until it's synced up with the master.
@@ -348,18 +399,22 @@ void LLAudioEngine::idle(F32 max_decode_time)
}
LLAudioChannel *channelp = sourcep->getChannel();
if (!channelp)
bool is_stopped = channelp && channelp->isPlaying();
if (is_stopped || (sourcep->isLoop() && channelp->mLoopedThisFrame))
{
// This sound isn't playing, so we just process move the queue
sourcep->mCurrentDatap = sourcep->mQueuedDatap;
sourcep->mQueuedDatap = NULL;
// Reset the timer so the source doesn't die.
sourcep->mAgeTimer.reset();
// Make sure we have the buffer set up if we just decoded the data
if (sourcep->mCurrentDatap)
if(is_stopped)
{
updateBufferForData(sourcep->mCurrentDatap);
// Reset the timer so the source doesn't die.
sourcep->mAgeTimer.reset();
// Make sure we have the buffer set up if we just decoded the data
if (sourcep->mCurrentDatap)
{
updateBufferForData(sourcep->mCurrentDatap);
}
}
// Actually play the associated data.
@@ -372,52 +427,6 @@ void LLAudioEngine::idle(F32 max_decode_time)
}
continue;
}
else
{
// Check to see if the current sound is done playing, or looped.
if (!channelp->isPlaying())
{
sourcep->mCurrentDatap = sourcep->mQueuedDatap;
sourcep->mQueuedDatap = NULL;
// Reset the timer so the source doesn't die.
sourcep->mAgeTimer.reset();
// Make sure we have the buffer set up if we just decoded the data
if (sourcep->mCurrentDatap)
{
updateBufferForData(sourcep->mCurrentDatap);
}
// Actually play the associated data.
sourcep->setupChannel();
channelp = sourcep->getChannel();
if (channelp)
{
channelp->updateBuffer();
channelp->play();
}
}
else if (sourcep->isLoop())
{
// It's a loop, we need to check and see if we're done with it.
if (channelp->mLoopedThisFrame)
{
sourcep->mCurrentDatap = sourcep->mQueuedDatap;
sourcep->mQueuedDatap = NULL;
// Actually, should do a time sync so if we're a loop master/slave
// we don't drift away.
sourcep->setupChannel();
channelp = sourcep->getChannel();
if (channelp)
{
channelp->updateBuffer();
channelp->play();
}
}
}
}
}
// Lame, update the channels AGAIN.
@@ -491,7 +500,7 @@ void LLAudioEngine::idle(F32 max_decode_time)
{
if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f)
{
//llinfos << "Flushing unused buffer!" << llendl;
LL_DEBUGS("AudioEngine") << "Flushing unused buffer!" << llendl;
mBuffers[i]->mAudioDatap->mBufferp = NULL;
delete mBuffers[i];
mBuffers[i] = NULL;
@@ -572,6 +581,8 @@ void LLAudioEngine::enableWind(bool enable)
LLAudioBuffer * LLAudioEngine::getFreeBuffer()
{
//checkStates(); //Fails
S32 i;
for (i = 0; i < MAX_BUFFERS; i++)
{
@@ -582,6 +593,7 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()
}
}
//checkStates(); // Fails
// Grab the oldest unused buffer
F32 max_age = -1.f;
@@ -601,10 +613,11 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()
}
}
//checkStates(); //Fails
if (buffer_id >= 0)
{
lldebugs << "Taking over unused buffer " << buffer_id << llendl;
//llinfos << "Flushing unused buffer!" << llendl;
LL_DEBUGS("AudioEngine") << "Taking over unused buffer! max_age=" << max_age << llendl;
mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL;
for (U32 i = 0; i < MAX_CHANNELS; i++)
{
@@ -612,12 +625,15 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()
if(channelp && channelp->mCurrentBufferp == mBuffers[buffer_id])
{
channelp->cleanup();
llassert(channelp->mCurrentBufferp == NULL);
}
}
delete mBuffers[buffer_id];
mBuffers[buffer_id] = createBuffer();
return mBuffers[buffer_id];
}
//checkStates(); //Fails
return NULL;
}
@@ -638,6 +654,7 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
// Channel is allocated but not playing right now, use it.
if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting())
{
LL_DEBUGS("AudioEngine") << "Replacing unused channel" << llendl;
mChannels[i]->cleanup();
if (mChannels[i]->getSource())
{
@@ -670,9 +687,9 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
return NULL;
}
LL_DEBUGS("AudioEngine") << "Flushing min channel" << llendl;
// Flush the minimum priority channel, and return it.
min_channelp->cleanup();
min_channelp->getSource()->setChannel(NULL);
return min_channelp;
}
@@ -1006,10 +1023,13 @@ LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid)
if( sourcep && sourcep->getCurrentData() && sourcep->getCurrentData()->getID() == audio_uuid )
{
LLAudioChannel* chan=sourcep->getChannel();
delete sourcep;
if(chan)
{
LL_DEBUGS("AudioEngine") << "removeAudioData" << llendl;
chan->cleanup();
mAllSources.erase(iter2++);
}
delete sourcep;
mAllSources.erase(iter2++);
}
else
++iter2;
@@ -1043,7 +1063,7 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
iter = mAllSources.find(asp->getID());
if (iter == mAllSources.end())
{
llwarns << "Cleaning up unknown audio source!" << llendl;
LL_WARNS("AudioEngine") << "Cleaning up unknown audio source!" << llendl;
return;
}
delete asp;
@@ -1264,7 +1284,7 @@ void LLAudioEngine::startNextTransfer()
if (asset_id.notNull())
{
llinfos << "Getting asset data for: " << asset_id << llendl;
LL_DEBUGS("AudioEngine") << "Getting asset data for: " << asset_id << llendl;
gAudiop->mCurrentTransfer = asset_id;
gAudiop->mCurrentTransferTimer.reset();
gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND,
@@ -1282,7 +1302,7 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
{
if (result_code)
{
llinfos << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl;
LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl;
// Need to mark data as bad to avoid constant rerequests.
LLAudioData *adp = gAudiop->getAudioData(uuid);
if (adp)
@@ -1299,7 +1319,7 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
if (!adp)
{
// Should never happen
llwarns << "Got asset callback without audio data for " << uuid << llendl;
LL_WARNS("AudioEngine") << "Got asset callback without audio data for " << uuid << llendl;
}
else
{
@@ -1360,8 +1380,7 @@ LLAudioSource::~LLAudioSource()
if (mChannelp)
{
// Stop playback of this sound
mChannelp->setSource(NULL);
setChannel(NULL);
mChannelp->cleanup();
}
}
@@ -1404,7 +1423,7 @@ void LLAudioSource::update()
}
else if (adp->hasCompletedDecode()) // Only mark corrupted after decode is done
{
llwarns << "Marking LLAudioSource corrupted for " << adp->getID() << llendl;
LL_WARNS("AudioEngine") << "Marking LLAudioSource corrupted for " << adp->getID() << llendl;
mCorrupted = true ;
}
}
@@ -1463,6 +1482,8 @@ bool LLAudioSource::setupChannel()
}
mChannelp->setSource(this);
llassert(this == mChannelp->getSource());
llassert(mChannelp->mCurrentBufferp == getCurrentBuffer());
return true;
}
@@ -1474,8 +1495,8 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
{
if (getChannel())
{
llassert(this == getChannel()->getSource());
getChannel()->setSource(NULL);
setChannel(NULL);
if (!isMuted())
{
mCurrentDatap = NULL;
@@ -1727,13 +1748,20 @@ LLAudioChannel::LLAudioChannel() :
LLAudioChannel::~LLAudioChannel()
{
llassert(mCurrentBufferp == NULL);
// Need to disconnect any sources which are using this channel.
//llinfos << "Cleaning up audio channel" << llendl;
if (mCurrentSourcep)
{
cleanup();
}
void LLAudioChannel::cleanup()
{
if(mCurrentSourcep)
mCurrentSourcep->setChannel(NULL);
}
mCurrentBufferp = NULL;
mCurrentSourcep = NULL;
mWaiting = false;
}
@@ -1744,22 +1772,21 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep)
if (!sourcep)
{
// Clearing the source for this channel, don't need to do anything.
//llinfos << "Clearing source for channel" << llendl;
LL_DEBUGS("AudioEngine") << "Clearing source for channel" << llendl;
cleanup();
mCurrentSourcep = NULL;
mWaiting = false;
return;
}
if (sourcep == mCurrentSourcep)
{
// Don't reallocate the channel, this will make FMOD goofy.
//llinfos << "Calling setSource with same source!" << llendl;
LL_DEBUGS("AudioEngine") << "Calling setSource with same source!" << llendl;
}
cleanup();
mCurrentSourcep = sourcep;
mCurrentSourcep->setChannel(this);
updateBuffer();
update3DPosition();
}
@@ -1796,7 +1823,12 @@ bool LLAudioChannel::updateBuffer()
// The source changed what buffer it's playing. We need to clean up
// the existing channel
//
LLAudioSource* source = mCurrentSourcep;
cleanup();
mCurrentSourcep = source;
mCurrentSourcep->setChannel(this);
llassert(mCurrentBufferp == NULL);
mCurrentBufferp = bufferp;
if (bufferp)
@@ -1856,7 +1888,7 @@ bool LLAudioData::load()
if (mBufferp)
{
// We already have this sound in a buffer, don't do anything.
llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl;
LL_INFOS("AudioEngine") << "Already have a buffer for this sound, don't bother loading!" << llendl;
return true;
}
@@ -1864,7 +1896,7 @@ bool LLAudioData::load()
if (!mBufferp)
{
// No free buffers, abort.
lldebugs << "Not able to allocate a new audio buffer, aborting." << llendl;
LL_DEBUGS("AudioEngine") << "Not able to allocate a new audio buffer, aborting." << llendl;
return false;
}

View File

@@ -189,6 +189,8 @@ public:
static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status);
friend class LLPipeline; // For debugging
void checkStates();
public:
F32 mMaxWindGain; // Hack. Public to set before fade in?
@@ -447,7 +449,7 @@ public:
protected:
virtual void play() = 0;
virtual void playSynced(LLAudioChannel *channelp) = 0;
virtual void cleanup() = 0;
virtual void cleanup();
void setWaiting(bool waiting) { mWaiting = waiting; }
public:

View File

@@ -576,6 +576,7 @@ void LLAudioChannelFMOD::updateLoop()
void LLAudioChannelFMOD::cleanup()
{
LLAudioChannel::cleanup();
if (!mChannelID)
{
//llinfos << "Aborting cleanup with no channelID." << llendl;
@@ -588,7 +589,6 @@ void LLAudioChannelFMOD::cleanup()
LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
}
mCurrentBufferp = NULL;
mChannelID = 0;
}

View File

@@ -70,12 +70,172 @@ bool attemptDelayLoad()
}
#endif
static bool sVerboseDebugging = false;
FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0};
LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler)
//This class is designed to keep track of all sound<->channel assocations.
//Used to verify validity of sound and channel pointers, as well as catch cases were sounds
//are released with active channels still attached.
class CFMODSoundChecks
{
typedef std::map<FMOD::Sound*,std::set<FMOD::Channel*> > active_sounds_t;
typedef std::set<FMOD::Sound*> dead_sounds_t;
typedef std::map<FMOD::Channel*,FMOD::Sound*> active_channels_t;
typedef std::map<FMOD::Channel*,FMOD::Sound*> dead_channels_t;
active_sounds_t mActiveSounds;
dead_sounds_t mDeadSounds;
active_channels_t mActiveChannels;
dead_channels_t mDeadChannels;
public:
enum STATUS
{
ACTIVE,
DEAD,
UNKNOWN
};
STATUS getPtrStatus(LLAudioChannelFMODEX* channel)
{
if(!channel)
return UNKNOWN;
return getPtrStatus(channel->mChannelp);
}
STATUS getPtrStatus(LLAudioBufferFMODEX* sound)
{
if(!sound)
return UNKNOWN;
return getPtrStatus(sound->mSoundp);
}
STATUS getPtrStatus(FMOD::Channel* channel)
{
if(!channel)
return UNKNOWN;
else if(mActiveChannels.find(channel) != mActiveChannels.end())
return ACTIVE;
else if(mDeadChannels.find(channel) != mDeadChannels.end())
return DEAD;
return UNKNOWN;
}
STATUS getPtrStatus(FMOD::Sound* sound)
{
if(!sound)
return UNKNOWN;
if(mActiveSounds.find(sound) != mActiveSounds.end())
return ACTIVE;
else if(mDeadSounds.find(sound) != mDeadSounds.end())
return DEAD;
return UNKNOWN;
}
void addNewSound(FMOD::Sound* sound)
{
llassert(getPtrStatus(sound) != ACTIVE);
mDeadSounds.erase(sound);
mActiveSounds.insert(std::make_pair(sound,std::set<FMOD::Channel*>()));
}
void removeSound(FMOD::Sound* sound)
{
#ifdef SHOW_ASSERT
STATUS status = getPtrStatus(sound);
llassert(status != DEAD);
llassert(status != UNKNOWN);
#endif
active_sounds_t::const_iterator it = mActiveSounds.find(sound);
llassert(it != mActiveSounds.end());
if(it != mActiveSounds.end())
{
if(!it->second.empty())
{
#ifdef LL_RELEASE_FOR_DOWNLOAD
LL_WARNS("AudioImpl") << "Removing sound " << sound << " with attached channels: \n";
#else
LL_ERRS("AudioImpl") << "Removing sound " << sound << " with attached channels: \n";
#endif
for(std::set<FMOD::Channel*>::iterator it2 = it->second.begin(); it2 != it->second.end();++it2)
{
switch(getPtrStatus(*it2))
{
case ACTIVE:
llcont << " Channel " << *it2 << " ACTIVE\n";
break;
case DEAD:
llcont << " Channel " << *it2 << " DEAD\n";
break;
default:
llcont << " Channel " << *it2 << " UNKNOWN\n";
}
}
llcont << llendl;
}
mDeadSounds.insert(sound);
mActiveSounds.erase(sound);
}
}
void addNewChannelToSound(FMOD::Sound* sound,FMOD::Channel* channel)
{
STATUS status = getPtrStatus(sound);
llassert(status != DEAD);
llassert(status != UNKNOWN);
status = getPtrStatus(channel);
llassert(status != ACTIVE);
mActiveSounds[sound].insert(channel);
mActiveChannels.insert(std::make_pair(channel,sound));
}
void removeChannel(FMOD::Channel* channel)
{
#ifdef SHOW_ASSERT
STATUS status = getPtrStatus(channel);
llassert(status != DEAD);
llassert(status != UNKNOWN);
#endif
active_channels_t::const_iterator it = mActiveChannels.find(channel);
llassert(it != mActiveChannels.end());
if(it != mActiveChannels.end())
{
#ifdef SHOW_ASSERT
STATUS status = getPtrStatus(it->second);
llassert(status != DEAD);
llassert(status != UNKNOWN);
#endif
active_sounds_t::iterator it2 = mActiveSounds.find(it->second);
llassert(it2 != mActiveSounds.end());
if(it2 != mActiveSounds.end())
{
it2->second.erase(channel);
}
mDeadChannels.insert(*it);
mActiveChannels.erase(channel);
}
}
} gSoundCheck;
bool isActive(LLAudioChannel* channel)
{
return gSoundCheck.getPtrStatus(dynamic_cast<LLAudioChannelFMODEX*>(channel)) == CFMODSoundChecks::ACTIVE;
}
bool isActive(LLAudioBuffer* sound)
{
return gSoundCheck.getPtrStatus(dynamic_cast<LLAudioBufferFMODEX*>(sound)) == CFMODSoundChecks::ACTIVE;
}
#define CHECK_PTR(ptr) \
if(sVerboseDebugging){\
CFMODSoundChecks::STATUS chan = gSoundCheck.getPtrStatus(ptr); \
if(chan == CFMODSoundChecks::DEAD) \
LL_DEBUGS("AudioImpl") << __FUNCTION__ << ": Using dead " << typeid(ptr).name() << " " << ptr << llendl; \
else if(chan == CFMODSoundChecks::UNKNOWN) \
LL_DEBUGS("AudioImpl") << __FUNCTION__ << ": Using unknown " << typeid(ptr).name() << " " << ptr << llendl;} \
LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler, bool verbose_debugging)
{
sVerboseDebugging = verbose_debugging;
mInited = false;
mWindGen = NULL;
mWindDSP = NULL;
@@ -93,7 +253,7 @@ inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
{
if(result == FMOD_OK)
return false;
llwarns << string << " Error: " << FMOD_ErrorString(result) << llendl;
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << llendl;
return true;
}
@@ -101,11 +261,11 @@ void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const cha
{
if(type & FMOD_MEMORY_STREAM_DECODE)
{
llinfos << "Decode buffer size: " << size << llendl;
LL_INFOS("AudioImpl") << "Decode buffer size: " << size << llendl;
}
else if(type & FMOD_MEMORY_STREAM_FILE)
{
llinfos << "Strean buffer size: " << size << llendl;
LL_INFOS("AudioImpl") << "Stream buffer size: " << size << llendl;
}
return new char[size];
}
@@ -344,7 +504,7 @@ void LLAudioEngine_FMODEX::allocateListener(void)
mListenerp = (LLListener *) new LLListener_FMODEX(mSystem);
if (!mListenerp)
{
llwarns << "Listener creation failed" << llendl;
LL_WARNS("AudioImpl") << "Listener creation failed" << llendl;
}
}
@@ -353,13 +513,16 @@ void LLAudioEngine_FMODEX::shutdown()
{
stopInternetStream();
llinfos << "About to LLAudioEngine::shutdown()" << llendl;
LL_INFOS("AudioImpl") << "About to LLAudioEngine::shutdown()" << llendl;
LLAudioEngine::shutdown();
llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl;
LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl;
if ( mSystem ) // speculative fix for MAINT-2657
{
mSystem->close();
mSystem->release();
llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl;
}
LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl;
delete mListenerp;
mListenerp = NULL;
@@ -490,6 +653,34 @@ LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChanne
LLAudioChannelFMODEX::~LLAudioChannelFMODEX()
{
if(sVerboseDebugging)
LL_DEBUGS("AudioImpl") << "Destructing Audio Channel. mChannelp = " << mChannelp << llendl;
cleanup();
}
static FMOD_RESULT F_CALLBACK channel_callback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *commanddata1, void *commanddata2)
{
if(type == FMOD_CHANNEL_CALLBACKTYPE_END)
{
FMOD::Channel* chan = reinterpret_cast<FMOD::Channel*>(channel);
LLAudioChannelFMODEX* audio_channel = NULL;
chan->getUserData((void**)&audio_channel);
if(audio_channel)
{
audio_channel->onRelease();
}
}
return FMOD_OK;
}
void LLAudioChannelFMODEX::onRelease()
{
llassert(mChannelp);
if(sVerboseDebugging)
LL_DEBUGS("AudioImpl") << "Fmod signaled channel release for channel " << mChannelp << llendl;
gSoundCheck.removeChannel(mChannelp);
mChannelp = NULL; //Null out channel here so cleanup doesn't try to redundantly stop it.
cleanup();
}
@@ -502,13 +693,16 @@ bool LLAudioChannelFMODEX::updateBuffer()
LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer();
llassert(mCurrentBufferp != NULL);
llassert(mCurrentBufferp == bufferp);
// Grab the FMOD sample associated with the buffer
FMOD::Sound *soundp = bufferp->getSound();
if (!soundp)
{
// This is bad, there should ALWAYS be a sound associated with a legit
// buffer.
llerrs << "No FMOD sound!" << llendl;
LL_ERRS("AudioImpl") << "No FMOD sound!" << llendl;
return false;
}
@@ -517,11 +711,21 @@ bool LLAudioChannelFMODEX::updateBuffer()
// setup.
if(!mChannelp)
{
llassert(!isActive(this));
FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp);
Check_FMOD_Error(result, "FMOD::System::playSound");
}
if(result == FMOD_OK)
{
if(sVerboseDebugging)
LL_DEBUGS("AudioImpl") << "Created channel " << mChannelp << " for sound " << soundp << llendl;
//llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
gSoundCheck.addNewChannelToSound(soundp,mChannelp);
mChannelp->setCallback(&channel_callback);
mChannelp->setUserData(this);
llassert(isActive(this));
}
}
}
// If we have a source for the channel, we need to update its gain.
@@ -530,18 +734,12 @@ bool LLAudioChannelFMODEX::updateBuffer()
// SJB: warnings can spam and hurt framerate, disabling
FMOD_RESULT result;
CHECK_PTR(mChannelp);
result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain());
Check_FMOD_Error(result, "FMOD::Channel::setVolume");
result = mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
Check_FMOD_Error(result, "FMOD::Channel::setMode");
/*if(Check_FMOD_Error(result, "FMOD::Channel::setMode"))
{
S32 index;
mChannelp->getIndex(&index);
llwarns << "Channel " << index << "Source ID: " << mCurrentSourcep->getID()
<< " at " << mCurrentSourcep->getPositionGlobal() << llendl;
}*/
}
return true;
@@ -564,6 +762,8 @@ void LLAudioChannelFMODEX::update3DPosition()
return;
}
CHECK_PTR(mChannelp);
if (mCurrentSourcep->isAmbient())
{
// Ambient sound, don't need to do any positional updates.
@@ -590,6 +790,8 @@ void LLAudioChannelFMODEX::updateLoop()
return;
}
CHECK_PTR(mChannelp);
//
// Hack: We keep track of whether we looped or not by seeing when the
// sample position looks like it's going backwards. Not reliable; may
@@ -608,17 +810,30 @@ void LLAudioChannelFMODEX::updateLoop()
void LLAudioChannelFMODEX::cleanup()
{
LLAudioChannel::cleanup();
if (!mChannelp)
{
llassert(!isActive(this));
llassert(mCurrentBufferp == NULL);
//llinfos << "Aborting cleanup with no channel handle." << llendl;
return;
}
//llinfos << "Cleaning up channel: " << mChannelID << llendl;
Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop");
CHECK_PTR(mChannelp);
if(sVerboseDebugging)
LL_DEBUGS("AudioImpl") << "Stopping channel " << mChannelp << llendl;
mChannelp->setCallback(NULL);
if(!Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"))
{
gSoundCheck.removeChannel(mChannelp);
}
mCurrentBufferp = NULL;
mChannelp = NULL;
llassert(!isActive(this));
}
@@ -626,12 +841,19 @@ void LLAudioChannelFMODEX::play()
{
if (!mChannelp)
{
llwarns << "Playing without a channel handle, aborting" << llendl;
LL_WARNS("AudioImpl") << "Playing without a channel handle, aborting" << llendl;
return;
}
llassert(isActive(this));
CHECK_PTR(mChannelp);
Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused");
if(sVerboseDebugging)
LL_DEBUGS("AudioImpl") << "Playing channel " << mChannelp << llendl;
getSource()->setPlayedOnce(true);
if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()])
@@ -648,6 +870,8 @@ void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp)
return;
}
CHECK_PTR(mChannelp);
U32 cur_pos;
if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position"))
return;
@@ -669,6 +893,8 @@ bool LLAudioChannelFMODEX::isPlaying()
return false;
}
CHECK_PTR(mChannelp);
bool paused, playing;
Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused");
Check_FMOD_Error(mChannelp->isPlaying(&playing),"FMOD::Channel::isPlaying");
@@ -690,7 +916,12 @@ LLAudioBufferFMODEX::~LLAudioBufferFMODEX()
{
if(mSoundp)
{
if(sVerboseDebugging)
LL_DEBUGS("AudioImpl") << "Release sound " << mSoundp << llendl;
CHECK_PTR(mSoundp);
Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release");
gSoundCheck.removeSound(mSoundp);
mSoundp = NULL;
}
}
@@ -714,8 +945,10 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
if (mSoundp)
{
CHECK_PTR(mSoundp);
// If there's already something loaded in this buffer, clean it up.
Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::release");
gSoundCheck.removeSound(mSoundp);
mSoundp = NULL;
}
@@ -734,7 +967,7 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
if (result != FMOD_OK)
{
// We failed to load the file for some reason.
llwarns << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl;
LL_WARNS("AudioImpl") << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl;
//
// If we EVER want to load wav files provided by end users, we need
@@ -745,6 +978,8 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
return false;
}
gSoundCheck.addNewSound(mSoundp);
// Everything went well, return true
return true;
}
@@ -757,6 +992,7 @@ U32 LLAudioBufferFMODEX::getLength()
return 0;
}
CHECK_PTR(mSoundp);
U32 length;
Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES),"FMOD::Sound::getLength");
return length;
@@ -765,6 +1001,8 @@ U32 LLAudioBufferFMODEX::getLength()
void LLAudioChannelFMODEX::set3DMode(bool use3d)
{
CHECK_PTR(mChannelp);
FMOD_MODE current_mode;
if(Check_FMOD_Error(mChannelp->getMode(&current_mode),"FMOD::Channel::getMode"))
return;

View File

@@ -53,7 +53,7 @@ namespace FMOD
class LLAudioEngine_FMODEX : public LLAudioEngine
{
public:
LLAudioEngine_FMODEX(bool enable_profiler);
LLAudioEngine_FMODEX(bool enable_profiler, bool verbose_debugging);
virtual ~LLAudioEngine_FMODEX();
// initialization/startup/shutdown
@@ -95,7 +95,7 @@ class LLAudioChannelFMODEX : public LLAudioChannel
public:
LLAudioChannelFMODEX(FMOD::System *audioengine);
virtual ~LLAudioChannelFMODEX();
void onRelease();
protected:
/*virtual*/ void play();
/*virtual*/ void playSynced(LLAudioChannel *channelp);
@@ -112,6 +112,8 @@ protected:
FMOD::System *mSystemp;
FMOD::Channel *mChannelp;
S32 mLastSamplePos;
friend class CFMODSoundChecks;
};
@@ -129,6 +131,8 @@ protected:
FMOD::System *mSystemp;
FMOD::Sound *getSound() const{ return mSoundp; }
FMOD::Sound *mSoundp;
friend class CFMODSoundChecks;
};

View File

@@ -186,10 +186,9 @@ LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
void LLAudioChannelOpenAL::cleanup()
{
LLAudioChannel::cleanup();
alSourceStop(mALSource);
alSourcei(mALSource, AL_BUFFER, AL_NONE);
mCurrentBufferp = NULL;
}
void LLAudioChannelOpenAL::play()

View File

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

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

@@ -0,0 +1,358 @@
/**
* @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)
{
if(!singleton_t::instance().mStaticScope)
mStaticScope = new ScopedRegistrar();
singleton_t::instance().mStaticScope->add(key, value);
}
};
// convenience functions
typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
static ref_registrar_t currentRegistrar()
{
return singleton_t::instance().registry_t::currentRegistrar();
}
static ref_registrar_t defaultRegistrar()
{
return singleton_t::instance().registry_t::defaultRegistrar();
}
static ptr_value_t getValue(ref_const_key_t key)
{
return singleton_t::instance().registry_t::getValue(key);
}
protected:
// DERIVED_TYPE needs to derive from LLRegistrySingleton
LLRegistrySingleton()
: mStaticScope(NULL)
{}
virtual void initSingleton()
{
//mStaticScope = new ScopedRegistrar();
}
virtual ~LLRegistrySingleton()
{
delete mStaticScope;
}
private:
ScopedRegistrar* mStaticScope;
};
// helper macro for doing static registration
#define GLUED_TOKEN(x, y) x ## y
#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
#endif

View File

@@ -0,0 +1,342 @@
/**
* @file llsdparam.cpp
* @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
// Project includes
#include "llsdparam.h"
#include "llsdutil.h"
static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
static const LLSD NO_VALUE_MARKER;
LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
//
// LLParamSDParser
//
LLParamSDParser::LLParamSDParser()
: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
{
using boost::bind;
if (sReadFuncs.empty())
{
registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
}
}
// special case handling of U32 due to ambiguous LLSD::assign overload
bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
if (!sdparser.mWriteRootSD) return false;
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
sd_to_write.assign((S32)*((const U32*)val_ptr));
return true;
}
bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
if (!sdparser.mWriteRootSD) return false;
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
return true;
}
void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
{
mCurReadSD = &sd;
block.submitValue(name_stack, *this);
}
void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
{
mCurReadSD = NULL;
mNameStack.clear();
setParseSilently(silent);
LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
//readSDValues(sd, block);
}
void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
{
mNameStack.clear();
mWriteRootSD = &sd;
name_stack_t name_stack;
block.serializeBlock(*this, name_stack);
}
/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
{
std::string full_name = "sd";
for (name_stack_t::iterator it = mNameStack.begin();
it != mNameStack.end();
++it)
{
full_name += llformat("[%s]", it->first.c_str());
}
return full_name;
}
bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
return self.mCurReadSD == &NO_VALUE_MARKER;
}
bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((S32*)val_ptr) = self.mCurReadSD->asInteger();
return true;
}
bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((U32*)val_ptr) = self.mCurReadSD->asInteger();
return true;
}
bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((F32*)val_ptr) = self.mCurReadSD->asReal();
return true;
}
bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((F64*)val_ptr) = self.mCurReadSD->asReal();
return true;
}
bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((bool*)val_ptr) = self.mCurReadSD->asBoolean();
return true;
}
bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((std::string*)val_ptr) = self.mCurReadSD->asString();
return true;
}
bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
return true;
}
bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
return true;
}
bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
return true;
}
bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
{
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
*((LLSD*)val_ptr) = *self.mCurReadSD;
return true;
}
// static
LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
{
LLSD* sd_to_write = &input;
for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
it != name_stack_range.second;
++it)
{
bool new_traversal = it->second;
LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
if (child_sd->isArray())
{
if (new_traversal)
{
// write to new element at end
sd_to_write = &(*child_sd)[child_sd->size()];
}
else
{
// write to last of existing elements, or first element if empty
sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
}
}
else
{
if (new_traversal
&& child_sd->isDefined()
&& !child_sd->isArray())
{
// copy child contents into first element of an array
LLSD new_array = LLSD::emptyArray();
new_array.append(*child_sd);
// assign array to slot that previously held the single value
*child_sd = new_array;
// return next element in that array
sd_to_write = &((*child_sd)[1]);
}
else
{
sd_to_write = child_sd;
}
}
it->second = false;
}
return *sd_to_write;
}
//static
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
{
if (sd.isMap())
{
for (LLSD::map_const_iterator it = sd.beginMap();
it != sd.endMap();
++it)
{
stack.push_back(make_pair(it->first, true));
readSDValues(cb, it->second, stack);
stack.pop_back();
}
}
else if (sd.isArray())
{
for (LLSD::array_const_iterator it = sd.beginArray();
it != sd.endArray();
++it)
{
stack.back().second = true;
readSDValues(cb, *it, stack);
}
}
else if (sd.isUndefined())
{
if (!cb.empty())
{
cb(NO_VALUE_MARKER, stack);
}
}
else
{
if (!cb.empty())
{
cb(sd, stack);
}
}
}
//static
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
{
LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
readSDValues(cb, sd, stack);
}
namespace LLInitParam
{
// LLSD specialization
// block param interface
bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
{
LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
LLSD::String string;
if (p.readValue<LLSD::String>(string))
{
sd = string;
return true;
}
return false;
}
//static
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
{
p.writeValue<LLSD::String>(sd.asString(), name_stack);
}
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
{
// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
Parser::name_stack_t stack;
LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
}
}

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

@@ -0,0 +1,126 @@
/**
* @file llsdparam.h
* @brief parameter block abstraction for creating complex objects and
* parsing construction parameters from xml and LLSD
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLSDPARAM_H
#define LL_LLSDPARAM_H
#include "llinitparam.h"
#include "boost/function.hpp"
struct LL_COMMON_API LLParamSDParserUtilities
{
static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
};
class LL_COMMON_API LLParamSDParser
: public LLInitParam::Parser
{
LOG_CLASS(LLParamSDParser);
typedef LLInitParam::Parser parser_t;
public:
LLParamSDParser();
void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
/*virtual*/ std::string getCurrentElementName();
private:
void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
template<typename T>
static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
{
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
if (!sdparser.mWriteRootSD) return false;
LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
sd_to_write.assign(*((const T*)val_ptr));
return true;
}
static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
static bool readFlag(Parser& parser, void* val_ptr);
static bool readS32(Parser& parser, void* val_ptr);
static bool readU32(Parser& parser, void* val_ptr);
static bool readF32(Parser& parser, void* val_ptr);
static bool readF64(Parser& parser, void* val_ptr);
static bool readBool(Parser& parser, void* val_ptr);
static bool readString(Parser& parser, void* val_ptr);
static bool readUUID(Parser& parser, void* val_ptr);
static bool readDate(Parser& parser, void* val_ptr);
static bool readURI(Parser& parser, void* val_ptr);
static bool readSD(Parser& parser, void* val_ptr);
Parser::name_stack_t mNameStack;
const LLSD* mCurReadSD;
LLSD* mWriteRootSD;
LLSD* mCurWriteSD;
};
extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
template<typename T>
class LLSDParamAdapter : public T
{
public:
LLSDParamAdapter() {}
LLSDParamAdapter(const LLSD& sd)
{
LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
LLParamSDParser parser;
// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
bool parse_silently = true;
parser.readSD(sd, *this, parse_silently);
}
operator LLSD() const
{
LLParamSDParser parser;
LLSD sd;
parser.writeSD(sd, *this);
return sd;
}
LLSDParamAdapter(const T& val)
: T(val)
{
T::operator=(val);
}
};
#endif // LL_LLSDPARAM_H

View File

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

View File

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

View File

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

View File

@@ -56,6 +56,7 @@ bool LLPluginClassMedia::init_impl(void)
{
// Queue up the media init message -- it will be sent after all the currently queued messages.
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
message.setValue("target", mTarget);
sendMessage(message);
return true;
@@ -127,7 +128,7 @@ void LLPluginClassMedia::reset_impl(void)
void LLPluginClassMedia::idle_impl(void)
{
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()))
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
{
// Can't process a size change at this time
}
@@ -246,16 +247,18 @@ unsigned char* LLPluginClassMedia::getBitsData()
void LLPluginClassMedia::setSize(int width, int height)
{
if (width <= 0 || height <= 0)
{
width = height = -1;
}
if (mSetMediaWidth != width || mSetMediaHeight != height)
if((width > 0) && (height > 0))
{
mSetMediaWidth = width;
mSetMediaHeight = height;
setSizeInternal();
}
else
{
mSetMediaWidth = -1;
mSetMediaHeight = -1;
}
setSizeInternal();
}
void LLPluginClassMedia::setSizeInternal(void)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -544,7 +544,7 @@ void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height)
// virtual
void LLButton::draw()
{
F32 alpha = mAlpha;
F32 alpha = mAlpha * getDrawContext().mAlpha;
bool flash = FALSE;
if( mFlashing )
{

View File

@@ -307,9 +307,6 @@ LLXMLNodePtr LLCheckBoxCtrl::getXML(bool save_children) const
// static
LLView* LLCheckBoxCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("checkbox");
node->getAttributeString("name", name);
std::string label("");
node->getAttributeString("label", label);
@@ -326,7 +323,7 @@ LLView* LLCheckBoxCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
LLRect rect;
createRect(node, rect, parent, LLRect());
LLCheckBoxCtrl* checkbox = new LLCheckboxCtrl(name,
LLCheckBoxCtrl* checkbox = new LLCheckboxCtrl("checkbox",
rect,
label,
font,

View File

@@ -149,9 +149,6 @@ LLXMLNodePtr LLComboBox::getXML(bool save_children) const
// static
LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("combo_box");
node->getAttributeString("name", name);
std::string label("");
node->getAttributeString("label", label);
@@ -164,7 +161,7 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
S32 max_chars = 20;
node->getAttributeS32("max_chars", max_chars);
LLComboBox* combo_box = new LLComboBox(name,
LLComboBox* combo_box = new LLComboBox("combo_box",
rect,
label);
combo_box->setAllowTextEntry(allow_text_entry, max_chars);
@@ -1245,16 +1242,13 @@ LLXMLNodePtr LLFlyoutButton::getXML(bool save_children) const
//static
LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name = "flyout_button";
node->getAttributeString("name", name);
std::string label("");
node->getAttributeString("label", label);
LLRect rect;
createRect(node, rect, parent, LLRect());
LLFlyoutButton* flyout_button = new LLFlyoutButton(name,
LLFlyoutButton* flyout_button = new LLFlyoutButton("flyout_button",
rect,
label);

View File

@@ -52,9 +52,6 @@ void LLFilterEditor::handleKeystroke()
// static
LLView* LLFilterEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("filter_editor");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
@@ -63,7 +60,7 @@ LLView* LLFilterEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
std::string text = node->getValue().substr(0, max_text_length - 1);
LLFilterEditor* search_editor = new LLFilterEditor(name,
LLFilterEditor* search_editor = new LLFilterEditor("filter_editor",
rect,
max_text_length);

View File

@@ -58,6 +58,7 @@
#include "v2math.h"
#include "llfasttimer.h"
#include "airecursive.h"
#include "llnotifications.h"
const S32 MINIMIZED_WIDTH = 160;
const S32 CLOSE_BOX_FROM_TOP = 1;
@@ -1411,6 +1412,10 @@ void LLFloater::closeFocusedFloater()
}
}
LLNotificationPtr LLFloater::addContextualNotification(const std::string& name, const LLSD& substitutions)
{
return LLNotifications::instance().add(LLNotification::Params(name).context(mNotificationContext).substitutions(substitutions));
}
void LLFloater::onClickClose()
{
@@ -2488,8 +2493,13 @@ LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
if (filename.empty())
{
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
floaterp->getCommitCallbackRegistrar().pushScope();
floaterp->getEnableCallbackRegistrar().pushScope();
// Load from node
floaterp->initFloaterXML(node, parent, factory);
floaterp->getCommitCallbackRegistrar().popScope();
floaterp->getEnableCallbackRegistrar().popScope();
}
else
{

View File

@@ -40,7 +40,8 @@
#include "llpanel.h"
#include "lluuid.h"
#include "lltabcontainer.h"
#include "llnotifications.h"
#include "llnotificationcontext.h"
#include "llnotificationptr.h"
#include <set>
class LLDragHandle;
@@ -232,10 +233,7 @@ public:
// handle refocusing.
static void closeFocusedFloater();
LLNotification::Params contextualNotification(const std::string& name)
{
return LLNotification::Params(name).context(mNotificationContext);
}
LLNotificationPtr addContextualNotification(const std::string& name, const LLSD& substitutions = LLSD());
void onClickClose();
void onClickMinimize();

View File

@@ -106,7 +106,8 @@ void LLIconCtrl::draw()
{
if( mImagep.notNull() )
{
mImagep->draw(getLocalRect(), mColor );
const F32 alpha = getDrawContext().mAlpha;
mImagep->draw(getLocalRect(), mColor % alpha );
}
LLUICtrl::draw();
@@ -157,9 +158,6 @@ LLXMLNodePtr LLIconCtrl::getXML(bool save_children) const
LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("icon");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
@@ -172,7 +170,7 @@ LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
LLColor4 color(LLColor4::white);
LLUICtrlFactory::getAttributeColor(node,"color", color);
LLIconCtrl* icon = new LLIconCtrl(name, rect, image_name);
LLIconCtrl* icon = new LLIconCtrl("icon", rect, image_name);
icon->setColor(color);

1038
indra/llui/lllayoutstack.cpp Normal file

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,179 @@
/**
* @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"
#include "llresizebar.h"
class LLLayoutPanel;
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
{
public:
typedef enum e_layout_orientation
{
HORIZONTAL,
VERTICAL
} ELayoutOrientation;
LLLayoutStack(ELayoutOrientation orientation, S32 border_size, bool animate, bool clip, F32 open_time_constant, F32 close_time_constant, F32 resize_bar_overlap);
virtual ~LLLayoutStack();
/*virtual*/ void draw();
/*virtual*/ void removeChild(LLView*);
/*virtual*/ BOOL postBuild();
/*virtual*/ bool addChild(LLView* child, S32 tab_groupdatefractuiona = 0);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
typedef enum e_animate
{
NO_ANIMATE,
ANIMATE
} EAnimate;
void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE);
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
S32 getNumPanels() { return mPanels.size(); }
void updateLayout();
S32 getPanelSpacing() const { return mPanelSpacing; }
static void updateClass();
protected:
LLLayoutStack(const Params&);
friend class LLUICtrlFactory;
friend class LLLayoutPanel;
private:
void updateResizeBarLimits();
bool animatePanels();
void createResizeBar(LLLayoutPanel* panel);
const ELayoutOrientation mOrientation;
typedef std::vector<LLLayoutPanel*> e_panel_list_t;
e_panel_list_t mPanels;
LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
void updateFractionalSizes();
void normalizeFractionalSizes();
void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect );
S32 mPanelSpacing;
// true if we already applied animation this frame
bool mAnimatedThisFrame;
bool mAnimate;
bool mClip;
F32 mOpenTimeConstant;
F32 mCloseTimeConstant;
bool mNeedsLayout;
S32 mResizeBarOverlap;
}; // end class LLLayoutStack
class LLLayoutPanel : public LLPanel
{
friend class LLLayoutStack;
friend class LLUICtrlFactory;
public:
~LLLayoutPanel();
void initFromParams(const Params& p);
static LLView* fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *factory);
void handleReshape(const LLRect& new_rect, bool by_user);
void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
void setVisible(BOOL visible);
S32 getLayoutDim() const;
S32 getTargetDim() const;
void setTargetDim(S32 value);
S32 getMinDim() const { return llmax(0, mMinDim); }
void setMinDim(S32 value) { mMinDim = value; }
S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); }
void setExpandedMinDim(S32 value) { mExpandedMinDim = value; }
S32 getRelevantMinDim() const
{
S32 min_dim = mMinDim;
if (!mCollapsed)
{
min_dim = getExpandedMinDim();
}
return min_dim;
}
F32 getAutoResizeFactor() const;
F32 getVisibleAmount() const;
S32 getVisibleDim() const;
LLResizeBar* getResizeBar() { return mResizeBar; }
bool isCollapsed() const { return mCollapsed;}
void setOrientation(LLLayoutStack::ELayoutOrientation orientation);
void storeOriginalDim();
void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; }
protected:
LLLayoutPanel(S32 min_dim=-1, BOOL auto_resize=TRUE, BOOL user_resize=TRUE, LLRect rect = LLRect());
/*virtual*/ BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
bool mAutoResize;
bool mUserResize;
S32 mExpandedMinDim;
S32 mMinDim;
bool mCollapsed;
F32 mVisibleAmt;
F32 mCollapseAmt;
F32 mFractionalSize;
S32 mTargetDim;
bool mIgnoreReshape;
LLLayoutStack::ELayoutOrientation mOrientation;
class LLResizeBar* mResizeBar;
};
#endif

View File

@@ -1702,6 +1702,7 @@ void LLLineEditor::drawMisspelled(LLRect background)
if (glggHunSpell->getSpellCheckHighlight())
{
F32 alpha = getDrawContext().mAlpha;
for (int i =0; i<(int)misspellLocations.size(); i++)
{
S32 wstart =findPixelNearestPos( misspellLocations[i]-getCursor());
@@ -1716,7 +1717,7 @@ void LLLineEditor::drawMisspelled(LLRect background)
{
wstart = maxw;
}
gGL.color4ub(255,0,0,200);
gGL.color4ub(255,0,0,200*alpha);
//3 line zig zags..
while (wstart < wend)
{
@@ -1733,6 +1734,7 @@ void LLLineEditor::drawMisspelled(LLRect background)
void LLLineEditor::draw()
{
F32 alpha = getDrawContext().mAlpha;
S32 text_len = mText.length();
std::string saved_text;
@@ -1776,7 +1778,7 @@ void LLLineEditor::draw()
bg_color = mWriteableBgColor;
}
}
gl_rect_2d(background, bg_color);
gl_rect_2d(background, bg_color % alpha);
}
#endif
@@ -1801,7 +1803,9 @@ void LLLineEditor::draw()
{
text_color = mReadOnlyFgColor;
}
LLColor4 label_color = mTentativeFgColor;
text_color %= alpha;
LLColor4 label_color = mTentativeFgColor % alpha;
if (hasPreeditString())
{
@@ -1824,7 +1828,7 @@ void LLLineEditor::draw()
background.mBottom + PREEDIT_STANDOUT_POSITION,
preedit_pixels_right - PREEDIT_STANDOUT_GAP - 1,
background.mBottom + PREEDIT_STANDOUT_POSITION - PREEDIT_STANDOUT_THICKNESS,
(text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
(text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(alpha));
}
else
{
@@ -1832,7 +1836,7 @@ void LLLineEditor::draw()
background.mBottom + PREEDIT_MARKER_POSITION,
preedit_pixels_right - PREEDIT_MARKER_GAP - 1,
background.mBottom + PREEDIT_MARKER_POSITION - PREEDIT_MARKER_THICKNESS,
(text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
(text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(alpha));
}
}
}
@@ -1874,7 +1878,7 @@ void LLLineEditor::draw()
if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
{
LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], 1.f);
LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], alpha );
// selected middle
S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
@@ -1883,7 +1887,7 @@ void LLLineEditor::draw()
rendered_text += mGLFont->render(
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ),
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
@@ -1953,7 +1957,7 @@ void LLLineEditor::draw()
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
{
mGLFont->render(mText, getCursor(), (F32)(cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS / 2), text_bottom,
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ),
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
@@ -2551,9 +2555,6 @@ LLXMLNodePtr LLLineEditor::getXML(bool save_children) const
// static
LLView* LLLineEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("line_editor");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
@@ -2580,7 +2581,7 @@ LLView* LLLineEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
S32 border_thickness = 1;
node->getAttributeS32("border_thickness", border_thickness);
LLLineEditor* line_editor = new LLLineEditor(name,
LLLineEditor* line_editor = new LLLineEditor("line_editor",
rect,
text,
font,

View File

@@ -1928,6 +1928,7 @@ LLXMLNodePtr LLMenuGL::getXML(bool save_children) const
void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory *factory)
{
std::string name(child->getName()->mString);
if (child->hasName(LL_MENU_GL_TAG))
{
// SUBMENU
@@ -2025,7 +2026,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling())
{
if (call_child->hasName("on_check"))
if (call_child->hasName("on_check") || call_child->hasName(name+".on_check"))
{
std::string callback_name;
std::string control_name;
@@ -2083,7 +2084,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling())
{
if (call_child->hasName("on_click"))
if (call_child->hasName("on_click") || call_child->hasName(name+".on_click"))
{
std::string callback_name;
call_child->getAttributeString("function", callback_name);
@@ -2104,7 +2105,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
new_item->addListener(callback, "on_click", callback_data);
}
if (call_child->hasName("on_enable"))
if (call_child->hasName("on_enable") || call_child->hasName(name+".on_enable"))
{
std::string callback_name;
std::string control_name;
@@ -2148,7 +2149,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
}
new_item->setEnabledControl(control_name, parent);
}
if (call_child->hasName("on_visible"))
if (call_child->hasName("on_visible") || call_child->hasName(name+".on_visible"))
{
std::string callback_name;
std::string control_name;
@@ -2322,7 +2323,7 @@ LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
++token_count;
}
BOOL opaque = FALSE;
BOOL opaque = TRUE;
node->getAttributeBOOL("opaque", opaque);
LLMenuGL *menu = new LLMenuGL(name, new_menu_label);
@@ -4150,13 +4151,10 @@ LLXMLNodePtr LLMenuBarGL::getXML(bool save_children) const
LLView* LLMenuBarGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("menu");
node->getAttributeString("name", name);
BOOL opaque = FALSE;
node->getAttributeBOOL("opaque", opaque);
LLMenuBarGL *menubar = new LLMenuBarGL(name);
LLMenuBarGL *menubar = new LLMenuBarGL("menu");
LLHandle<LLFloater> parent_handle;
LLFloater* parent_floater = dynamic_cast<LLFloater*>(parent);

View File

@@ -624,9 +624,6 @@ LLXMLNodePtr LLMultiSlider::getXML(bool save_children) const
//static
LLView* LLMultiSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("multi_slider_bar");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
@@ -654,7 +651,7 @@ LLView* LLMultiSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
BOOL use_triangle = FALSE;
node->getAttributeBOOL("use_triangle", use_triangle);
LLMultiSlider* multiSlider = new LLMultiSlider(name,
LLMultiSlider* multiSlider = new LLMultiSlider("multi_slider_bar",
rect,
NULL,
initial_value,

View File

@@ -470,9 +470,6 @@ LLXMLNodePtr LLMultiSliderCtrl::getXML(bool save_children) const
LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("multi_slider");
node->getAttributeString("name", name);
std::string label;
node->getAttributeString("label", label);
@@ -556,7 +553,7 @@ LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFa
label.assign(node->getTextContents());
}
LLMultiSliderCtrl* slider = new LLMultiSliderCtrl(name,
LLMultiSliderCtrl* slider = new LLMultiSliderCtrl("multi_slider",
rect,
label,
font,

View File

@@ -0,0 +1,59 @@
/**
* @file llnotifications.h
* @brief Notification context class, pulled out of llnotifications.h to avoid including said file in llfloater.h. (Needed, as llnotifications.h includes llevents.h, which causes issues)
* @author Q (with assistance from Richard and Coco)
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008-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_LLNOTIFICATION_CONTEX
#define LL_LLNOTIFICATION_CONTEX
// context data that can be looked up via a notification's payload by the display logic
// derive from this class to implement specific contexts
class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
{
public:
LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID())
{
}
virtual ~LLNotificationContext() {}
LLSD asLLSD() const
{
return getKey();
}
private:
};
#endif //LL_LLNOTIFICATION_CONTEX

View File

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

View File

@@ -100,11 +100,13 @@
#include "llinstancetracker.h"
// and we need this to manage the notification callbacks
#include "llavatarname.h"
#include "llevents.h"
#include "llfunctorregistry.h"
#include "llui.h"
#include "llxmlnode.h"
#include "llnotificationptr.h"
#include "llnotificationcontext.h"
typedef enum e_notification_priority
{
@@ -120,26 +122,6 @@ typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder
typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;
typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration;
// context data that can be looked up via a notification's payload by the display logic
// derive from this class to implement specific contexts
class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
{
public:
LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID())
{
}
virtual ~LLNotificationContext() {}
LLSD asLLSD() const
{
return getKey();
}
private:
};
// Contains notification form data, such as buttons and text fields along with
// manipulator functions
class LLNotificationForm
@@ -791,7 +773,5 @@ private:
LLNotificationMap mUniqueNotifications;
};
#endif//LL_LLNOTIFICATIONS_H

View File

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

View File

@@ -140,7 +140,9 @@ public:
const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; }
BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
CommitCallbackRegistry::ScopedRegistrar& getCommitCallbackRegistrar() { return mCommitCallbackRegistrar; }
EnableCallbackRegistry::ScopedRegistrar& getEnableCallbackRegistrar() { return mEnableCallbackRegistrar; }
virtual BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
void initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory);
void setPanelParameters(LLXMLNodePtr node, LLView *parentp);
@@ -230,6 +232,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:
@@ -258,56 +262,4 @@ private:
}; // end class LLPanel
class LLLayoutStack : public LLView
{
public:
typedef enum e_layout_orientation
{
HORIZONTAL,
VERTICAL
} eLayoutOrientation;
LLLayoutStack(eLayoutOrientation orientation);
virtual ~LLLayoutStack();
/*virtual*/ void draw();
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void removeChild(LLView* ctrl);
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
S32 getMinWidth() const { return mMinWidth; }
S32 getMinHeight() const { return mMinHeight; }
typedef enum e_animate
{
NO_ANIMATE,
ANIMATE
} EAnimate;
void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
void removePanel(LLPanel* panel);
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
S32 getNumPanels() { return mPanels.size(); }
private:
struct LLEmbeddedPanel;
void updateLayout(BOOL force_resize = FALSE);
void calcMinExtents();
S32 getDefaultHeight(S32 cur_height);
S32 getDefaultWidth(S32 cur_width);
const eLayoutOrientation mOrientation;
typedef std::vector<LLEmbeddedPanel*> e_panel_list_t;
e_panel_list_t mPanels;
LLEmbeddedPanel* findEmbeddedPanel(LLPanel* panelp) const;
S32 mMinWidth;
S32 mMinHeight;
S32 mPanelSpacing;
}; // end class LLLayoutStack
#endif

View File

@@ -73,19 +73,19 @@ LLProgressBar::~LLProgressBar()
void LLProgressBar::draw()
{
static LLTimer timer;
LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga");
F32 alpha = getDrawContext().mAlpha;
//LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga");
LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga");
LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga");
LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga");
//LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga");
LLColor4 background_color = LLUI::sColorsGroup->getColor("LoginProgressBarBgColor");
bar_bg_imagep->draw(getLocalRect(),
background_color);
bar_bg_imagep->draw(getLocalRect(), background_color % alpha);
LLRect progress_rect = getLocalRect();
progress_rect.mRight = llround(getRect().getWidth() * (mPercentDone / 100.f));
bar_fg_imagep->draw(progress_rect);
bar_fg_imagep->draw(progress_rect, LLColor4::white % alpha);
}
void LLProgressBar::setPercent(const F32 percent)

View File

@@ -352,9 +352,6 @@ LLXMLNodePtr LLRadioGroup::getXML(bool save_children) const
// static
LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("radio_group");
node->getAttributeString("name", name);
U32 initial_value = 0;
node->getAttributeU32("initial_value", initial_value);
@@ -364,7 +361,7 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
LLRect rect;
createRect(node, rect, parent, LLRect());
LLRadioGroup* radio_group = new LLRadioGroup(name,
LLRadioGroup* radio_group = new LLRadioGroup("radio_group",
rect,
initial_value,
NULL,
@@ -408,10 +405,8 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
LLRect item_rect;
createRect(child, item_rect, radio_group, rect);
std::string radioname("radio");
child->getAttributeString("name", radioname);
std::string item_label = child->getTextContents();
LLRadioCtrl* radio = radio_group->addRadioButton(radioname, item_label, item_rect, font);
LLRadioCtrl* radio = radio_group->addRadioButton("radio", item_label, item_rect, font);
radio->initFromXML(child, radio_group);
}

View File

@@ -152,13 +152,10 @@ LLXMLNodePtr LLScrollingPanelList::getXML(bool save_children) const
// static
LLView* LLScrollingPanelList::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("scrolling_panel_list");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
LLScrollingPanelList* scrolling_panel_list = new LLScrollingPanelList(name, rect);
LLScrollingPanelList* scrolling_panel_list = new LLScrollingPanelList("scrolling_panel_list", rect);
scrolling_panel_list->initFromXML(node, parent);
return scrolling_panel_list;
}

View File

@@ -3104,9 +3104,6 @@ void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node)
// static
LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("scroll_list");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
@@ -3132,7 +3129,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
node->getAttributeBOOL("mouse_wheel_opaque", mouse_wheel_opaque);
LLScrollListCtrl* scroll_list = new LLScrollListCtrl(
name,
"scroll_list",
rect,
NULL,
multi_select,

View File

@@ -147,9 +147,6 @@ void LLSearchEditor::handleKeystroke()
// static
LLView* LLSearchEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("search_editor");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
@@ -158,7 +155,7 @@ LLView* LLSearchEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
std::string text = node->getValue().substr(0, max_text_length - 1);
LLSearchEditor* search_editor = new LLSearchEditor(name,
LLSearchEditor* search_editor = new LLSearchEditor("search_editor",
rect,
max_text_length);

View File

@@ -250,6 +250,8 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask)
void LLSlider::draw()
{
F32 alpha = getDrawContext().mAlpha;
// since thumb image might still be decoding, need thumb to accomodate image size
updateThumbRect();
@@ -258,31 +260,47 @@ void LLSlider::draw()
// drawing solids requires texturing be disabled
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
F32 opacity = getEnabled() ? 1.f : 0.3f;
LLColor4 center_color = (mThumbCenterColor % opacity);
// Track
LLRect track_rect(mThumbImage->getWidth() / 2,
getLocalRect().getCenterY() + (mTrackImage->getHeight() / 2),
getRect().getWidth() - mThumbImage->getWidth() / 2,
getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
LLRect highlight_rect(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom);
mTrackImage->draw(track_rect);
mTrackHighlightImage->draw(highlight_rect);
mTrackImage->draw(track_rect, LLColor4::white % alpha);
mTrackHighlightImage->draw(highlight_rect, LLColor4::white % alpha);
// Thumb
if( hasMouseCapture() )
{
// Show ghost where thumb was before dragging began.
mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor % 0.3f);
}
if (hasFocus())
{
// Draw focus highlighting.
mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth());
}
if( hasMouseCapture() )
{
// Show ghost where thumb was before dragging began.
if (mThumbImage.notNull())
{
mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor % (0.3f * alpha));
mThumbImage->draw(mThumbRect, mThumbOutlineColor % alpha);
}
}
else if(!getEnabled())
{
if (mThumbImage.notNull())
{
mThumbImage->draw(mThumbRect, mThumbCenterColor % (0.3f * alpha));
}
}
else
{
if (mThumbImage.notNull())
{
mThumbImage->draw(mThumbRect, mThumbCenterColor % alpha);
}
}
// Fill in the thumb.
mThumbImage->draw(mThumbRect, hasMouseCapture() ? mThumbOutlineColor : center_color);
LLUICtrl::draw();
}
@@ -325,9 +343,6 @@ boost::signals2::connection LLSlider::setMouseUpCallback( const commit_signal_t:
//static
LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory)
{
std::string name("slider_bar");
node->getAttributeString("name", name);
LLRect rect;
createRect(node, rect, parent, LLRect());
@@ -346,7 +361,7 @@ LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFacto
BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE;
node->getAttributeBOOL("volume", volume);
LLSlider* slider = new LLSlider(name,
LLSlider* slider = new LLSlider("slider_bar",
rect,
NULL,
initial_value,

View File

@@ -96,9 +96,9 @@ private:
S32 mMouseOffset;
LLRect mDragStartThumbRect;
LLUIImage* mThumbImage;
LLUIImage* mTrackImage;
LLUIImage* mTrackHighlightImage;
LLPointer<LLUIImage> mThumbImage;
LLPointer<LLUIImage> mTrackImage;
LLPointer<LLUIImage> mTrackHighlightImage;
LLRect mThumbRect;
LLColor4 mTrackColor;

View File

@@ -401,9 +401,6 @@ LLXMLNodePtr LLSliderCtrl::getXML(bool save_children) const
LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("slider");
node->getAttributeString("name", name);
std::string label;
node->getAttributeString("label", label);
@@ -478,7 +475,7 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
label.assign(node->getTextContents());
}
LLSliderCtrl* slider = new LLSliderCtrl(name,
LLSliderCtrl* slider = new LLSliderCtrl("slider",
rect,
label,
font,

View File

@@ -515,9 +515,6 @@ LLXMLNodePtr LLSpinCtrl::getXML(bool save_children) const
LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("spinner");
node->getAttributeString("name", name);
std::string label;
node->getAttributeString("label", label);
@@ -552,7 +549,7 @@ LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
label.assign( node->getValue() );
}
LLSpinCtrl* spinner = new LLSpinCtrl(name,
LLSpinCtrl* spinner = new LLSpinCtrl("spinner",
rect,
label,
font,

View File

@@ -197,12 +197,16 @@ void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
{
max_width = (F32)getRect().getWidth();
}
if(max_width <= 0.0f)
{
return; //It makes no sense to try to wrap text to fit zero-width columns. (In fact, it causes infinite recursion in the following while loop!)
}
LLWString wtext = utf8str_to_wstring(in_text);
LLWString final_wtext;
LLWString::size_type cur = 0;;
LLWString::size_type len = wtext.size();
LLWString::size_type len = wtext.length();
while (cur < len)
{
@@ -282,6 +286,7 @@ BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text
void LLTextBox::draw()
{
F32 alpha = getDrawContext().mAlpha;
if (mBorderVisible)
{
gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
@@ -292,12 +297,12 @@ void LLTextBox::draw()
static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow");
static S32 drop_shadow_tooltip = LLUI::sConfigGroup->getS32("DropShadowTooltip");
gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
color_drop_shadow, drop_shadow_tooltip);
color_drop_shadow % alpha, drop_shadow_tooltip);
}
if (mBackgroundVisible)
{
gl_rect_2d( getLocalRect(), mBackgroundColor );
gl_rect_2d( getLocalRect(), mBackgroundColor % alpha );
}
S32 text_x = 0;
@@ -320,16 +325,16 @@ void LLTextBox::draw()
{
if(mHasHover)
{
drawText( text_x, text_y, mHoverColor );
drawText( text_x, text_y, mHoverColor % alpha );
}
else
{
drawText( text_x, text_y, mTextColor );
drawText( text_x, text_y, mTextColor % alpha );
}
}
else
{
drawText( text_x, text_y, mDisabledColor );
drawText( text_x, text_y, mDisabledColor % alpha );
}
if (sDebugRects)
@@ -382,6 +387,69 @@ void LLTextBox::reshapeToFitText()
reshape( width + 2 * mHPad, height + 2 * mVPad );
}
// virtual
void LLTextBox::initFromXML(LLXMLNodePtr node, LLView* parent)
{
LLUICtrl::initFromXML(node, parent);
LLFontGL* font = LLView::selectFont(node);
if(font)
mFontGL = font;
setText(node->getTextContents());
LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
setHAlign(halign);
node->getAttributeS32("line_spacing", mLineSpacing);
std::string font_style;
if (node->getAttributeString("font-style", font_style))
{
mFontStyle = LLFontGL::getStyleFromString(font_style);
}
if (node->getAttributeString("font-shadow", font_style))
{
if(font_style == "soft")
mFontShadow = LLFontGL::DROP_SHADOW_SOFT;
else if(font_style == "hard")
mFontShadow = LLFontGL::DROP_SHADOW;
else
mFontShadow = LLFontGL::NO_SHADOW;
}
BOOL mouse_opaque = getMouseOpaque();
if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
{
setMouseOpaque(mouse_opaque);
}
if(node->hasAttribute("text_color"))
{
LLColor4 color;
LLUICtrlFactory::getAttributeColor(node, "text_color", color);
setColor(color);
}
if(node->hasAttribute("hover_color"))
{
LLColor4 color;
LLUICtrlFactory::getAttributeColor(node, "hover_color", color);
setHoverColor(color);
setHoverActive(true);
}
BOOL hover_active = FALSE;
if(node->getAttributeBOOL("hover", hover_active))
{
setHoverActive(hover_active);
}
node->getAttributeBOOL("use_ellipses", mUseEllipses);
}
// virtual
LLXMLNodePtr LLTextBox::getXML(bool save_children) const
{
@@ -411,68 +479,8 @@ LLXMLNodePtr LLTextBox::getXML(bool save_children) const
// static
LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("text_box");
node->getAttributeString("name", name);
LLFontGL* font = LLView::selectFont(node);
std::string text = node->getTextContents();
LLTextBox* text_box = new LLTextBox(name,
LLRect(),
text,
font,
FALSE);
LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
text_box->setHAlign(halign);
LLTextBox* text_box = new LLTextBox("text_box", LLRect(), "" , NULL, FALSE);
text_box->initFromXML(node, parent);
node->getAttributeS32("line_spacing", text_box->mLineSpacing);
std::string font_style;
if (node->getAttributeString("font-style", font_style))
{
text_box->mFontStyle = LLFontGL::getStyleFromString(font_style);
}
if (node->getAttributeString("font-shadow", font_style))
{
if(font_style == "soft")
text_box->mFontShadow = LLFontGL::DROP_SHADOW_SOFT;
else if(font_style == "hard")
text_box->mFontShadow = LLFontGL::DROP_SHADOW;
else
text_box->mFontShadow = LLFontGL::NO_SHADOW;
}
BOOL mouse_opaque = text_box->getMouseOpaque();
if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
{
text_box->setMouseOpaque(mouse_opaque);
}
if(node->hasAttribute("text_color"))
{
LLColor4 color;
LLUICtrlFactory::getAttributeColor(node, "text_color", color);
text_box->setColor(color);
}
if(node->hasAttribute("hover_color"))
{
LLColor4 color;
LLUICtrlFactory::getAttributeColor(node, "hover_color", color);
text_box->setHoverColor(color);
text_box->setHoverActive(true);
}
BOOL hover_active = FALSE;
if(node->getAttributeBOOL("hover", hover_active))
{
text_box->setHoverActive(hover_active);
}
return text_box;
}

View File

@@ -63,6 +63,7 @@ public:
virtual ~LLTextBox() {}
virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
virtual LLXMLNodePtr getXML(bool save_children = true) const;
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);

View File

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

View File

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

View File

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

View File

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

View File

@@ -45,6 +45,8 @@ LLUICtrl::LLUICtrl() :
mViewModel(LLViewModelPtr(new LLViewModel)),
mCommitSignal(NULL),
mValidateSignal(NULL),
mMouseEnterSignal(NULL),
mMouseLeaveSignal(NULL),
mTentative(FALSE),
mTabStop(TRUE),
mIsChrome(FALSE)
@@ -60,6 +62,8 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect rect, BOOL mouse_opaque
mCommitSignal(NULL),
mValidateSignal(NULL),
mViewModel(LLViewModelPtr(new LLViewModel)),
mMouseEnterSignal(NULL),
mMouseLeaveSignal(NULL),
mTentative( FALSE ),
mTabStop( TRUE ),
mIsChrome(FALSE)
@@ -82,6 +86,25 @@ LLUICtrl::~LLUICtrl()
delete mValidateSignal;
}
// virtual
void LLUICtrl::onMouseEnter(S32 x, S32 y, MASK mask)
{
if (mMouseEnterSignal)
{
(*mMouseEnterSignal)(this, getValue());
}
}
// virtual
void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask)
{
if(mMouseLeaveSignal)
{
(*mMouseLeaveSignal)(this, getValue());
}
}
void LLUICtrl::onCommit()
{
if (mCommitSignal)
@@ -452,11 +475,62 @@ BOOL LLUICtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect
void LLUICtrl::initFromXML(LLXMLNodePtr node, LLView* parent)
{
std::string name;
if(node->getAttributeString("name", name))
setName(name);
BOOL has_tab_stop = hasTabStop();
node->getAttributeBOOL("tab_stop", has_tab_stop);
setTabStop(has_tab_stop);
std::string str = node->getName()->mString;
std::string attrib_str;
LLXMLNodePtr child_node;
//Since so many other callback 'types' piggyback off of the commitcallback registrar as well as use the same callback signature
//we can assemble a nice little static list to iterate down instead of copy-pasting mostly similar code for each instance.
//Validate/enable callbacks differ, as it uses its own registry/callback signature. This could be worked around with a template, but keeping
//all the code local to this scope is more beneficial.
typedef boost::signals2::connection (LLUICtrl::*commit_fn)( const commit_signal_t::slot_type& cb );
static std::pair<std::string,commit_fn> sCallbackRegistryMap[3] =
{
std::pair<std::string,commit_fn>(".commit_callback",&LLUICtrl::setCommitCallback),
std::pair<std::string,commit_fn>(".mouseenter_callback",&LLUICtrl::setMouseEnterCallback),
std::pair<std::string,commit_fn>(".mouseleave_callback",&LLUICtrl::setMouseLeaveCallback)
};
for(S32 i= 0; i < sizeof(sCallbackRegistryMap)/sizeof(sCallbackRegistryMap[0]);++i)
{
if(node->getChild((str+sCallbackRegistryMap[i].first).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))
(this->*sCallbackRegistryMap[i].second)(boost::bind((*func), this, LLSD(attrib_str)));
else
(this->*sCallbackRegistryMap[i].second)(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))
setValidateCallback(boost::bind((*func), this, LLSD(attrib_str)));
else
setValidateCallback(enable_signal_t::slot_type(*func));
}
}
}
LLView::initFromXML(node, parent);
}
@@ -546,3 +620,15 @@ boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t
if (!mValidateSignal) mValidateSignal = new enable_signal_t();
return mValidateSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb )
{
if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t();
return mMouseEnterSignal->connect(cb);
}
boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb )
{
if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t();
return mMouseLeaveSignal->connect(cb);
}

View File

@@ -40,6 +40,7 @@
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include "llinitparam.h"
#include "llviewmodel.h" // *TODO move dependency to .cpp file
class LLUICtrl
@@ -48,6 +49,7 @@ class LLUICtrl
public:
typedef boost::function<void (LLUICtrl* ctrl, const LLSD& param)> commit_callback_t;
typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> commit_signal_t;
typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t;
typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t;
LLUICtrl();
@@ -65,6 +67,8 @@ public:
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
/*virtual*/ BOOL isCtrl() const;
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
// From LLFocusableElement
/*virtual*/ void setFocus( BOOL b );
@@ -122,7 +126,9 @@ public:
//Start using these!
boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb );
boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb );
boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb );
boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb );
// *TODO: Deprecate; for backwards compatability only:
boost::signals2::connection setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data);
boost::signals2::connection setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb );
@@ -139,10 +145,20 @@ 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;
enable_signal_t* mValidateSignal;
commit_signal_t* mMouseEnterSignal;
commit_signal_t* mMouseLeaveSignal;
LLViewModelPtr mViewModel;

View File

@@ -102,11 +102,8 @@ public:
static LLView *fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
std::string name("pad");
node->getAttributeString("name", name);
LLUICtrlLocate *new_ctrl = new LLUICtrlLocate();
new_ctrl->setName(name);
new_ctrl->setName("pad");
new_ctrl->initFromXML(node, parent);
return new_ctrl;
}
@@ -285,8 +282,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 +382,13 @@ BOOL LLUICtrlFactory::buildPanelInternal(LLPanel* panelp, LLXMLNodePtr &root, co
mFactoryStack.push_front(factory_map);
}
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
panelp->getCommitCallbackRegistrar().pushScope();
panelp->getEnableCallbackRegistrar().pushScope();
didPost = panelp->initPanelXML(root, NULL, this);
panelp->getCommitCallbackRegistrar().popScope();
panelp->getEnableCallbackRegistrar().popScope();
if (LLUI::sShowXUINames)
{
panelp->setToolTip(filename);

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

@@ -0,0 +1,159 @@
/**
* @file llurlaction.cpp
* @author Martin Reddy
* @brief A set of actions that can performed on Urls
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llurlaction.h"
#include "llview.h"
#include "llwindow.h"
#include "llurlregistry.h"
// global state for the callback functions
LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback;
LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback;
LLUrlAction::url_callback_t LLUrlAction::sOpenURLExternalCallback;
LLUrlAction::execute_url_callback_t LLUrlAction::sExecuteSLURLCallback;
void LLUrlAction::setOpenURLCallback(url_callback_t cb)
{
sOpenURLCallback = cb;
}
void LLUrlAction::setOpenURLInternalCallback(url_callback_t cb)
{
sOpenURLInternalCallback = cb;
}
void LLUrlAction::setOpenURLExternalCallback(url_callback_t cb)
{
sOpenURLExternalCallback = cb;
}
void LLUrlAction::setExecuteSLURLCallback(execute_url_callback_t cb)
{
sExecuteSLURLCallback = cb;
}
void LLUrlAction::openURL(std::string url)
{
if (sOpenURLCallback)
{
sOpenURLCallback(url);
}
}
void LLUrlAction::openURLInternal(std::string url)
{
if (sOpenURLInternalCallback)
{
sOpenURLInternalCallback(url);
}
}
void LLUrlAction::openURLExternal(std::string url)
{
if (sOpenURLExternalCallback)
{
sOpenURLExternalCallback(url);
}
}
void LLUrlAction::executeSLURL(std::string url)
{
if (sExecuteSLURLCallback)
{
sExecuteSLURLCallback(url);
}
}
void LLUrlAction::clickAction(std::string url)
{
// Try to handle as SLURL first, then http Url
if ( (sExecuteSLURLCallback) && !sExecuteSLURLCallback(url) )
{
if (sOpenURLCallback)
{
sOpenURLCallback(url);
}
}
}
void LLUrlAction::teleportToLocation(std::string url)
{
LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
if (! match.getLocation().empty())
{
executeSLURL("secondlife:///app/teleport/" + match.getLocation());
}
}
}
void LLUrlAction::showLocationOnMap(std::string url)
{
LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
if (! match.getLocation().empty())
{
executeSLURL("secondlife:///app/worldmap/" + match.getLocation());
}
}
}
void LLUrlAction::copyURLToClipboard(std::string url)
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url));
}
void LLUrlAction::copyLabelToClipboard(std::string url)
{
LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(match.getLabel()));
}
}
void LLUrlAction::showProfile(std::string url)
{
// Get id from 'secondlife:///app/{cmd}/{id}/{action}'
// and show its profile
LLURI uri(url);
LLSD path_array = uri.pathArray();
if (path_array.size() == 4)
{
std::string id_str = path_array.get(2).asString();
if (LLUUID::validate(id_str))
{
std::string cmd_str = path_array.get(1).asString();
executeSLURL("secondlife:///app/" + cmd_str + "/" + id_str + "/about");
}
}
}

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

@@ -0,0 +1,98 @@
/**
* @file llurlaction.h
* @author Martin Reddy
* @brief A set of actions that can performed on Urls
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLURLACTION_H
#define LL_LLURLACTION_H
#include <string>
#include <boost/function.hpp>
///
/// The LLUrlAction class provides a number of static functions that
/// let you open Urls in web browsers, execute SLURLs, and copy Urls
/// to the clipboard. Many of these functions are not available at
/// the llui level, and must be supplied via a set of callbacks.
///
/// N.B. The action functions specifically do not use const ref
/// strings so that a url parameter can be used into a boost::bind()
/// call under situations when that input string is deallocated before
/// the callback is executed.
///
class LLUrlAction
{
public:
LLUrlAction();
/// load a Url in the user's preferred web browser
static void openURL(std::string url);
/// load a Url in the internal Second Life web browser
static void openURLInternal(std::string url);
/// load a Url in the operating system's default web browser
static void openURLExternal(std::string url);
/// execute the given secondlife: SLURL
static void executeSLURL(std::string url);
/// if the Url specifies an SL location, teleport there
static void teleportToLocation(std::string url);
/// if the Url specifies an SL location, show it on a map
static void showLocationOnMap(std::string url);
/// perform the appropriate action for left-clicking on a Url
static void clickAction(std::string url);
/// copy the label for a Url to the clipboard
static void copyLabelToClipboard(std::string url);
/// copy a Url to the clipboard
static void copyURLToClipboard(std::string url);
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url);
/// specify the callbacks to enable this class's functionality
typedef boost::function<void (const std::string&)> url_callback_t;
typedef boost::function<bool(const std::string& url)> execute_url_callback_t;
static void setOpenURLCallback(url_callback_t cb);
static void setOpenURLInternalCallback(url_callback_t cb);
static void setOpenURLExternalCallback(url_callback_t cb);
static void setExecuteSLURLCallback(execute_url_callback_t cb);
private:
// callbacks for operations we can perform on Urls
static url_callback_t sOpenURLCallback;
static url_callback_t sOpenURLInternalCallback;
static url_callback_t sOpenURLExternalCallback;
static execute_url_callback_t sExecuteSLURLCallback;
};
#endif

1188
indra/llui/llurlentry.cpp Normal file

File diff suppressed because it is too large Load Diff

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

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

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

@@ -0,0 +1,62 @@
/**
* @file llurlmatch.cpp
* @author Martin Reddy
* @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llurlmatch.h"
LLUrlMatch::LLUrlMatch() :
mStart(0),
mEnd(0),
mUrl(""),
mLabel(""),
mTooltip(""),
mIcon(""),
mMenuName(""),
mLocation(""),
mUnderlineOnHoverOnly(false)
{
}
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, /*const LLStyle::Params& style,*/
const std::string &menu, const std::string &location,
const LLUUID& id, bool underline_on_hover_only)
{
mStart = start;
mEnd = end;
mUrl = url;
mLabel = label;
mTooltip = tooltip;
mIcon = icon;
//mStyle = style;
//mStyle.link_href = url;
mMenuName = menu;
mLocation = location;
mID = id;
mUnderlineOnHoverOnly = underline_on_hover_only;
}

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

@@ -0,0 +1,105 @@
/**
* @file llurlmatch.h
* @author Martin Reddy
* @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLURLMATCH_H
#define LL_LLURLMATCH_H
//#include "linden_common.h"
#include <string>
#include <vector>
#include "llstyle.h"
///
/// LLUrlMatch describes a single Url that was matched within a string by
/// the LLUrlRegistry::findUrl() method. It includes the actual Url that
/// was matched along with its first/last character offset in the string.
/// An alternate label is also provided for creating a hyperlink, as well
/// as tooltip/status text, an icon, and a XUI file for a context menu
/// that can be used in a popup for a Url (e.g., Open, Copy URL, etc.)
///
class LLUrlMatch
{
public:
LLUrlMatch();
/// return true if this object does not contain a valid Url match yet
bool empty() const { return mUrl.empty(); }
/// return the offset in the string for the first character of the Url
U32 getStart() const { return mStart; }
/// return the offset in the string for the last character of the Url
U32 getEnd() const { return mEnd; }
/// return the Url that has been matched in the input string
std::string getUrl() const { return mUrl; }
/// return a label that can be used for the display of this Url
std::string getLabel() const { return mLabel; }
/// return a message that could be displayed in a tooltip or status bar
std::string getTooltip() const { return mTooltip; }
/// return the filename for an icon that can be displayed next to this Url
std::string getIcon() const { return mIcon; }
/// Return the color to render the displayed text
//LLStyle::Params getStyle() const { return mStyle; }
/// Return the name of a XUI file containing the context menu items
std::string getMenuName() const { return mMenuName; }
/// return the SL location that this Url describes, or "" if none.
std::string getLocation() const { return mLocation; }
/// Should this link text be underlined only when mouse is hovered over it?
bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
/*const LLStyle::Params& style, */const std::string &menu,
const std::string &location, const LLUUID& id,
bool underline_on_hover_only = false );
const LLUUID& getID() const { return mID; }
private:
U32 mStart;
U32 mEnd;
std::string mUrl;
std::string mLabel;
std::string mTooltip;
std::string mIcon;
std::string mMenuName;
std::string mLocation;
LLUUID mID;
//LLStyle::Params mStyle;
bool mUnderlineOnHoverOnly;
};
#endif

View File

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

View File

@@ -0,0 +1,97 @@
/**
* @file llurlregistry.h
* @author Martin Reddy
* @brief Contains a set of Url types that can be matched in a string
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLURLREGISTRY_H
#define LL_LLURLREGISTRY_H
#include "llurlentry.h"
#include "llurlmatch.h"
#include "llsingleton.h"
#include "llstring.h"
#include <string>
#include <vector>
/// This default callback for findUrl() simply ignores any label updates
void LLUrlRegistryNullCallback(const std::string &url,
const std::string &label,
const std::string &icon);
///
/// LLUrlRegistry is a singleton that contains a set of Url types that
/// can be matched in string. E.g., http:// or secondlife:// Urls.
///
/// Clients call the findUrl() method on a string to locate the first
/// occurence of a supported Urls in that string. If findUrl() returns
/// true, the LLUrlMatch object will be updated to describe the Url
/// that was matched, including a label that can be used to hyperlink
/// the Url, an icon to display next to the Url, and a XUI menu that
/// can be used as a popup context menu for that Url.
///
/// New Url types can be added to the registry with the registerUrl
/// method. E.g., to add support for a new secondlife:///app/ Url.
///
/// Computing the label for a Url could involve a roundtrip request
/// to the server (e.g., to find the actual agent or group name).
/// As such, you can provide a callback method that will get invoked
/// when a new label is available for one of your matched Urls.
///
class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
{
public:
~LLUrlRegistry();
/// add a new Url handler to the registry (will be freed on destruction)
/// optionally force it to the front of the list, making it take
/// priority over other regular expression matches for URLs
void registerUrl(LLUrlEntryBase *url, bool force_front = false);
/// get the next Url in an input string, starting at a given character offset
/// your callback is invoked if the matched Url's label changes in the future
bool findUrl(const std::string &text, LLUrlMatch &match,
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
/// a slightly less efficient version of findUrl for wide strings
bool findUrl(const LLWString &text, LLUrlMatch &match,
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
// return true if the given string contains a URL that findUrl would match
bool hasUrl(const std::string &text);
bool hasUrl(const LLWString &text);
// return true if the given string is a URL that findUrl would match
bool isUrl(const std::string &text);
bool isUrl(const LLWString &text);
private:
LLUrlRegistry();
friend class LLSingleton<LLUrlRegistry>;
std::vector<LLUrlEntryBase *> mUrlEntry;
};
#endif

View File

@@ -74,6 +74,7 @@ BOOL LLView::sForceReshape = FALSE;
LLView* LLView::sEditingUIView = NULL;
S32 LLView::sLastLeftXML = S32_MIN;
S32 LLView::sLastBottomXML = S32_MIN;
std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
LLView::DrilldownFunc LLView::sDrilldown =
boost::bind(&LLView::pointInView, _1, _2, _3, HIT_TEST_USE_BOUNDING_RECT);
@@ -677,6 +678,16 @@ BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
}
void LLView::onMouseEnter(S32 x, S32 y, MASK mask)
{
//llinfos << "Mouse entered " << getName() << llendl;
}
void LLView::onMouseLeave(S32 x, S32 y, MASK mask)
{
//llinfos << "Mouse left " << getName() << llendl;
}
std::string LLView::getShowNamesToolTip()
{
LLView* view = getParent();
@@ -2481,6 +2492,56 @@ void LLView::parseFollowsFlags(const LLView::Params& params)
}
}
LLView::tree_iterator_t LLView::beginTreeDFS()
{
return tree_iterator_t(this,
boost::bind(boost::mem_fn(&LLView::beginChild), _1),
boost::bind(boost::mem_fn(&LLView::endChild), _1));
}
LLView::tree_iterator_t LLView::endTreeDFS()
{
// an empty iterator is an "end" iterator
return tree_iterator_t();
}
LLView::tree_post_iterator_t LLView::beginTreeDFSPost()
{
return tree_post_iterator_t(this,
boost::bind(boost::mem_fn(&LLView::beginChild), _1),
boost::bind(boost::mem_fn(&LLView::endChild), _1));
}
LLView::tree_post_iterator_t LLView::endTreeDFSPost()
{
// an empty iterator is an "end" iterator
return tree_post_iterator_t();
}
LLView::bfs_tree_iterator_t LLView::beginTreeBFS()
{
return bfs_tree_iterator_t(this,
boost::bind(boost::mem_fn(&LLView::beginChild), _1),
boost::bind(boost::mem_fn(&LLView::endChild), _1));
}
LLView::bfs_tree_iterator_t LLView::endTreeBFS()
{
// an empty iterator is an "end" iterator
return bfs_tree_iterator_t();
}
LLView::root_to_view_iterator_t LLView::beginRootToView()
{
return root_to_view_iterator_t(this, boost::bind(&LLView::getParent, _1));
}
LLView::root_to_view_iterator_t LLView::endRootToView()
{
return root_to_view_iterator_t();
}
// static
U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect)
{
@@ -2944,6 +3005,32 @@ S32 LLView::notifyParent(const LLSD& info)
return parent->notifyParent(info);
return 0;
}
bool LLView::notifyChildren(const LLSD& info)
{
bool ret = false;
BOOST_FOREACH(LLView* childp, mChildList)
{
ret = ret || childp->notifyChildren(info);
}
return ret;
}
// convenient accessor for draw context
const LLViewDrawContext& LLView::getDrawContext()
{
return LLViewDrawContext::getCurrentContext();
}
const LLViewDrawContext& LLViewDrawContext::getCurrentContext()
{
static LLViewDrawContext default_context;
if (sDrawContextStack.empty())
return default_context;
return *sDrawContextStack.back();
}
LLView* LLView::createWidget(LLXMLNodePtr xml_node) const
{
// forward requests to ui ctrl factory

View File

@@ -55,6 +55,7 @@
#include "lluistring.h"
#include "llcursortypes.h"
#include "llinitparam.h"
#include "lltreeiterators.h"
#include "llfocusmgr.h"
#include <boost/unordered_map.hpp>
#include "ailist.h"
@@ -130,6 +131,35 @@ public:
}
};
// maintains render state during traversal of UI tree
class LLViewDrawContext
{
public:
F32 mAlpha;
LLViewDrawContext(F32 alpha = 1.f)
: mAlpha(alpha)
{
if (!sDrawContextStack.empty())
{
LLViewDrawContext* context_top = sDrawContextStack.back();
// merge with top of stack
mAlpha *= context_top->mAlpha;
}
sDrawContextStack.push_back(this);
}
~LLViewDrawContext()
{
sDrawContextStack.pop_back();
}
static const LLViewDrawContext& getCurrentContext();
private:
static std::vector<LLViewDrawContext*> sDrawContextStack;
};
class LLView
: public LLMouseHandler, // handles mouse events
public LLFocusableElement, // handles keyboard events
@@ -378,7 +408,24 @@ public:
BOOL hasAncestor(const LLView* parentp) const;
BOOL hasChild(const std::string& childname, BOOL recurse = FALSE) const;
BOOL childHasKeyboardFocus( const std::string& childname ) const;
// these iterators are used for collapsing various tree traversals into for loops
typedef LLTreeDFSIter<LLView, child_list_const_iter_t> tree_iterator_t;
tree_iterator_t beginTreeDFS();
tree_iterator_t endTreeDFS();
typedef LLTreeDFSPostIter<LLView, child_list_const_iter_t> tree_post_iterator_t;
tree_post_iterator_t beginTreeDFSPost();
tree_post_iterator_t endTreeDFSPost();
typedef LLTreeBFSIter<LLView, child_list_const_iter_t> bfs_tree_iterator_t;
bfs_tree_iterator_t beginTreeBFS();
bfs_tree_iterator_t endTreeBFS();
typedef LLTreeDownIter<LLView> root_to_view_iterator_t;
root_to_view_iterator_t beginRootToView();
root_to_view_iterator_t endRootToView();
//
// UTILITIES
@@ -489,6 +536,9 @@ public:
virtual LLView* childFromPoint(S32 x, S32 y, bool recur=false);
// view-specific handlers
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
template <class T> T* findChild(const std::string& name)
{
return getChild<T>(name,true,false);
@@ -607,6 +657,16 @@ public:
//send custom notification to LLView parent
virtual S32 notifyParent(const LLSD& info);
//send custom notification to all view childrend
// return true if _any_ children return true. otherwise false.
virtual bool notifyChildren(const LLSD& info);
//send custom notification to current view
virtual S32 notify(const LLSD& info) { return 0;};
static const LLViewDrawContext& getDrawContext();
protected:
void drawDebugRect();
void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE);

View File

@@ -104,6 +104,8 @@ void LLViewBorder::draw()
void LLViewBorder::drawOnePixelLines()
{
F32 alpha = getDrawContext().mAlpha;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLColor4 top_color = mHighlightLight;
@@ -138,6 +140,9 @@ void LLViewBorder::drawOnePixelLines()
S32 right = getRect().getWidth();
S32 bottom = 0;
top_color %= alpha;
bottom_color %= alpha;
gGL.color4fv( top_color.mV );
gl_line_2d(left, bottom, left, top);
gl_line_2d(left, top, right, top);

View File

@@ -41,6 +41,17 @@
#include "lluuid.h"
#include "lldiriterator.h"
#include "stringize.h"
#include <boost/foreach.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <algorithm>
using boost::assign::list_of;
using boost::assign::map_list_of;
#if LL_WINDOWS
#include "lldir_win32.h"
@@ -86,12 +97,17 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
std::string fullpath;
S32 result;
// File masks starting with "/" will match nothing, so we consider them invalid.
if (LLStringUtil::startsWith(mask, getDirDelimiter()))
{
llwarns << "Invalid file mask: " << mask << llendl;
llassert(!"Invalid file mask");
}
LLDirIterator iter(dirname, mask);
while (iter.next(filename))
{
fullpath = dirname;
fullpath += getDirDelimiter();
fullpath += filename;
fullpath = add(dirname, filename);
if(LLFile::isdir(fullpath))
{
@@ -259,12 +275,12 @@ std::string LLDir::buildSLOSCacheDir() const
}
else
{
res = getOSUserAppDir() + mDirDelimiter + "cache_sg1";
res = add(getOSUserAppDir(), "cache_sg1");
}
}
else
{
res = getOSCacheDir() + mDirDelimiter + "SingularityViewer";
res = add(getOSCacheDir(), "SingularityViewer");
}
return res;
}
@@ -312,6 +328,39 @@ const std::string &LLDir::getLLPluginDir() const
return mLLPluginDir;
}
static std::string ELLPathToString(ELLPath location)
{
typedef std::map<ELLPath, const char*> ELLPathMap;
#define ENT(symbol) (symbol, #symbol)
static const ELLPathMap sMap = map_list_of
ENT(LL_PATH_NONE)
ENT(LL_PATH_USER_SETTINGS)
ENT(LL_PATH_APP_SETTINGS)
ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet
ENT(LL_PATH_CACHE)
ENT(LL_PATH_CHARACTER)
ENT(LL_PATH_HELP)
ENT(LL_PATH_LOGS)
ENT(LL_PATH_TEMP)
ENT(LL_PATH_SKINS)
ENT(LL_PATH_TOP_SKIN)
ENT(LL_PATH_CHAT_LOGS)
ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS)
ENT(LL_PATH_USER_SKIN)
ENT(LL_PATH_LOCAL_ASSETS)
ENT(LL_PATH_EXECUTABLE)
ENT(LL_PATH_DEFAULT_SKIN)
ENT(LL_PATH_FONTS)
ENT(LL_PATH_LAST)
;
#undef ENT
ELLPathMap::const_iterator found = sMap.find(location);
if (found != sMap.end())
return found->second;
return STRINGIZE("Invalid ELLPath value " << location);
}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
{
return getExpandedFilename(location, "", filename);
@@ -332,15 +381,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 +397,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 +413,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 +437,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,56 +445,36 @@ 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:
llassert(0);
}
std::string filename = in_filename;
if (!subdir2.empty())
{
filename = subdir2 + mDirDelimiter + filename;
}
if (!subdir1.empty())
{
filename = subdir1 + mDirDelimiter + filename;
}
if (prefix.empty())
{
llwarns << "prefix is empty, possible bad filename" << llendl;
}
std::string expanded_filename;
if (!filename.empty())
{
if (!prefix.empty())
{
expanded_filename += prefix;
expanded_filename += mDirDelimiter;
expanded_filename += filename;
}
else
{
expanded_filename = filename;
}
}
else if (!prefix.empty())
{
// Directory only, no file name.
expanded_filename = prefix;
}
else
{
expanded_filename.assign("");
llwarns << ELLPathToString(location)
<< ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
<< "': prefix is empty, possible bad filename" << llendl;
}
//llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl;
std::string expanded_filename = add(add(prefix, subdir1), subdir2);
if (expanded_filename.empty() && in_filename.empty())
{
return "";
}
// Use explicit concatenation here instead of another add() call. Callers
// passing in_filename as "" expect to obtain a pathname ending with
// mDirSeparator so they can later directly concatenate with a specific
// filename. A caller using add() doesn't care, but there's still code
// loose in the system that uses std::string::operator+().
expanded_filename += mDirDelimiter;
expanded_filename += in_filename;
LL_DEBUGS("LLDir") << ELLPathToString(location)
<< ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
<< "' => '" << expanded_filename << "'" << LL_ENDL;
return expanded_filename;
}
@@ -530,12 +549,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 +586,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 +625,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 +645,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 +670,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 +703,57 @@ void LLDir::dumpCurrentDirectories()
LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
}
std::string LLDir::add(const std::string& path, const std::string& name) const
{
std::string destpath(path);
append(destpath, name);
return destpath;
}
void LLDir::append(std::string& destpath, const std::string& name) const
{
// Delegate question of whether we need a separator to helper method.
SepOff sepoff(needSep(destpath, name));
if (sepoff.first) // do we need a separator?
{
destpath += mDirDelimiter;
}
// If destpath ends with a separator, AND name starts with one, skip
// name's leading separator.
destpath += name.substr(sepoff.second);
}
LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const
{
if (path.empty() || name.empty())
{
// If either path or name are empty, we do not need a separator
// between them.
return SepOff(false, 0);
}
// Here we know path and name are both non-empty. But if path already ends
// with a separator, or if name already starts with a separator, we need
// not add one.
std::string::size_type seplen(mDirDelimiter.length());
bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter);
bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter);
if ((! path_ends_sep) && (! name_starts_sep))
{
// If neither path nor name brings a separator to the junction, then
// we need one.
return SepOff(true, 0);
}
if (path_ends_sep && name_starts_sep)
{
// But if BOTH path and name bring a separator, we need not add one.
// Moreover, we should actually skip the leading separator of 'name'.
return SepOff(false, seplen);
}
// Here we know that either path_ends_sep or name_starts_sep is true --
// but not both. So don't add a separator, and don't skip any characters:
// simple concatenation will do the trick.
return SepOff(false, 0);
}
void dir_exists_or_crash(const std::string &dir_name)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,31 +3,25 @@
* @brief Prototypes for functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
* Copyright (C) 2010, Linden Research, Inc.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -3,31 +3,25 @@
* @brief Definition of functions shared between llwindowmacosx.cpp
* and llwindowmacosx-objc.mm.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
* Copyright (C) 2010, Linden Research, Inc.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1133,9 +1133,7 @@ void *updatethreadproc(void*)
llinfos << "Clearing cache..." << llendl;
char mask[LL_MAX_PATH]; /* Flawfinder: ignore */
snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str());
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),"*.*");
llinfos << "Clear complete." << llendl;

View File

@@ -220,7 +220,7 @@ set(viewer_SOURCE_FILES
llfloaterlandholdings.cpp
llfloaterlandmark.cpp
llfloatermap.cpp
llfloatermediabrowser.cpp
llfloatermediasettings.cpp
llfloatermemleak.cpp
llfloatermessagelog.cpp
llfloatermodelpreview.cpp
@@ -259,7 +259,10 @@ set(viewer_SOURCE_FILES
llfloatertos.cpp
llfloaterurldisplay.cpp
llfloaterurlentry.cpp
llfloatervoiceeffect.cpp
llfloaterwater.cpp
llfloaterwebcontent.cpp
llfloaterwhitelistentry.cpp
llfloaterwindlight.cpp
llfloaterworldmap.cpp
llfolderview.cpp
@@ -314,6 +317,7 @@ set(viewer_SOURCE_FILES
llmarketplacefunctions.cpp
llmarketplacenotifications.cpp
llmediactrl.cpp
llmediadataclient.cpp
llmediaremotectrl.cpp
llmenucommands.cpp
llmenuoptionpathfindingrebakenavmesh.cpp
@@ -364,7 +368,10 @@ set(viewer_SOURCE_FILES
llpanellogin.cpp
llpanelmaininventory.cpp
llpanelmarketplaceoutboxinventory.cpp
llpanelmediahud.cpp
llpanelmediasettingsgeneral.cpp
llpanelmediasettingspermissions.cpp
llpanelmediasettingssecurity.cpp
llpanelnearbymedia.cpp
llpanelmorph.cpp
llpanelmsgs.cpp
llpanelnetwork.cpp
@@ -373,9 +380,11 @@ set(viewer_SOURCE_FILES
llpanelpermissions.cpp
llpanelpick.cpp
llpanelplace.cpp
llpanelprimmediacontrols.cpp
llpanelprofile.cpp
llpanelskins.cpp
llpanelvoicedevicesettings.cpp
llpanelvoiceeffect.cpp
llpanelvolume.cpp
llpanelweb.cpp
llparcelselection.cpp
@@ -414,6 +423,7 @@ set(viewer_SOURCE_FILES
llscrollingpanelparambase.cpp
llselectmgr.cpp
llsky.cpp
llslurl.cpp
llspatialpartition.cpp
llspeakers.cpp
llsprite.cpp
@@ -456,7 +466,6 @@ set(viewer_SOURCE_FILES
llurl.cpp
llurldispatcher.cpp
llurlhistory.cpp
llurlsimstring.cpp
llurlwhitelist.cpp
lluserauth.cpp
llvectorperfoptions.cpp
@@ -482,9 +491,7 @@ set(viewer_SOURCE_FILES
llviewerlayer.cpp
llviewermedia.cpp
llviewermedia_streamingaudio.cpp
llviewermediaeventemitter.cpp
llviewermediafocus.cpp
llviewermediaobserver.cpp
llviewermenu.cpp
llviewermenufile.cpp
llviewermessage.cpp
@@ -519,6 +526,7 @@ set(viewer_SOURCE_FILES
llvoclouds.cpp
llvograss.cpp
llvoground.cpp
llvoicecallhandler.cpp
llvoicechannel.cpp
llvoiceclient.cpp
llvoiceremotectrl.cpp
@@ -722,7 +730,7 @@ set(viewer_HEADER_FILES
llfloaterlandholdings.h
llfloaterlandmark.h
llfloatermap.h
llfloatermediabrowser.h
llfloatermediasettings.h
llfloatermemleak.h
llfloatermessagelog.h
llfloatermodelpreview.h
@@ -761,7 +769,10 @@ set(viewer_HEADER_FILES
llfloatertos.h
llfloaterurldisplay.h
llfloaterurlentry.h
llfloatervoiceeffect.h
llfloaterwater.h
llfloaterwebcontent.h
llfloaterwhitelistentry.h
llfloaterwindlight.h
llfloaterworldmap.h
llfolderview.h
@@ -816,6 +827,7 @@ set(viewer_HEADER_FILES
llmarketplacefunctions.h
llmarketplacenotifications.h
llmediactrl.h
llmediadataclient.h
llmediaremotectrl.h
llmenucommands.h
llmenuoptionpathfindingrebakenavmesh.h
@@ -866,7 +878,10 @@ set(viewer_HEADER_FILES
llpanellogin.h
llpanelmaininventory.h
llpanelmarketplaceoutboxinventory.h
llpanelmediahud.h
llpanelmediasettingsgeneral.h
llpanelmediasettingspermissions.h
llpanelmediasettingssecurity.h
llpanelnearbymedia.h
llpanelmorph.h
llpanelmsgs.h
llpanelnetwork.h
@@ -875,9 +890,11 @@ set(viewer_HEADER_FILES
llpanelpermissions.h
llpanelpick.h
llpanelplace.h
llpanelprimmediacontrols.h
llpanelprofile.h
llpanelskins.h
llpanelvoicedevicesettings.h
llpanelvoiceeffect.h
llpanelvolume.h
llpanelweb.h
llparcelselection.h
@@ -918,6 +935,7 @@ set(viewer_HEADER_FILES
llselectmgr.h
llsimplestat.h
llsky.h
llslurl.h
llspatialpartition.h
llspeakers.h
llsprite.h
@@ -963,7 +981,6 @@ set(viewer_HEADER_FILES
llurl.h
llurldispatcher.h
llurlhistory.h
llurlsimstring.h
llurlwhitelist.h
lluserauth.h
llvectorperfoptions.h
@@ -988,9 +1005,7 @@ set(viewer_HEADER_FILES
llviewerkeyboard.h
llviewerlayer.h
llviewermedia.h
llviewermediaeventemitter.h
llviewermediafocus.h
llviewermediaobserver.h
llviewermenu.h
llviewermenufile.h
llviewermessage.h

View File

@@ -425,7 +425,19 @@
</array>
</map>
<!-- Begin: AO-->
<key>ShowNearbyMediaFloater</key>
<map>
<key>Comment</key>
<string>Show nearby media floter</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<!-- Begin: AO-->
<key>ShowAOSitPopup</key>
<map>
@@ -1158,7 +1170,7 @@ This should be as low as possible, but too low may break functionality</string>
<key>Comment</key>
<string>Show Windlight popup</string>
<key>Persist</key>
<integer>0</integer>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
@@ -2257,6 +2269,17 @@ This should be as low as possible, but too low may break functionality</string>
<string>F32</string>
<key>Value</key>
<real>0.075</real>
</map>
<key>AudioStreamingMedia</key>
<map>
<key>Comment</key>
<string>Enable streaming</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>AudioStreamingMusic</key>
<map>
@@ -2269,17 +2292,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>AudioStreamingVideo</key>
<map>
<key>Comment</key>
<string>Enable streaming video</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AuditTexture</key>
<map>
<key>Comment</key>
@@ -2724,23 +2736,23 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PluginAttachDebuggerToPlugins</key>
<key>BrowserEnableJSObject</key>
<map>
<key>Comment</key>
<string>Opens a terminal window with a debugger and attach it, every time a new SLPlugin process is started.</string>
<string>(WARNING: Advanced feature. Use if you are aware of the implications). Enable or disable the viewer to Javascript bridge object.</string>
<key>Persist</key>
<integer>1</integer>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<integer>0</integer>
</map>
<key>BlockAvatarAppearanceMessages</key>
<map>
<key>Comment</key>
<string>Ignores appearance messages (for simulating Ruth)</string>
<key>Persist</key>
<integer>1</integer>
<map>
<key>Comment</key>
<string>Ignores appearance messages (for simulating Ruth)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
@@ -3802,17 +3814,6 @@ This should be as low as possible, but too low may break functionality</string>
<string/>
</array>
</map>
<key>CmdLineRegionURI</key>
<map>
<key>Comment</key>
<string>URL of region to connect to through Agent Domain.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>ColorPaletteEntry01</key>
<map>
<key>Comment</key>
@@ -5452,6 +5453,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DisableExternalBrowser</key>
<map>
<key>Comment</key>
<string>Disable opening an external browser.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DisableRendering</key>
<map>
<key>Comment</key>
@@ -5463,6 +5475,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>
@@ -6036,17 +6059,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FirstLoginThisInstall</key>
<map>
<key>Comment</key>
<string>Specifies that you have not successfully logged in since you installed the latest update</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FirstName</key>
<map>
<key>Comment</key>
@@ -6091,6 +6103,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FirstLoginThisInstall</key>
<map>
<key>Comment</key>
<string>Specifies that you have not successfully logged in since you installed the latest update</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FixedWeather</key>
<map>
<key>Comment</key>
@@ -7438,6 +7461,22 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>-1</integer>
</map>
<key>FloaterVoiceEffectRect</key>
<map>
<key>Comment</key>
<string>Rectangle for voice morpher floater</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Rect</string>
<key>Value</key>
<array>
<integer>0</integer>
<integer>300</integer>
<integer>360</integer>
<integer>0</integer>
</array>
</map>
<key>FloaterWorldMapRect2</key>
<map>
<key>Comment</key>
@@ -8812,6 +8851,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LastMediaSettingsTab</key>
<map>
<key>Comment</key>
<string>Last selected tab in media settings window</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LastRunVersion</key>
<map>
<key>Comment</key>
@@ -9131,16 +9181,16 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LoginLastLocation</key>
<key>LoginLocation</key>
<map>
<key>Comment</key>
<string>Login at same location you last logged out</string>
<string>Default Login location ('last', 'home') preference</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<string>String</string>
<key>Value</key>
<integer>1</integer>
<string>last</string>
</map>
<key>LoginPage</key>
<map>
@@ -9457,13 +9507,68 @@ This should be as low as possible, but too low may break functionality</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>MemoryFailurePreventionEnabled</key>
<map>
<key>Comment</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MediaPerformanceManagerDebug</key>
<map>
<key>Comment</key>
<string>Whether to show debug data for the media performance manager in the nearby media list.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>MediaShowOnOthers</key>
<map>
<key>Comment</key>
<string>Whether or not to show media on other avatars</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>MediaShowOutsideParcel</key>
<map>
<key>Comment</key>
<string>Whether or not to show media from outside the current parcel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MediaShowWithinParcel</key>
<map>
<key>Comment</key>
<string>Whether or not to show media within the current parcel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MediaTentativeAutoPlay</key>
<map>
<key>Comment</key>
<string>This is a tentative flag that may be temporarily set off by the user, until she teleports</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MemoryFailurePreventionEnabled</key>
<map>
<key>Comment</key>
<string>If set, the viewer will quit to avoid crash when memory failure happens</string>
<key>Persist</key>
<integer>1</integer>
@@ -10448,6 +10553,86 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>PluginAttachDebuggerToPlugins</key>
<map>
<key>Comment</key>
<string>If true, attach a debugger session to each plugin process as it's launched.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PluginInstancesCPULimit</key>
<map>
<key>Comment</key>
<string>Amount of total plugin CPU usage before inworld plugins start getting turned down to "slideshow" priority. Set to 0 to disable this check.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.9</real>
</map>
<key>PlainTextChatHistory</key>
<map>
<key>Comment</key>
<string>Enable/Disable plain text chat history style</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PluginInstancesLow</key>
<map>
<key>Comment</key>
<string>Limit on the number of inworld media plugins that will run at "low" priority</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>4</integer>
</map>
<key>PluginInstancesNormal</key>
<map>
<key>Comment</key>
<string>Limit on the number of inworld media plugins that will run at "normal" or higher priority</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>2</integer>
</map>
<key>PluginInstancesTotal</key>
<map>
<key>Comment</key>
<string>Hard limit on the number of plugins that will be instantiated at once for inworld media</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>8</integer>
</map>
<key>PluginUseReadThread</key>
<map>
<key>Comment</key>
<string>Use a separate thread to read incoming messages from plugins</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PlayTypingSound</key>
<map>
<key>Comment</key>
@@ -10651,6 +10836,94 @@ This should be as low as possible, but too low may break functionality</string>
</array>
</map>
<key>PrimMediaMasterEnabled</key>
<map>
<key>Comment</key>
<string>Whether or not Media on a Prim is enabled.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>PrimMediaControlsUseHoverControlSet</key>
<map>
<key>Comment</key>
<string>Whether or not hovering over prim media uses minimal "hover" controls or the authored control set.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PrimMediaDragNDrop</key>
<map>
<key>Comment</key>
<string>Enable drag and drop of URLs onto prim faces</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>PrimMediaMaxRetries</key>
<map>
<key>Comment</key>
<string>Maximum number of retries for media queries.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>4</integer>
</map>
<key>PrimMediaRequestQueueDelay</key>
<map>
<key>Comment</key>
<string>Timer delay for fetching media from the queue (in seconds).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>PrimMediaRetryTimerDelay</key>
<map>
<key>Comment</key>
<string>Timer delay for retrying on media queries (in seconds).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>5.0</real>
</map>
<key>PrimMediaMaxSortedQueueSize</key>
<map>
<key>Comment</key>
<string>Maximum number of objects the viewer will load media for initially</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>100000</integer>
</map>
<key>PrimMediaMaxRoundRobinQueueSize</key>
<map>
<key>Comment</key>
<string>Maximum number of objects the viewer will continuously update media for</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>100000</integer>
</map>
<key>PreviewAnimRect</key>
<map>
<key>Comment</key>
@@ -10959,6 +11232,50 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>WebContentWindowLimit</key>
<map>
<key>Comment</key>
<string>Maximum number of web browser windows that can be open at once in the Web content floater (0 for no limit)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>5</integer>
</map>
<key>MediaRollOffRate</key>
<map>
<key>Comment</key>
<string>Multiplier to change rate of media attenuation</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.125</real>
</map>
<key>MediaRollOffMin</key>
<map>
<key>Comment</key>
<string>Adjusts the distance at which media attentuation starts</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>5.0</real>
</map>
<key>MediaRollOffMax</key>
<map>
<key>Comment</key>
<string>Distance at which media volume is set to 0</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>30.0</real>
</map>
<key>RecentItemsSortOrder</key>
<map>
<key>Comment</key>
@@ -16475,6 +16792,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<real>0.40000000596</real>
</map>
<key>moapbeacon</key>
<map>
<key>Comment</key>
<string>Beacon / Highlight media on a prim sources</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>particlesbeacon</key>
<map>
<key>Comment</key>
@@ -16573,6 +16901,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>
@@ -16585,17 +16935,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>keepbeacons</key>
<map>
<key>Comment</key>
<string>Keep beacons when closing floater</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ClearBeaconAfterTeleport</key>
<map>
<key>Comment</key>
@@ -16651,6 +16990,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>
@@ -16770,6 +17122,22 @@ This should be as low as possible, but too low may break functionality</string>
<integer>473</integer>
</array>
</map>
<key>FloaterNearbyMediaRect</key>
<map>
<key>Comment</key>
<string>Rectangle for nearby media floater.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Rect</string>
<key>Value</key>
<array>
<integer>0</integer>
<integer>0</integer>
<integer>0</integer>
<integer>0</integer>
</array>
</map>
<key>WindEnabled</key>
<map>
<key>Comment</key>

View File

@@ -41,6 +41,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>SHEnableFMODEXVerboseDebugging</key>
<map>
<key>Comment</key>
<string>Enable profiler tool if using FMOD Ex</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SHFMODExStreamBufferSize</key>
<map>
<key>Comment</key>

View File

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

View File

@@ -506,7 +506,7 @@ void HippoGridInfo::formatFee(std::string &fee, int cost, bool showFree) const
}
//static
std::string HippoGridInfo::sanitizeGridNick(std::string &gridnick)
std::string HippoGridInfo::sanitizeGridNick(const std::string &gridnick)
{
std::string tmp;
int size = gridnick.size();
@@ -529,7 +529,7 @@ std::string HippoGridInfo::sanitizeGridNick(std::string &gridnick)
}
std::string HippoGridInfo::getGridNick()
std::string HippoGridInfo::getGridNick() const
{
if(!mGridNick.empty())
{
@@ -684,42 +684,57 @@ void HippoGridManager::discardAndReload()
HippoGridInfo* HippoGridManager::getGrid(const std::string& grid) const
{
if(grid.empty())
return NULL;
std::map<std::string, HippoGridInfo*>::const_iterator it;
it = mGridInfo.find(grid);
//The grids are keyed by 'name' which equates to something like "Second Life"
//Try to match such first.
if (it != mGridInfo.end())
{
return it->second;
}
else
else //Fall back to nick short names. (so something like "secondlife" will work)
{
return 0;
for(it = mGridInfo.begin(); it != mGridInfo.end(); ++it)
{
if(it->second && LLStringUtil::compareInsensitive(it->second->getGridNick(), grid)==0)
return it->second;
}
}
return NULL;
}
HippoGridInfo* HippoGridManager::getCurrentGrid() const
{
HippoGridInfo* grid = getGrid(mCurrentGrid);
if (grid)
if(!grid)
{
return grid;
}
else
{
return &HippoGridInfo::FALLBACK_GRIDINFO;
grid = getGrid(mDefaultGrid);
}
return grid ? grid : &HippoGridInfo::FALLBACK_GRIDINFO;
}
const std::string& HippoGridManager::getDefaultGridNick() const
std::string HippoGridManager::getDefaultGridNick() const
{
HippoGridInfo* grid = getGrid(mDefaultGrid);
return grid ? grid->getGridNick() : HippoGridInfo::FALLBACK_GRIDINFO.getGridNick();
}
std::string HippoGridManager::getCurrentGridNick() const
{
return getCurrentGrid()->getGridNick();
}
const std::string& HippoGridManager::getDefaultGridName() const
{
return mDefaultGrid;
}
const std::string& HippoGridManager::getCurrentGridNick() const
const std::string& HippoGridManager::getCurrentGridName() const
{
if (mCurrentGrid.empty())
{
return mDefaultGrid;
}
return mCurrentGrid;
}

View File

@@ -57,7 +57,7 @@ public:
const std::string& getVoiceConnector() const { return mVoiceConnector; }
std::string getSearchUrl(SearchType ty, bool is_web) const;
bool isRenderCompat() const { return mRenderCompat; }
std::string getGridNick();
std::string getGridNick() const;
int getMaxAgentGroups() const { return mMaxAgentGroups; }
const std::string& getCurrencySymbol() const { return mCurrencySymbol; }
@@ -99,7 +99,7 @@ public:
bool retrieveGridInfo();
static const char* getPlatformString(Platform platform);
static std::string sanitizeGridNick(std::string &gridnick);
static std::string sanitizeGridNick(const std::string &gridnick);
static HippoGridInfo FALLBACK_GRIDINFO;
static void initFallback();
@@ -163,8 +163,10 @@ public:
HippoGridInfo* getConnectedGrid() const { return mConnectedGrid ? mConnectedGrid : getCurrentGrid(); }
HippoGridInfo* getCurrentGrid() const;
const std::string& getDefaultGridNick() const;
const std::string& getCurrentGridNick() const;
std::string getDefaultGridNick() const;
std::string getCurrentGridNick() const;
const std::string& getDefaultGridName() const;
const std::string& getCurrentGridName() const;
void setDefaultGrid(const std::string& grid);
void setCurrentGrid(const std::string& grid);

View File

@@ -164,7 +164,7 @@ BOOL HippoPanelGridsImpl::postBuild()
// called internally too
void HippoPanelGridsImpl::refresh()
{
const std::string &defaultGrid = gHippoGridManager->getDefaultGridNick();
const std::string &defaultGrid = gHippoGridManager->getDefaultGridName();
LLComboBox *grids = getChild<LLComboBox>("grid_selector");
S32 selectIndex = -1, i = 0;
@@ -365,7 +365,7 @@ bool HippoPanelGridsImpl::saveCurGrid()
void HippoPanelGridsImpl::reset()
{
mState = NORMAL;
mCurGrid = gHippoGridManager->getCurrentGridNick();
mCurGrid = gHippoGridManager->getCurrentGridName();
loadCurGrid();
}

View File

@@ -57,6 +57,7 @@
#include "llsdmessage.h"
#include "llsdutil.h"
#include "llsky.h"
#include "llslurl.h"
#include "llsmoothstep.h"
#include "llspeakers.h"
#include "llstartup.h"
@@ -65,6 +66,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"
@@ -345,6 +348,7 @@ LLAgent::LLAgent() :
mAgentAccess(new LLAgentAccess(gSavedSettings)),
mGodLevelChangeSignal(),
mCanEditParcel(false),
mTeleportSourceSLURL(new LLSLURL),
mTeleportRequest(),
mTeleportFinishedSlot(),
mTeleportFailedSlot(),
@@ -485,6 +489,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
@@ -949,24 +955,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()
@@ -3916,7 +3904,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
@@ -4308,7 +4296,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:
@@ -4734,6 +4722,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 )
{
@@ -4787,14 +4779,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.
{
@@ -4802,8 +4793,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
}
}
@@ -4814,7 +4805,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();
@@ -4823,7 +4814,7 @@ void LLAgent::onFoundLureDestination(LLSimInfo *siminfo)
llinfos << mPendingLure->mAvatarName << "'s teleport lure is to " << sim_name << " (" << maturity << ")" << llendl;
LLStringUtil::format_map_t args;
args["[NAME]"] = mPendingLure->mAvatarName;
args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name, (S32)mPendingLure->mPosLocal[0], (S32)mPendingLure->mPosLocal[1], (S32)mPendingLure->mPosLocal[2] );
args["[DESTINATION]"] = LLSLURL(sim_name,mPendingLure->mPosLocal).getSLURLString();
std::string msg = LLTrans::getString("TeleportOfferMaturity", args);
if (!maturity.empty())
{

View File

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

View File

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

View File

@@ -56,6 +56,7 @@
#include "llmodaldialog.h"
#include "llpumpio.h"
#include "llmimetypes.h"
#include "llslurl.h"
#include "llstartup.h"
#include "llfocusmgr.h"
#include "llviewerjoystick.h"
@@ -80,6 +81,7 @@
#include "llvector4a.h"
#include "llvoicechannel.h"
#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
@@ -749,9 +752,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
@@ -969,6 +974,8 @@ bool LLAppViewer::init()
LLEnvManagerNew::instance().usePrefs();
gGLActive = FALSE;
LLViewerMedia::initClass();
LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ;
return true;
}
@@ -1695,8 +1702,7 @@ bool LLAppViewer::cleanup()
if (mPurgeOnExit)
{
llinfos << "Purging all cache files on exit" << llendflush;
std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),"*.*");
}
removeMarkerFile(); // Any crashes from here on we'll just have to ignore
@@ -1773,7 +1779,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
@@ -2323,30 +2328,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");
@@ -2425,18 +2417,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;
@@ -2492,9 +2477,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");
@@ -2678,8 +2664,7 @@ void LLAppViewer::cleanupSavedSettings()
void LLAppViewer::removeCacheFiles(const std::string& file_mask)
{
std::string mask = gDirUtilp->getDirDelimiter() + file_mask;
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask);
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask);
}
void LLAppViewer::writeSystemInfo()

View File

@@ -459,7 +459,7 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ
std::string url = slurl;
LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
if (LLURLDispatcher::dispatch(url, web, trusted_browser))
if (LLURLDispatcher::dispatch(url, "", web, trusted_browser))
{
// bring window to foreground, as it has just been "launched" from a URL
// todo: hmm, how to get there from here?

View File

@@ -43,7 +43,6 @@
#include "llviewernetwork.h"
#include "llviewercontrol.h"
#include "llmd5.h"
#include "llurlsimstring.h"
#include "llfloaterworldmap.h"
#include "llurldispatcher.h"
#include <Carbon/Carbon.h>
@@ -476,7 +475,7 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
LLURLDispatcher::dispatch(url, web, trusted_browser);
LLURLDispatcher::dispatch(url, "", web, trusted_browser);
}
return(result);

View File

@@ -488,7 +488,7 @@ bool LLAppViewerWin32::initHardwareTest()
if (OSBTN_NO== button)
{
LL_INFOS("AppInit") << "User quitting after failed DirectX 9 detection" << LL_ENDL;
LLWeb::loadURLExternal(DIRECTX_9_URL);
LLWeb::loadURLExternal(DIRECTX_9_URL, false);
return false;
}
gSavedSettings.setWarning("AboutDirectX9", FALSE);

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