Merge branch 'DRTVWR-501-maint' into DRTVWR-503-maint

# Conflicts:
#	indra/llcommon/llkeybind.cpp
#	indra/llcommon/llkeybind.h
master
Andrey Lihatskiy 2020-06-24 00:08:35 +03:00
commit b8127f80c7
66 changed files with 2294 additions and 5660 deletions

1
.gitignore vendored
View File

@ -68,6 +68,7 @@ indra/web/doc/asset-upload/plugins/verify-texture
installed.xml
libraries
tarfile_tmp
trivial_change_force_build
web/config.*
web/locale.*
web/secondlife.com.*

View File

@ -1,6 +1,5 @@
Second Life Viewer
====================
This project manages the source code for the
[Second Life](https://www.secondlife.com) Viewer.

View File

@ -580,9 +580,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>23aeaf23e7db2484a1850017141860dd</string>
<string>350866eec6be17ffc265904b91dcfe6b</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34069/283470/dullahan-1.1.1320_3.3626.1895.g7001d56-darwin64-525361.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60900/572290/dullahan-1.7.0.202005311125_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-543086.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -592,9 +592,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>71fa66203326aca918796e874976c080</string>
<string>aa4faf9ef9057362d63f8d57092506b3</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34070/283477/dullahan-1.1.1320_3.3626.1895.g7001d56-windows-525361.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60902/572301/dullahan-1.7.0.202005311828_81.3.10_gb223419_chromium-81.0.4044.138-windows-543086.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -604,16 +604,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>c7162e4805f50a3609f5dc63d0cf2bc0</string>
<string>6e29ea2ccdad80dcf1b5dc974932c1f6</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/34071/283480/dullahan-1.1.1320_3.3626.1895.g7001d56-windows64-525361.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60901/572302/dullahan-1.7.0.202005311828_81.3.10_gb223419_chromium-81.0.4044.138-windows64-543086.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>1.1.1320_3.3626.1895.g7001d56</string>
<string>1.7.0.202005311828_81.3.10_gb223419_chromium-81.0.4044.138</string>
</map>
<key>elfio</key>
<map>

View File

@ -73,7 +73,6 @@ set(llcommon_SOURCE_FILES
llinitparam.cpp
llinitdestroyclass.cpp
llinstancetracker.cpp
llkeybind.cpp
llleap.cpp
llleaplistener.cpp
llliveappconfig.cpp
@ -184,7 +183,6 @@ set(llcommon_HEADER_FILES
llinitdestroyclass.h
llinitparam.h
llinstancetracker.h
llkeybind.h
llkeythrottle.h
llleap.h
llleaplistener.h

View File

@ -54,17 +54,6 @@ enum ETerrainBrushType
E_LANDBRUSH_INVALID = 6
};
enum EMouseClickType{
CLICK_NONE = -1,
CLICK_LEFT = 0,
CLICK_MIDDLE,
CLICK_RIGHT,
CLICK_BUTTON4,
CLICK_BUTTON5,
CLICK_DOUBLELEFT,
CLICK_COUNT // 'size', CLICK_NONE does not counts
};
// keys
// Bit masks for various keyboard modifier keys.
const MASK MASK_NONE = 0x0000;

View File

@ -1,395 +0,0 @@
/**
* @file llkeybind.cpp
* @brief Information about key combinations.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, 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 "llkeybind.h"
#include "llsd.h"
#include "llsdutil.h"
LLKeyData::LLKeyData()
:
mMouse(CLICK_NONE),
mKey(KEY_NONE),
mMask(MASK_NONE),
mIgnoreMasks(false)
{
}
LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask)
:
mMouse(mouse),
mKey(key),
mMask(mask),
mIgnoreMasks(false)
{
}
LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask)
:
mMouse(mouse),
mKey(key),
mMask(MASK_NONE),
mIgnoreMasks(ignore_mask)
{
}
LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
:
mMouse(mouse),
mKey(key),
mMask(mask),
mIgnoreMasks(ignore_mask)
{
}
LLKeyData::LLKeyData(const LLSD &key_data)
{
if (key_data.has("mouse"))
{
mMouse = (EMouseClickType)key_data["mouse"].asInteger();
}
if (key_data.has("key"))
{
mKey = key_data["key"].asInteger();
}
if (key_data.has("ignore_accelerators"))
{
mIgnoreMasks = key_data["ignore_accelerators"];
}
if (key_data.has("mask"))
{
mMask = key_data["mask"].asInteger();
}
}
LLSD LLKeyData::asLLSD() const
{
LLSD data;
data["mouse"] = (LLSD::Integer)mMouse;
data["key"] = (LLSD::Integer)mKey;
data["mask"] = (LLSD::Integer)mMask;
if (mIgnoreMasks)
{
data["ignore_accelerators"] = (LLSD::Boolean)mIgnoreMasks;
}
return data;
}
bool LLKeyData::isEmpty() const
{
return mMouse == CLICK_NONE && mKey == KEY_NONE;
}
void LLKeyData::reset()
{
mMouse = CLICK_NONE;
mKey = KEY_NONE;
mMask = MASK_NONE;
mIgnoreMasks = false;
}
LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
{
mMouse = rhs.mMouse;
mKey = rhs.mKey;
mMask = rhs.mMask;
mIgnoreMasks = rhs.mIgnoreMasks;
return *this;
}
bool LLKeyData::operator==(const LLKeyData& rhs)
{
if (mMouse != rhs.mMouse) return false;
if (mKey != rhs.mKey) return false;
if (mMask != rhs.mMask) return false;
if (mIgnoreMasks != rhs.mIgnoreMasks) return false;
return true;
}
bool LLKeyData::operator!=(const LLKeyData& rhs)
{
if (mMouse != rhs.mMouse) return true;
if (mKey != rhs.mKey) return true;
if (mMask != rhs.mMask) return true;
if (mIgnoreMasks != rhs.mIgnoreMasks) return true;
return false;
}
bool LLKeyData::canHandle(const LLKeyData& data) const
{
if (data.mKey == mKey
&& data.mMouse == mMouse
&& ((mIgnoreMasks && (data.mMask & mMask) == mMask) || data.mMask == mMask))
{
return true;
}
return false;
}
bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
{
if (mouse == mMouse
&& key == mKey
&& ((mIgnoreMasks && (mask & mMask) == mMask) || mask == mMask))
{
return true;
}
return false;
}
// LLKeyBind
LLKeyBind::LLKeyBind(const LLSD &key_bind)
{
if (key_bind.isArray())
{
for (LLSD::array_const_iterator data = key_bind.beginArray(), endLists = key_bind.endArray();
data != endLists;
data++
)
{
mData.push_back(LLKeyData(*data));
}
}
}
bool LLKeyBind::operator==(const LLKeyBind& rhs)
{
U32 size = mData.size();
if (size != rhs.mData.size()) return false;
for (U32 i = 0; i < size; i++)
{
if (mData[i] != rhs.mData[i]) return false;
}
return true;
}
bool LLKeyBind::operator!=(const LLKeyBind& rhs)
{
U32 size = mData.size();
if (size != rhs.mData.size()) return true;
for (U32 i = 0; i < size; i++)
{
if (mData[i] != rhs.mData[i]) return true;
}
return false;
}
bool LLKeyBind::isEmpty() const
{
for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (!iter->isEmpty()) return false;
}
return true;
}
LLSD LLKeyBind::asLLSD() const
{
S32 last = mData.size() - 1;
while (mData[last].empty())
{
last--;
}
LLSD data;
for (S32 i = 0; i <= last; ++i)
{
// append even if empty to not affect visual representation
data.append(mData[i].asLLSD());
}
return data;
}
bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
{
if (mouse == CLICK_NONE && key == KEY_NONE)
{
// assume placeholder
return false;
}
for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (iter->canHandle(mouse, key, mask))
{
return true;
}
}
return false;
}
bool LLKeyBind::canHandleKey(KEY key, MASK mask) const
{
return canHandle(CLICK_NONE, key, mask);
}
bool LLKeyBind::canHandleMouse(EMouseClickType mouse, MASK mask) const
{
return canHandle(mouse, KEY_NONE, mask);
}
bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
{
if (mouse != CLICK_NONE || key != KEY_NONE)
{
for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (iter->mKey == key
&& iter->mMask == mask
&& iter->mMouse == mouse
&& iter->mIgnoreMasks == ignore)
{
return true;
}
}
}
return false;
}
bool LLKeyBind::hasKeyData(const LLKeyData& data) const
{
return hasKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
}
bool LLKeyBind::hasKeyData(U32 index) const
{
return mData.size() > index;
}
S32 LLKeyBind::findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
{
if (mouse != CLICK_NONE || key != KEY_NONE)
{
for (S32 i = 0; i < mData.size(); ++i)
{
if (mData[i].mKey == key
&& mData[i].mMask == mask
&& mData[i].mMouse == mouse
&& mData[i].mIgnoreMasks == ignore)
{
return i;
}
}
}
return -1;
}
S32 LLKeyBind::findKeyData(const LLKeyData& data) const
{
return findKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
}
LLKeyData LLKeyBind::getKeyData(U32 index) const
{
if (mData.size() > index)
{
return mData[index];
}
return LLKeyData();
}
bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore)
{
if (!hasKeyData(mouse, key, mask, ignore))
{
mData.push_back(LLKeyData(mouse, key, mask, ignore));
return true;
}
return false;
}
bool LLKeyBind::addKeyData(const LLKeyData& data)
{
if (!hasKeyData(data))
{
mData.push_back(data);
return true;
}
return false;
}
void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index)
{
replaceKeyData(LLKeyData(mouse, key, mask, ignore), index);
}
void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
{
if (!data.isEmpty())
{
// if both click and key are none (isEmpty()), we are inserting a placeholder, we don't want to reset anything
// otherwise reset identical key
for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (iter->mKey == data.mKey
&& iter->mMouse == data.mMouse
&& iter->mIgnoreMasks == data.mIgnoreMasks
&& iter->mMask == data.mMask)
{
// Replacing only fully equal combinations even in case 'ignore' is set
// Reason: Simplicity and user might decide to do a 'move' command as W and Shift+Ctrl+W, and 'run' as Shift+W
iter->reset();
break;
}
}
}
if (mData.size() <= index)
{
mData.resize(index + 1);
}
mData[index] = data;
}
void LLKeyBind::resetKeyData(S32 index)
{
if (mData.size() > index)
{
mData[index].reset();
}
}
void LLKeyBind::trimEmpty()
{
S32 last = mData.size() - 1;
while (last >= 0 && mData[last].empty())
{
mData.erase(mData.begin() + last);
last--;
}
}
U32 LLKeyBind::getDataCount()
{
return mData.size();
}

View File

@ -1,106 +0,0 @@
/**
* @file llkeybind.h
* @brief Information about key combinations.
*
* $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_KEYBIND_H
#define LL_KEYBIND_H
#include "indra_constants.h"
// KeyData - single key combination (mouse/mask/keyboard)
class LL_COMMON_API LLKeyData
{
public:
LLKeyData();
LLKeyData(EMouseClickType mouse, KEY key, MASK mask);
LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask);
LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask);
LLKeyData(const LLSD &key_data);
LLSD asLLSD() const;
bool isEmpty() const;
bool empty() const { return isEmpty(); };
void reset();
LLKeyData& operator=(const LLKeyData& rhs);
bool operator==(const LLKeyData& rhs);
bool operator!=(const LLKeyData& rhs);
bool canHandle(const LLKeyData& data) const;
bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
EMouseClickType mMouse;
KEY mKey;
MASK mMask;
// Either to expect exact match or to make sure mMask is inclused and ignore not expected masks
bool mIgnoreMasks;
};
// One function can bind to multiple Key options
class LLKeyBind
{
public:
LLKeyBind() {}
LLKeyBind(const LLSD &key_bind);
bool operator==(const LLKeyBind& rhs);
bool operator!=(const LLKeyBind& rhs);
bool isEmpty() const;
bool empty() const { return isEmpty(); };
LLSD asLLSD() const;
bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
bool canHandleKey(KEY key, MASK mask) const;
bool canHandleMouse(EMouseClickType mouse, MASK mask) const;
// contains specified combination
bool hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
bool hasKeyData(const LLKeyData& data) const;
bool hasKeyData(U32 index) const;
// index of contained LLKeyData
S32 findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
S32 findKeyData(const LLKeyData& data) const;
LLKeyData getKeyData(U32 index) const;
// these methods enshure there will be no repeats
bool addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore);
bool addKeyData(const LLKeyData& data);
void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index);
void replaceKeyData(const LLKeyData& data, U32 index);
void resetKeyData(S32 index);
void clear() { mData.clear(); }
// if there any empty LLKeyData in the end of the array, remove them
void trimEmpty();
U32 getDataCount();
private:
typedef std::vector<LLKeyData> data_vector_t;
data_vector_t mData;
};
#endif // LL_KEYBIND_H

View File

@ -1138,6 +1138,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
mDebugMessageLevel = message.getValue("message_level");
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE);
}
else if (message_name == "tooltip_text")
{
mHoverText = message.getValue("tooltip");
}
else
{
LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;

View File

@ -212,12 +212,6 @@ LLSD LLMenuItemGL::getValue() const
return getLabel();
}
//virtual
bool LLMenuItemGL::hasAccelerator(const KEY &key, const MASK &mask) const
{
return (mAcceleratorKey == key) && (mAcceleratorMask == mask);
}
//virtual
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{
@ -269,13 +263,13 @@ BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp)
BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
{
LLMenuKeyboardBinding *accelerator = NULL;
LLKeyBinding *accelerator = NULL;
if (mAcceleratorKey != KEY_NONE)
{
std::list<LLMenuKeyboardBinding*>::iterator list_it;
std::list<LLKeyBinding*>::iterator list_it;
for (list_it = listp->begin(); list_it != listp->end(); ++list_it)
{
accelerator = *list_it;
@ -299,7 +293,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *list
}
if (!accelerator)
{
accelerator = new LLMenuKeyboardBinding;
accelerator = new LLKeyBinding;
if (accelerator)
{
accelerator->mKey = mAcceleratorKey;
@ -1023,11 +1017,6 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask)
return TRUE;
}
bool LLMenuItemBranchGL::hasAccelerator(const KEY &key, const MASK &mask) const
{
return getBranch() && getBranch()->hasAccelerator(key, mask);
}
BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
{
return getBranch() && getBranch()->handleAcceleratorKey(key, mask);
@ -1035,7 +1024,7 @@ BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp)
BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLKeyBinding*> *listp)
{
LLMenuGL* branch = getBranch();
if (!branch)
@ -3034,27 +3023,6 @@ void LLMenuGL::updateParent(LLView* parentp)
}
}
bool LLMenuGL::hasAccelerator(const KEY &key, const MASK &mask) const
{
if (key == KEY_NONE)
{
return false;
}
// Note: checking this way because mAccelerators seems to be broken
// mAccelerators probably needs to be cleaned up or fixed
// It was used for dupplicate accelerator avoidance.
item_list_t::const_iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
{
LLMenuItemGL* itemp = *item_iter;
if (itemp->hasAccelerator(key, mask))
{
return true;
}
}
return false;
}
BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask)
{
// don't handle if not enabled

View File

@ -42,13 +42,6 @@
extern S32 MENU_BAR_HEIGHT;
extern S32 MENU_BAR_WIDTH;
class LLMenuKeyboardBinding
{
public:
KEY mKey;
MASK mMask;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemGL
//
@ -98,7 +91,6 @@ public:
/*virtual*/ void setValue(const LLSD& value);
/*virtual*/ LLSD getValue() const;
virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); }
@ -117,7 +109,7 @@ public:
virtual void setBriefItem(BOOL brief);
virtual BOOL isBriefItem() const;
virtual BOOL addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp);
virtual BOOL addToAcceleratorList(std::list<LLKeyBinding*> *listp);
void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }
BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; }
@ -444,8 +436,7 @@ public:
/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
/*virtual*/ void removeChild( LLView* ctrl);
/*virtual*/ BOOL postBuild();
virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const;
@ -637,11 +628,10 @@ public:
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
// check if we've used these accelerators already
virtual BOOL addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp);
virtual BOOL addToAcceleratorList(std::list <LLKeyBinding*> *listp);
// called to rebuild the draw label
virtual void buildDrawLabel( void );
@ -807,7 +797,7 @@ private:
void checkMenuTrigger();
std::list <LLMenuKeyboardBinding*> mAccelerators;
std::list <LLKeyBinding*> mAccelerators;
BOOL mAltKeyTrigger;
};

View File

@ -50,10 +50,6 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_
{
cell = new LLScrollListDate(cell_p);
}
else if (cell_p.type() == "icontext")
{
cell = new LLScrollListIconText(cell_p);
}
else // default is "text"
{
cell = new LLScrollListText(cell_p);
@ -172,7 +168,7 @@ U32 LLScrollListText::sCount = 0;
LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
: LLScrollListCell(p),
mText(p.label.isProvided() ? p.label() : p.value().asString()),
mText(p.value().asString()),
mFont(p.font),
mColor(p.color),
mUseColor(p.color.isProvided()),
@ -196,7 +192,7 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
void LLScrollListText::highlightText(S32 offset, S32 num_chars)
{
mHighlightOffset = offset;
mHighlightCount = llmax(0, num_chars);
mHighlightCount = num_chars;
}
//virtual
@ -296,12 +292,11 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
if (mHighlightCount > 0)
{
// Highlight text
S32 left = 0;
switch(mFontAlignment)
{
case LLFontGL::LEFT:
left = mFont->getWidth(mText.getString(), 1, mHighlightOffset);
left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
break;
case LLFontGL::RIGHT:
left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
@ -324,7 +319,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
switch(mFontAlignment)
{
case LLFontGL::LEFT:
start_x = 1.f;
start_x = 0.f;
break;
case LLFontGL::RIGHT:
start_x = (F32)getWidth();
@ -440,139 +435,3 @@ const LLSD LLScrollListDate::getValue() const
{
return mDate;
}
//
// LLScrollListIconText
//
LLScrollListIconText::LLScrollListIconText(const LLScrollListCell::Params& p)
: LLScrollListText(p),
mIcon(p.value().isUUID() ? LLUI::getUIImageByID(p.value().asUUID()) : LLUI::getUIImage(p.value().asString())),
mPad(4)
{
mTextWidth = getWidth() - mPad /*padding*/ - mFont->getLineHeight();
}
LLScrollListIconText::~LLScrollListIconText()
{
}
const LLSD LLScrollListIconText::getValue() const
{
if (mIcon.isNull())
{
return LLStringUtil::null;
}
return mIcon->getName();
}
void LLScrollListIconText::setValue(const LLSD& value)
{
if (value.isUUID())
{
// don't use default image specified by LLUUID::null, use no image in that case
LLUUID image_id = value.asUUID();
mIcon = image_id.notNull() ? LLUI::getUIImageByID(image_id) : LLUIImagePtr(NULL);
}
else
{
std::string value_string = value.asString();
if (LLUUID::validate(value_string))
{
setValue(LLUUID(value_string));
}
else if (!value_string.empty())
{
mIcon = LLUI::getUIImage(value.asString());
}
else
{
mIcon = NULL;
}
}
}
void LLScrollListIconText::setWidth(S32 width)
{
LLScrollListCell::setWidth(width);
// Assume that iamge height and width is identical to font height and width
mTextWidth = width - mPad /*padding*/ - mFont->getLineHeight();
}
void LLScrollListIconText::draw(const LLColor4& color, const LLColor4& highlight_color) const
{
LLColor4 display_color;
if (mUseColor)
{
display_color = mColor;
}
else
{
display_color = color;
}
S32 icon_height = mFont->getLineHeight();
S32 icon_space = mIcon ? (icon_height + mPad) : 0;
if (mHighlightCount > 0)
{
S32 left = 0;
switch (mFontAlignment)
{
case LLFontGL::LEFT:
left = mFont->getWidth(mText.getString(), icon_space + 1, mHighlightOffset);
break;
case LLFontGL::RIGHT:
left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX) - icon_space;
break;
case LLFontGL::HCENTER:
left = (getWidth() - mFont->getWidth(mText.getString()) - icon_space) / 2;
break;
}
LLRect highlight_rect(left - 2,
mFont->getLineHeight() + 1,
left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
1);
mRoundedRectImage->draw(highlight_rect, highlight_color);
}
// Try to draw the entire string
F32 right_x;
U32 string_chars = mText.length();
F32 start_text_x = 0.f;
S32 start_icon_x = 0;
switch (mFontAlignment)
{
case LLFontGL::LEFT:
start_text_x = icon_space + 1;
start_icon_x = 1;
break;
case LLFontGL::RIGHT:
start_text_x = (F32)getWidth();
start_icon_x = getWidth() - mFont->getWidth(mText.getString()) - icon_space;
break;
case LLFontGL::HCENTER:
F32 center = (F32)getWidth()* 0.5f;
start_text_x = center + ((F32)icon_space * 0.5f);
start_icon_x = center - (((F32)icon_space + mFont->getWidth(mText.getString())) * 0.5f);
break;
}
mFont->render(mText.getWString(), 0,
start_text_x, 0.f,
display_color,
mFontAlignment,
LLFontGL::BOTTOM,
0,
LLFontGL::NO_SHADOW,
string_chars,
getTextWidth(),
&right_x,
TRUE);
if (mIcon)
{
mIcon->draw(start_icon_x, 0, icon_height, icon_height, mColor);
}
}

View File

@ -59,8 +59,7 @@ public:
visible;
Optional<void*> userdata;
Optional<LLSD> value; // state of checkbox, icon id/name, date
Optional<std::string> label; // description or text
Optional<LLSD> value;
Optional<std::string> tool_tip;
Optional<const LLFontGL*> font;
@ -76,7 +75,6 @@ public:
enabled("enabled", true),
visible("visible", true),
value("value"),
label("label"),
tool_tip("tool_tip", ""),
font("font", LLFontGL::getFontSansSerifSmall()),
font_color("font_color", LLColor4::black),
@ -154,12 +152,11 @@ public:
void setText(const LLStringExplicit& text);
void setFontStyle(const U8 font_style);
protected:
private:
LLUIString mText;
S32 mTextWidth;
const LLFontGL* mFont;
LLColor4 mColor;
LLColor4 mHighlightColor;
U8 mUseColor;
LLFontGL::HAlign mFontAlignment;
BOOL mVisible;
@ -172,7 +169,7 @@ protected:
};
/*
* Cell displaying an image. AT the moment, this is specifically UI image
* Cell displaying an image.
*/
class LLScrollListIcon : public LLScrollListCell
{
@ -226,26 +223,4 @@ private:
LLDate mDate;
};
/*
* Cell displaying icon and text.
*/
class LLScrollListIconText : public LLScrollListText
{
public:
LLScrollListIconText(const LLScrollListCell::Params& p);
/*virtual*/ ~LLScrollListIconText();
/*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
/*virtual*/ const LLSD getValue() const;
/*virtual*/ void setValue(const LLSD& value);
S32 getIconWidth() const;
/*virtual*/ void setWidth(S32 width);/* { LLScrollListCell::setWidth(width); mTextWidth = width - ; }*/
private:
LLPointer<LLUIImage> mIcon;
S32 mPad;
};
#endif

View File

@ -115,13 +115,6 @@ struct SortScrollListItem
// LLScrollListCtrl
//---------------------------------------------------------------------------
void LLScrollListCtrl::SelectionTypeNames::declareValues()
{
declare("row", LLScrollListCtrl::ROW);
declare("cell", LLScrollListCtrl::CELL);
declare("header", LLScrollListCtrl::HEADER);
}
LLScrollListCtrl::Contents::Contents()
: columns("column"),
rows("row")
@ -135,10 +128,8 @@ LLScrollListCtrl::Params::Params()
has_border("draw_border"),
draw_heading("draw_heading"),
search_column("search_column", 0),
selection_type("selection_type", ROW),
sort_column("sort_column", -1),
sort_ascending("sort_ascending", true),
can_sort("can_sort", true),
mouse_wheel_opaque("mouse_wheel_opaque", false),
commit_on_keyboard_movement("commit_on_keyboard_movement", true),
heading_height("heading_height"),
@ -173,10 +164,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
mCommitOnSelectionChange(false),
mSelectionChanged(false),
mSelectionType(p.selection_type),
mNeedsScroll(false),
mCanSelect(true),
mCanSort(p.can_sort),
mColumnsDirty(false),
mMaxItemCount(INT_MAX),
mBorderThickness( 2 ),
@ -830,15 +819,7 @@ BOOL LLScrollListCtrl::selectFirstItem()
{
if (!itemp->getSelected())
{
switch (mSelectionType)
{
case CELL:
selectItem(itemp, 0);
break;
case HEADER:
case ROW:
selectItem(itemp, -1);
}
selectItem(itemp);
}
success = TRUE;
mOriginalSelection = 0;
@ -897,8 +878,7 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )
{
if( itemp->getEnabled() )
{
// TODO: support range selection for cells
selectItem(itemp, -1, FALSE);
selectItem(itemp, FALSE);
success = TRUE;
}
}
@ -1024,14 +1004,10 @@ void LLScrollListCtrl::clearHighlightedItems()
void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index)
{
if (mHighlightedItem != target_index)
{
if (mHighlightedItem >= 0 && mHighlightedItem < mItemList.size())
{
mItemList[mHighlightedItem]->setHoverCell(-1);
}
mHighlightedItem = target_index;
}
if (mHighlightedItem != target_index)
{
mHighlightedItem = target_index;
}
}
S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
@ -1046,8 +1022,7 @@ S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
{
if (item->getEnabled() && (item->getUUID() == (*iditr)))
{
// TODO: support multiple selection for cells
selectItem(item, -1, FALSE);
selectItem(item,FALSE);
++count;
break;
}
@ -1120,7 +1095,7 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
{
if (prev_item)
{
selectItem(prev_item, cur_item->getSelectedCell(), !extend_selection);
selectItem(prev_item, !extend_selection);
}
else
{
@ -1164,7 +1139,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
{
if (next_item)
{
selectItem(next_item, cur_item->getSelectedCell(), !extend_selection);
selectItem(next_item, !extend_selection);
}
else
{
@ -1235,7 +1210,7 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen
bool found = NULL != item;
if(found)
{
selectItem(item, -1);
selectItem(item);
}
if (mCommitOnSelectionChange)
@ -1303,7 +1278,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
if (select)
{
selectItem(item, -1);
selectItem(item);
found = TRUE;
break;
}
@ -1343,7 +1318,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
// find offset of matching text (might have leading whitespace)
S32 offset = item_label.find(target_trimmed);
cellp->highlightText(offset, target_trimmed.size());
selectItem(item, -1);
selectItem(item);
found = TRUE;
break;
}
@ -1409,7 +1384,7 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)
{
if (selected)
{
selectItem(item, -1);
selectItem(item);
}
else
{
@ -1489,7 +1464,7 @@ void LLScrollListCtrl::drawItems()
S32 max_columns = 0;
LLColor4 highlight_color = LLColor4::white; // ex: text inside cells
LLColor4 highlight_color = LLColor4::white;
static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0);
highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout(), 0.4f, 0.f);
@ -1515,8 +1490,7 @@ void LLScrollListCtrl::drawItems()
max_columns = llmax(max_columns, item->getNumColumns());
LLColor4 fg_color;
LLColor4 hover_color(LLColor4::transparent);
LLColor4 select_color(LLColor4::transparent);
LLColor4 bg_color(LLColor4::transparent);
if( mScrollLines <= line && line < mScrollLines + num_page_lines )
{
@ -1525,44 +1499,44 @@ void LLScrollListCtrl::drawItems()
{
if(item->getHighlighted()) // if it's highlighted, average the colors
{
select_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
bg_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
}
else // otherwise just select-highlight it
{
select_color = mBgSelectedColor.get();
bg_color = mBgSelectedColor.get();
}
fg_color = (item->getEnabled() ? mFgSelectedColor.get() : mFgDisabledColor.get());
}
if (mHighlightedItem == line && mCanSelect)
else if (mHighlightedItem == line && mCanSelect)
{
if(item->getHighlighted()) // if it's highlighted, average the colors
{
hover_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
bg_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
}
else // otherwise just hover-highlight it
{
hover_color = mHoveredColor.get();
bg_color = mHoveredColor.get();
}
}
else if (item->getHighlighted())
{
hover_color = mHighlightedColor.get();
bg_color = mHighlightedColor.get();
}
else
{
if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))
{
hover_color = mBgStripeColor.get();
bg_color = mBgStripeColor.get();
}
}
if (!item->getEnabled())
{
hover_color = mBgReadOnlyColor.get();
bg_color = mBgReadOnlyColor.get();
}
item->draw(item_rect, fg_color % alpha, hover_color% alpha, select_color% alpha, highlight_color % alpha, mColumnPadding);
item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding);
cur_y -= mLineHeight;
}
@ -1714,7 +1688,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if (mLastSelected == NULL)
{
selectItem(hit_item, getColumnIndexFromOffset(x));
selectItem(hit_item);
}
else
{
@ -1738,7 +1712,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
LLScrollListItem *item = *itor;
if (item == hit_item || item == lastSelected)
{
selectItem(item, getColumnIndexFromOffset(x), FALSE);
selectItem(item, FALSE);
selecting = !selecting;
if (hit_item == lastSelected)
{
@ -1748,7 +1722,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
}
if (selecting)
{
selectItem(item, getColumnIndexFromOffset(x), FALSE);
selectItem(item, FALSE);
}
}
}
@ -1763,7 +1737,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable))
{
selectItem(hit_item, getColumnIndexFromOffset(x), FALSE);
selectItem(hit_item, FALSE);
}
else
{
@ -1777,12 +1751,12 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
else
{
deselectAllItems(TRUE);
selectItem(hit_item, getColumnIndexFromOffset(x));
selectItem(hit_item);
}
}
else
{
selectItem(hit_item, getColumnIndexFromOffset(x));
selectItem(hit_item);
}
selection_changed = mSelectionChanged;
@ -2150,29 +2124,8 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
{
LLScrollListItem* item = hitItem(x, y);
if (item)
{
mouseOverHighlightNthItem(getItemIndex(item));
switch (mSelectionType)
{
case CELL:
item->setHoverCell(getColumnIndexFromOffset(x));
break;
case HEADER:
{
S32 cell = getColumnIndexFromOffset(x);
if (cell > 0)
{
item->setHoverCell(cell);
}
else
{
item->setHoverCell(-1);
}
break;
}
case ROW:
break;
}
{
mouseOverHighlightNthItem(getItemIndex(item));
}
else
{
@ -2220,52 +2173,6 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask )
handled = TRUE;
}
break;
case KEY_LEFT:
if (mAllowKeyboardMovement || hasFocus())
{
// TODO: support multi-select
LLScrollListItem *item = getFirstSelected();
S32 cell = item->getSelectedCell();
switch (mSelectionType)
{
case CELL:
if (cell < mColumns.size()) cell++;
break;
case HEADER:
if (cell == -1) cell = 1;
else if (cell > 1 && cell < mColumns.size()) cell++; // skip header
break;
case ROW:
cell = -1;
break;
}
item->setSelectedCell(cell);
handled = TRUE;
}
break;
case KEY_RIGHT:
if (mAllowKeyboardMovement || hasFocus())
{
// TODO: support multi-select
LLScrollListItem *item = getFirstSelected();
S32 cell = item->getSelectedCell();
switch (mSelectionType)
{
case CELL:
if (cell >= 0) cell--;
break;
case HEADER:
if (cell > 1) cell--;
else if (cell == 1) cell = -1; // skip header
break;
case ROW:
cell = -1;
break;
}
item->setSelectedCell(cell);
handled = TRUE;
}
break;
case KEY_PAGE_UP:
if (mAllowKeyboardMovement || hasFocus())
{
@ -2434,7 +2341,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char)
LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
{
selectItem(item, -1);
selectItem(item);
mNeedsScroll = true;
cellp->highlightText(0, 1);
mSearchTimer.reset();
@ -2486,7 +2393,7 @@ BOOL LLScrollListCtrl::isRepeatedChars(const LLWString& string) const
return TRUE;
}
void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, S32 cell, BOOL select_single_item)
void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_item)
{
if (!itemp) return;
@ -2505,18 +2412,6 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, S32 cell, BOOL select
deselectAllItems(TRUE);
}
itemp->setSelected(TRUE);
switch (mSelectionType)
{
case CELL:
itemp->setSelectedCell(cell);
break;
case HEADER:
itemp->setSelectedCell(cell <= 0 ? -1 : cell);
break;
case ROW:
itemp->setSelectedCell(-1);
break;
}
mLastSelected = itemp;
mSelectionChanged = true;
}
@ -2777,7 +2672,7 @@ void LLScrollListCtrl::selectAll()
LLScrollListItem *itemp = *iter;
if( itemp->getEnabled() )
{
selectItem(itemp, -1, FALSE);
selectItem(itemp, FALSE);
}
}
@ -2906,8 +2801,6 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
LLScrollListCtrl *parent = info->mParentCtrl;
if (!parent) return;
if (!parent->mCanSort) return;
S32 column_index = info->mIndex;
LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];

View File

@ -54,18 +54,6 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
public LLCtrlListInterface, public LLCtrlScrollInterface
{
public:
typedef enum e_selection_type
{
ROW, // default
CELL, // does not support multi-selection
HEADER, // when pointing to cells in column 0 will highlight whole row, otherwise cell, no multi-select
} ESelectionType;
struct SelectionTypeNames : public LLInitParam::TypeValuesHelper<LLScrollListCtrl::ESelectionType, SelectionTypeNames>
{
static void declareValues();
};
struct Contents : public LLInitParam::Block<Contents>
{
Multiple<LLScrollListColumn::Params> columns;
@ -111,8 +99,6 @@ public:
commit_on_keyboard_movement,
mouse_wheel_opaque;
Optional<ESelectionType, SelectionTypeNames> selection_type;
// display flags
Optional<bool> has_border,
draw_heading,
@ -129,8 +115,7 @@ public:
// sort and search behavior
Optional<S32> search_column,
sort_column;
Optional<bool> sort_ascending,
can_sort; // whether user is allowed to sort
Optional<bool> sort_ascending;
// colors
Optional<LLUIColor> fg_unselected_color,
@ -447,7 +432,7 @@ private:
void updateLineHeightInsert(LLScrollListItem* item);
void reportInvalidInput();
BOOL isRepeatedChars(const LLWString& string) const;
void selectItem(LLScrollListItem* itemp, S32 cell, BOOL single_select = TRUE);
void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
BOOL setSort(S32 column, BOOL ascending);
@ -472,11 +457,9 @@ private:
bool mCommitOnKeyboardMovement;
bool mCommitOnSelectionChange;
bool mSelectionChanged;
ESelectionType mSelectionType;
bool mNeedsScroll;
bool mMouseWheelOpaque;
bool mCanSelect;
bool mCanSort; // Whether user is allowed to sort
bool mDisplayColumnHeaders;
bool mColumnsDirty;
bool mColumnWidthsDirty;

View File

@ -40,8 +40,6 @@
LLScrollListItem::LLScrollListItem( const Params& p )
: mSelected(FALSE),
mHighlighted(FALSE),
mHoverIndex(-1),
mSelectedIndex(-1),
mEnabled(p.enabled),
mUserdata(p.userdata),
mItemValue(p.value)
@ -55,28 +53,6 @@ LLScrollListItem::~LLScrollListItem()
mColumns.clear();
}
void LLScrollListItem::setSelected(BOOL b)
{
mSelected = b;
mSelectedIndex = -1;
}
void LLScrollListItem::setHighlighted(BOOL b)
{
mHighlighted = b;
mHoverIndex = -1;
}
void LLScrollListItem::setHoverCell(S32 cell)
{
mHoverIndex = cell;
}
void LLScrollListItem::setSelectedCell(S32 cell)
{
mSelectedIndex = cell;
}
void LLScrollListItem::addColumn(const LLScrollListCell::Params& p)
{
mColumns.push_back(LLScrollListCell::create(p));
@ -144,21 +120,12 @@ std::string LLScrollListItem::getContentsCSV() const
}
void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& hover_color, const LLColor4& select_color, const LLColor4& highlight_color, S32 column_padding)
void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
{
// draw background rect
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLRect bg_rect = rect;
if (mSelectedIndex < 0 && getSelected())
{
// Whole item is highlighted/selected
gl_rect_2d(bg_rect, select_color);
}
else if (mHoverIndex < 0)
{
// Whole item is highlighted/selected
gl_rect_2d(bg_rect, hover_color);
}
gl_rect_2d( bg_rect, bg_color );
S32 cur_x = rect.mLeft;
S32 num_cols = getNumColumns();
@ -174,25 +141,6 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const
{
LLUI::translate((F32) cur_x, (F32) rect.mBottom);
if (mSelectedIndex == cur_col)
{
// select specific cell
LLRect highlight_rect(0,
cell->getHeight(),
cell->getWidth(),
0);
gl_rect_2d(highlight_rect, select_color);
}
else if (mHoverIndex == cur_col)
{
// highlight specific cell
LLRect highlight_rect(0,
cell->getHeight(),
cell->getWidth() ,
0);
gl_rect_2d(highlight_rect, hover_color);
}
cell->draw( fg_color, highlight_color );
}
LLUI::popMatrix();

View File

@ -77,21 +77,15 @@ public:
virtual ~LLScrollListItem();
void setSelected( BOOL b );
void setSelected( BOOL b ) { mSelected = b; }
BOOL getSelected() const { return mSelected; }
void setEnabled( BOOL b ) { mEnabled = b; }
BOOL getEnabled() const { return mEnabled; }
void setHighlighted( BOOL b );
void setHighlighted( BOOL b ) { mHighlighted = b; }
BOOL getHighlighted() const { return mHighlighted; }
void setSelectedCell( S32 cell );
S32 getSelectedCell() const { return mSelectedIndex; }
void setHoverCell( S32 cell );
S32 getHoverCell() const { return mHoverIndex; }
void setUserdata( void* userdata ) { mUserdata = userdata; }
void* getUserdata() const { return mUserdata; }
@ -113,21 +107,14 @@ public:
std::string getContentsCSV() const;
virtual void draw(const LLRect& rect,
const LLColor4& fg_color,
const LLColor4& hover_color, // highlight/hover selection of whole item or cell
const LLColor4& select_color, // highlight/hover selection of whole item or cell
const LLColor4& highlight_color, // highlights contents of cells (ex: text)
S32 column_padding);
virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
protected:
LLScrollListItem( const Params& );
private:
BOOL mSelected;
BOOL mHighlighted;
S32 mHoverIndex;
S32 mSelectedIndex;
BOOL mHighlighted;
BOOL mEnabled;
void* mUserdata;
LLSD mItemValue;

View File

@ -327,7 +327,7 @@ BOOL LLKeyboard::keyFromString(const std::string& str, KEY *key)
// static
std::string LLKeyboard::stringFromKey(KEY key, bool translate)
std::string LLKeyboard::stringFromKey(KEY key)
{
std::string res = get_if_there(sKeysToNames, key, std::string());
if (res.empty())
@ -338,60 +338,16 @@ std::string LLKeyboard::stringFromKey(KEY key, bool translate)
res = std::string(buffer);
}
if (translate)
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
res = trans(res.c_str());
}
res = trans(res.c_str());
}
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator(MASK accel_mask)
{
std::string res;
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans == NULL)
{
LL_ERRS() << "No mKeyStringTranslator" << LL_ENDL;
return res;
}
// Append any masks
#ifdef LL_DARWIN
// Standard Mac names for modifier keys in menu equivalents
// We could use the symbol characters, but they only exist in certain fonts.
if (accel_mask & MASK_CONTROL)
{
if (accel_mask & MASK_MAC_CONTROL)
{
res.append(trans("accel-mac-control"));
}
else
{
res.append(trans("accel-mac-command")); // Symbol would be "\xE2\x8C\x98"
}
}
if (accel_mask & MASK_ALT)
res.append(trans("accel-mac-option")); // Symbol would be "\xE2\x8C\xA5"
if (accel_mask & MASK_SHIFT)
res.append(trans("accel-mac-shift")); // Symbol would be "\xE2\x8C\xA7"
#else
if (accel_mask & MASK_CONTROL)
res.append(trans("accel-win-control"));
if (accel_mask & MASK_ALT)
res.append(trans("accel-win-alt"));
if (accel_mask & MASK_SHIFT)
res.append(trans("accel-win-shift"));
#endif
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
{
@ -403,7 +359,41 @@ std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
return res;
}
res.append(stringFromAccelerator(accel_mask));
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if( trans == NULL )
{
LL_ERRS() << "No mKeyStringTranslator" << LL_ENDL;
return res;
}
// Append any masks
#ifdef LL_DARWIN
// Standard Mac names for modifier keys in menu equivalents
// We could use the symbol characters, but they only exist in certain fonts.
if( accel_mask & MASK_CONTROL )
{
if ( accel_mask & MASK_MAC_CONTROL )
{
res.append( trans("accel-mac-control") );
}
else
{
res.append( trans("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98"
}
}
if( accel_mask & MASK_ALT )
res.append( trans("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5"
if( accel_mask & MASK_SHIFT )
res.append( trans("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7"
#else
if( accel_mask & MASK_CONTROL )
res.append( trans("accel-win-control") );
if( accel_mask & MASK_ALT )
res.append( trans("accel-win-alt") );
if( accel_mask & MASK_SHIFT )
res.append( trans("accel-win-shift") );
#endif
std::string key_string = LLKeyboard::stringFromKey(key);
if ((accel_mask & MASK_NORMALKEYS) &&
(key_string[0] == '-' || key_string[0] == '=' || key_string[0] == '+'))

View File

@ -38,10 +38,10 @@ enum EKeystate
{
KEYSTATE_DOWN,
KEYSTATE_LEVEL,
KEYSTATE_UP
KEYSTATE_UP
};
typedef boost::function<bool(EKeystate keystate)> LLKeyFunc;
typedef boost::function<void(EKeystate keystate)> LLKeyFunc;
typedef std::string (LLKeyStringTranslatorFunc)(const char *label);
enum EKeyboardInsertMode
@ -50,6 +50,15 @@ enum EKeyboardInsertMode
LL_KIM_OVERWRITE
};
class LLKeyBinding
{
public:
KEY mKey;
MASK mMask;
// const char *mName; // unused
LLKeyFunc mFunction;
};
class LLWindowCallbacks;
class LLKeyboard
@ -94,8 +103,7 @@ public:
static BOOL maskFromString(const std::string& str, MASK *mask); // False on failure
static BOOL keyFromString(const std::string& str, KEY *key); // False on failure
static std::string stringFromKey(KEY key, bool translate = true);
static std::string stringFromAccelerator( MASK accel_mask ); // separated for convinience, returns with "+": "Shift+" or "Shift+Alt+"...
static std::string stringFromKey(KEY key);
static std::string stringFromAccelerator( MASK accel_mask, KEY key );
void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; }

View File

@ -27,7 +27,7 @@
#include "llmousehandler.h"
//virtual
BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
{
BOOL handled = FALSE;
if (down)

View File

@ -29,7 +29,6 @@
#include "linden_common.h"
#include "llrect.h"
#include "indra_constants.h"
// Mostly-abstract interface.
// Intended for use via multiple inheritance.
@ -47,7 +46,16 @@ public:
SHOW_ALWAYS,
} EShowToolTip;
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
typedef enum {
CLICK_LEFT,
CLICK_MIDDLE,
CLICK_RIGHT,
CLICK_BUTTON4,
CLICK_BUTTON5,
CLICK_DOUBLELEFT
} EClickType;
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) = 0;

View File

@ -714,6 +714,7 @@ LLWindowWin32::~LLWindowWin32()
void LLWindowWin32::show()
{
LL_DEBUGS("Window") << "Setting window to show" << LL_ENDL;
ShowWindow(mWindowHandle, SW_SHOW);
SetForegroundWindow(mWindowHandle);
SetFocus(mWindowHandle);
@ -1126,6 +1127,12 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
mPostQuit = FALSE;
// create window
LL_DEBUGS("Window") << "Creating window with X: " << window_rect.left
<< " Y: " << window_rect.top
<< " Width: " << (window_rect.right - window_rect.left)
<< " Height: " << (window_rect.bottom - window_rect.top)
<< " Fullscreen: " << mFullscreen
<< LL_ENDL;
DestroyWindow(mWindowHandle);
mWindowHandle = CreateWindowEx(dw_ex_style,
mWindowClassName,

View File

@ -62,6 +62,7 @@ private:
void onConsoleMessageCallback(std::string message, std::string source, int line);
void onStatusMessageCallback(std::string value);
void onTitleChangeCallback(std::string title);
void onTooltipCallback(std::string text);
void onLoadStartCallback();
void onRequestExitCallback();
void onLoadEndCallback(int httpStatusCode);
@ -71,6 +72,7 @@ private:
bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password);
void onCursorChangedCallback(dullahan::ECursorType type);
const std::vector<std::string> onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, const std::string dialog_accept_filter, bool& use_default);
bool onJSDialogCallback(const std::string origin_url, const std::string message_text, const std::string default_prompt_text);
void postDebugMessage(const std::string& msg);
void authResponse(LLPluginMessage &message);
@ -87,6 +89,8 @@ private:
bool mPluginsEnabled;
bool mJavascriptEnabled;
bool mDisableGPU;
bool mDisableNetworkService;
bool mUseMockKeyChain;
std::string mUserAgentSubtring;
std::string mAuthUsername;
std::string mAuthPassword;
@ -95,7 +99,6 @@ private:
bool mCanCopy;
bool mCanPaste;
std::string mCachePath;
std::string mCookiePath;
std::string mCefLogFile;
bool mCefLogVerbose;
std::vector<std::string> mPickedFiles;
@ -119,6 +122,8 @@ MediaPluginBase(host_send_func, host_user_data)
mPluginsEnabled = false;
mJavascriptEnabled = true;
mDisableGPU = false;
mDisableNetworkService = true;
mUseMockKeyChain = true;
mUserAgentSubtring = "";
mAuthUsername = "";
mAuthPassword = "";
@ -127,7 +132,6 @@ MediaPluginBase(host_send_func, host_user_data)
mCanCopy = false;
mCanPaste = false;
mCachePath = "";
mCookiePath = "";
mCefLogFile = "";
mCefLogVerbose = false;
mPickedFiles.clear();
@ -208,6 +212,12 @@ void MediaPluginCEF::onTitleChangeCallback(std::string title)
sendMessage(message);
}
void MediaPluginCEF::onTooltipCallback(std::string text)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "tooltip_text");
message.setValue("tooltip", text);
sendMessage(message);
}
////////////////////////////////////////////////////////////////////////////////
//
void MediaPluginCEF::onLoadStartCallback()
@ -355,6 +365,14 @@ const std::vector<std::string> MediaPluginCEF::onFileDialog(dullahan::EFileDialo
return std::vector<std::string>();
}
////////////////////////////////////////////////////////////////////////////////
//
bool MediaPluginCEF::onJSDialogCallback(const std::string origin_url, const std::string message_text, const std::string default_prompt_text)
{
// return true indicates we suppress the JavaScript alert UI entirely
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type)
@ -431,6 +449,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
{
mCEFLib->update();
mVolumeCatcher.pump();
// this seems bad but unless the state changes (it won't until we figure out
// how to get CEF to tell us if copy/cut/paste is available) then this function
// will return immediately
@ -491,6 +511,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1));
mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1));
mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1));
mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
@ -500,15 +521,19 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1));
mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this));
mCEFLib->setOnJSDialogCallback(std::bind(&MediaPluginCEF::onJSDialogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
dullahan::dullahan_settings settings;
settings.accept_language_list = mHostLanguage;
settings.background_color = 0xffffffff;
settings.cache_enabled = true;
settings.cache_path = mCachePath;
settings.cookie_store_path = mCookiePath;
settings.cookies_enabled = mCookiesEnabled;
settings.disable_gpu = mDisableGPU;
#if LL_DARWIN
settings.disable_network_service = mDisableNetworkService;
settings.use_mock_keychain = mUseMockKeyChain;
#endif
settings.flash_enabled = mPluginsEnabled;
settings.flip_mouse_y = false;
settings.flip_pixels_y = true;
@ -561,7 +586,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
std::string user_data_path_cookies = message_in.getValue("cookies_path");
mCachePath = user_data_path_cache + "cef_cache";
mCookiePath = user_data_path_cookies + "cef_cookies";
mCefLogFile = message_in.getValue("cef_log_file");
mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log");
}
@ -661,8 +685,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
else if (message_name == "scroll_event")
{
// Mouse coordinates for cef to be able to scroll 'containers'
//S32 x = message_in.getValueS32("x");
//S32 y = message_in.getValueS32("y");
S32 x = message_in.getValueS32("x");
S32 y = message_in.getValueS32("y");
// Wheel's clicks
S32 delta_x = message_in.getValueS32("clicks_x");
S32 delta_y = message_in.getValueS32("clicks_y");
@ -670,8 +695,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
delta_x *= -scaling_factor;
delta_y *= -scaling_factor;
// mCEFLib->mouseWheel(x, y, delta_x, delta_y);
mCEFLib->mouseWheel(delta_x, delta_y);
mCEFLib->mouseWheel(x, y, delta_x, delta_y);
}
else if (message_name == "text_event")
{

View File

@ -376,7 +376,6 @@ set(viewer_SOURCE_FILES
llinventoryobserver.cpp
llinventorypanel.cpp
lljoystickbutton.cpp
llkeyconflict.cpp
lllandmarkactions.cpp
lllandmarklist.cpp
lllegacyatmospherics.cpp
@ -557,7 +556,6 @@ set(viewer_SOURCE_FILES
llsecapi.cpp
llsechandler_basic.cpp
llselectmgr.cpp
llsetkeybinddialog.cpp
llsettingspicker.cpp
llsettingsvo.cpp
llshareavatarhandler.cpp
@ -663,7 +661,7 @@ set(viewer_SOURCE_FILES
llviewerjointattachment.cpp
llviewerjointmesh.cpp
llviewerjoystick.cpp
llviewerinput.cpp
llviewerkeyboard.cpp
llviewerlayer.cpp
llviewermedia.cpp
llviewermedia_streamingaudio.cpp
@ -1009,7 +1007,6 @@ set(viewer_HEADER_FILES
llinventoryobserver.h
llinventorypanel.h
lljoystickbutton.h
llkeyconflict.h
lllandmarkactions.h
lllandmarklist.h
lllightconstants.h
@ -1180,7 +1177,6 @@ set(viewer_HEADER_FILES
llsecapi.h
llsechandler_basic.h
llselectmgr.h
llsetkeybinddialog.h
llsettingspicker.h
llsettingsvo.h
llsidepanelappearance.h
@ -1288,7 +1284,7 @@ set(viewer_HEADER_FILES
llviewerjointattachment.h
llviewerjointmesh.h
llviewerjoystick.h
llviewerinput.h
llviewerkeyboard.h
llviewerlayer.h
llviewermedia.h
llviewermediafocus.h
@ -1673,7 +1669,7 @@ set(viewer_APPSETTINGS_FILES
app_settings/grass.xml
app_settings/high_graphics.xml
app_settings/ignorable_dialogs.xml
app_settings/key_bindings.xml
app_settings/keys.xml
app_settings/keywords_lsl_default.xml
app_settings/logcontrol.xml
app_settings/low_graphics.xml

View File

@ -1 +1 @@
6.4.4
6.4.5

View File

@ -28,12 +28,34 @@
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="A" mask="SHIFT" command="slide_left"/>
<binding key="D" mask="SHIFT" command="slide_right"/>
<binding key="W" mask="SHIFT" command="push_forward"/>
<binding key="S" mask="SHIFT" command="push_backward"/>
<binding key="E" mask="SHIFT" command="jump"/>
<binding key="C" mask="SHIFT" command="push_down"/>
<binding key="F" mask="SHIFT" command="toggle_fly"/>
<binding key="SPACE" mask="NONE" command="stop_moving"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
<binding key="LEFT" mask="SHIFT" command="slide_left"/>
<binding key="RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="UP" mask="SHIFT" command="push_forward"/>
<binding key="DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PGUP" mask="SHIFT" command="jump"/>
<binding key="PGDN" mask="SHIFT" command="push_down"/>
<binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
<binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
<binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
<binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
<binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
<binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
</first_person>
<third_person>
<binding key="A" mask="NONE" command="turn_left"/>
@ -42,10 +64,15 @@
<binding key="D" mask="SHIFT" command="slide_right"/>
<binding key="W" mask="NONE" command="push_forward"/>
<binding key="S" mask="NONE" command="push_backward"/>
<binding key="W" mask="SHIFT" command="push_forward"/>
<binding key="S" mask="SHIFT" command="push_backward"/>
<binding key="E" mask="NONE" command="jump"/>
<binding key="C" mask="NONE" command="push_down"/>
<binding key="E" mask="SHIFT" command="jump"/>
<binding key="C" mask="SHIFT" command="push_down"/>
<binding key="F" mask="NONE" command="toggle_fly"/>
<binding key="F" mask="SHIFT" command="toggle_fly"/>
<binding key="SPACE" mask="NONE" command="stop_moving"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
@ -57,8 +84,13 @@
<binding key="RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="UP" mask="NONE" command="push_forward"/>
<binding key="DOWN" mask="NONE" command="push_backward"/>
<binding key="UP" mask="SHIFT" command="push_forward"/>
<binding key="DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PGUP" mask="NONE" command="jump"/>
<binding key="PGDN" mask="NONE" command="push_down"/>
<binding key="PGUP" mask="SHIFT" command="jump"/>
<binding key="PGDN" mask="SHIFT" command="push_down"/>
<binding key="HOME" mask="SHIFT" command="toggle_fly"/>
<binding key="HOME" mask="NONE" command="toggle_fly"/>
<binding key="PAD_LEFT" mask="NONE" command="turn_left"/>
@ -67,12 +99,20 @@
<binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="PAD_UP" mask="NONE" command="push_forward"/>
<binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
<binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
<binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PAD_PGUP" mask="NONE" command="jump"/>
<binding key="PAD_PGDN" mask="NONE" command="push_down"/>
<binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
<binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
<binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
<binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
<binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
<binding key="PAD_CENTER" mask="SHIFT" command="stop_moving"/>
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
<!--Camera controls in third person on Alt-->
<binding key="LEFT" mask="ALT" command="spin_around_cw"/>
@ -99,14 +139,28 @@
<binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
<!--mimic alt zoom behavior with keyboard only-->
<binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="W" mask="CTL_ALT" command="spin_over"/>
<binding key="S" mask="CTL_ALT" command="spin_under"/>
<binding key="E" mask="CTL_ALT" command="spin_over"/>
<binding key="C" mask="CTL_ALT" command="spin_under"/>
<binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="UP" mask="CTL_ALT" command="spin_over"/>
<binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
<binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
<binding key="PGDN" mask="CTL_ALT" command="spin_under"/>
<binding key="PAD_LEFT" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="PAD_RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="PAD_UP" mask="CTL_ALT" command="spin_over"/>
<binding key="PAD_DOWN" mask="CTL_ALT" command="spin_under"/>
<binding key="PAD_PGUP" mask="CTL_ALT" command="spin_over"/>
<binding key="PAD_PGDN" mask="CTL_ALT" command="spin_under"/>
<binding key="PAD_ENTER" mask="CTL_ALT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="CTL_ALT" command="start_gesture"/>
<!--Therefore pan on Alt-Shift-->
<binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
@ -125,10 +179,63 @@
<binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
<binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
</third_person>
<!-- Basic editing camera control -->
<edit>
<binding key="A" mask="NONE" command="spin_around_cw"/>
<binding key="D" mask="NONE" command="spin_around_ccw"/>
<binding key="W" mask="NONE" command="move_forward"/>
<binding key="S" mask="NONE" command="move_backward"/>
<binding key="E" mask="NONE" command="spin_over"/>
<binding key="C" mask="NONE" command="spin_under"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="LEFT" mask="NONE" command="spin_around_cw"/>
<binding key="RIGHT" mask="NONE" command="spin_around_ccw"/>
<binding key="UP" mask="NONE" command="move_forward"/>
<binding key="DOWN" mask="NONE" command="move_backward"/>
<binding key="PGUP" mask="NONE" command="spin_over"/>
<binding key="PGDN" mask="NONE" command="spin_under"/>
<binding key="A" mask="SHIFT" command="pan_left"/>
<binding key="D" mask="SHIFT" command="pan_right"/>
<binding key="W" mask="SHIFT" command="pan_up"/>
<binding key="S" mask="SHIFT" command="pan_down"/>
<binding key="LEFT" mask="SHIFT" command="pan_left"/>
<binding key="RIGHT" mask="SHIFT" command="pan_right"/>
<binding key="UP" mask="SHIFT" command="pan_up"/>
<binding key="DOWN" mask="SHIFT" command="pan_down"/>
<!--Walking works with ALT held down.-->
<binding key="A" mask="ALT" command="slide_left"/>
<binding key="D" mask="ALT" command="slide_right"/>
<binding key="W" mask="ALT" command="push_forward"/>
<binding key="S" mask="ALT" command="push_backward"/>
<binding key="E" mask="ALT" command="jump"/>
<binding key="C" mask="ALT" command="push_down"/>
<binding key="LEFT" mask="ALT" command="slide_left"/>
<binding key="RIGHT" mask="ALT" command="slide_right"/>
<binding key="UP" mask="ALT" command="push_forward"/>
<binding key="DOWN" mask="ALT" command="push_backward"/>
<binding key="PGUP" mask="ALT" command="jump"/>
<binding key="PGDN" mask="ALT" command="push_down"/>
<binding key="HOME" mask="ALT" command="toggle_fly"/>
<binding key="PAD_LEFT" mask="ALT" command="slide_left"/>
<binding key="PAD_RIGHT" mask="ALT" command="slide_right"/>
<binding key="PAD_UP" mask="ALT" command="push_forward"/>
<binding key="PAD_DOWN" mask="ALT" command="push_backward"/>
<binding key="PAD_PGUP" mask="ALT" command="jump"/>
<binding key="PAD_PGDN" mask="ALT" command="push_down"/>
<binding key="PAD_ENTER" mask="ALT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
</edit>
<sitting>
<binding key="A" mask="ALT" command="spin_around_cw"/>
<binding key="D" mask="ALT" command="spin_around_ccw"/>
@ -144,11 +251,15 @@
<binding key="PGUP" mask="ALT" command="spin_over"/>
<binding key="PGDN" mask="ALT" command="spin_under"/>
<binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="W" mask="CTL_ALT" command="spin_over"/>
<binding key="S" mask="CTL_ALT" command="spin_under"/>
<binding key="E" mask="CTL_ALT" command="spin_over"/>
<binding key="C" mask="CTL_ALT" command="spin_under"/>
<binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="UP" mask="CTL_ALT" command="spin_over"/>
<binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
<binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
@ -183,23 +294,23 @@
<binding key="A" mask="SHIFT" command="slide_left"/>
<binding key="D" mask="SHIFT" command="slide_right"/>
<binding key="W" mask="SHIFT" command="move_forward_sitting"/>
<binding key="S" mask="SHIFT" command="move_backward_sitting"/>
<binding key="E" mask="SHIFT" command="spin_over_sitting"/>
<binding key="C" mask="SHIFT" command="spin_under_sitting"/>
<binding key="S" mask="SHIFT" command="move_backward_sitting"/>
<binding key="E" mask="SHIFT" command="spin_over_sitting"/>
<binding key="C" mask="SHIFT" command="spin_under_sitting"/>
<binding key="LEFT" mask="SHIFT" command="slide_left"/>
<binding key="RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="UP" mask="SHIFT" command="move_forward_sitting"/>
<binding key="DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
<binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="PAD_UP" mask="SHIFT" command="move_forward_sitting"/>
<binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
@ -223,9 +334,6 @@
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
</sitting>
<edit_avatar>
<!--Avatar editing camera controls-->
@ -251,7 +359,5 @@
<binding key="PAD_PGDN" mask="NONE" command="edit_avatar_spin_under"/>
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
</edit_avatar>
</keys>
</keys>

View File

@ -3542,7 +3542,7 @@
<key>DoubleClickAutoPilot</key>
<map>
<key>Comment</key>
<string>(Obsolete)Enable double-click auto pilot</string>
<string>Enable double-click auto pilot</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -3553,13 +3553,13 @@
<key>DoubleClickTeleport</key>
<map>
<key>Comment</key>
<string>Enable double-click to teleport where allowed (afects minimap and people panel)</string>
<string>Enable double-click to teleport where allowed</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
<integer>0</integer>
</map>
<key>DoubleClickShowWorldMap</key>
<map>
@ -8274,7 +8274,7 @@
<key>PushToTalkButton</key>
<map>
<key>Comment</key>
<string>(Obsolete)Which button or keyboard key is used for push-to-talk</string>
<string>Which button or keyboard key is used for push-to-talk</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -8434,7 +8434,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.125</real>
<real>0.02</real>
</map>
<key>MediaRollOffMin</key>
<map>
@ -8445,7 +8445,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>10.0</real>
<real>40.0</real>
</map>
<key>MediaRollOffMax</key>
<map>
@ -8456,7 +8456,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>30.0</real>
<real>80.0</real>
</map>
<key>RecentItemsSortOrder</key>
<map>
@ -15559,7 +15559,7 @@
<key>ClickToWalk</key>
<map>
<key>Comment</key>
<string>(obsolete)Click in world to walk to location</string>
<string>Click in world to walk to location</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>

View File

@ -129,7 +129,7 @@
#include "llcoros.h"
#include "llexception.h"
#if !LL_LINUX
#include "cef/dullahan.h"
#include "cef/dullahan_version.h"
#include "vlc/libvlc_version.h"
#endif // LL_LINUX
@ -149,7 +149,7 @@
#include "llapr.h"
#include <boost/lexical_cast.hpp>
#include "llviewerinput.h"
#include "llviewerkeyboard.h"
#include "lllfsthread.h"
#include "llworkerthread.h"
#include "lltexturecache.h"
@ -1002,15 +1002,20 @@ bool LLAppViewer::init()
gGLManager.getGLInfo(gDebugInfo);
gGLManager.printGLInfoString();
// Load User's bindings
std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml");
if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
// Load Default bindings
std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
{
// Failed to load custom bindings, try default ones
key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
if (!gViewerInput.loadBindingsXML(key_bindings_file))
std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
if (!gViewerKeyboard.loadBindings(key_bindings_file))
{
LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
}
}
@ -1445,7 +1450,6 @@ bool LLAppViewer::doFrame()
{
joystick->scanJoystick();
gKeyboard->scanKeyboard();
gViewerInput.scanMouse();
}
// Update state based on messages, user input, object idle.
@ -3218,12 +3222,16 @@ LLSD LLAppViewer::getViewerInfo() const
cef_ver_codec << ".";
cef_ver_codec << DULLAHAN_VERSION_MINOR;
cef_ver_codec << ".";
cef_ver_codec << DULLAHAN_VERSION_POINT;
cef_ver_codec << ".";
cef_ver_codec << DULLAHAN_VERSION_BUILD;
cef_ver_codec << " / CEF: ";
cef_ver_codec << std::endl;
cef_ver_codec << " CEF: ";
cef_ver_codec << CEF_VERSION;
cef_ver_codec << " / Chromium: ";
cef_ver_codec << std::endl;
cef_ver_codec << " Chromium: ";
cef_ver_codec << CHROME_VERSION_MAJOR;
cef_ver_codec << ".";
cef_ver_codec << CHROME_VERSION_MINOR;

View File

@ -71,9 +71,8 @@
#include "lltrans.h"
#include "llviewercontrol.h"
#include "llviewercamera.h"
#include "llviewereventrecorder.h"
#include "llviewermessage.h"
#include "llviewerwindow.h"
#include "llviewermessage.h"
#include "llviewershadermgr.h"
#include "llviewerthrottle.h"
#include "llvoavatarself.h"
@ -160,6 +159,87 @@ struct LabelTable : public LLInitParam::Block<LabelTable>
{}
};
class LLVoiceSetKeyDialog : public LLModalDialog
{
public:
LLVoiceSetKeyDialog(const LLSD& key);
~LLVoiceSetKeyDialog();
/*virtual*/ BOOL postBuild();
void setParent(LLFloaterPreference* parent) { mParent = parent; }
BOOL handleKeyHere(KEY key, MASK mask);
BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
static void onCancel(void* user_data);
private:
LLFloaterPreference* mParent;
};
LLVoiceSetKeyDialog::LLVoiceSetKeyDialog(const LLSD& key)
: LLModalDialog(key),
mParent(NULL)
{
}
//virtual
BOOL LLVoiceSetKeyDialog::postBuild()
{
childSetAction("Cancel", onCancel, this);
getChild<LLUICtrl>("Cancel")->setFocus(TRUE);
gFocusMgr.setKeystrokesOnly(TRUE);
return TRUE;
}
LLVoiceSetKeyDialog::~LLVoiceSetKeyDialog()
{
}
BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask)
{
BOOL result = TRUE;
if (key == 'Q' && mask == MASK_CONTROL)
{
result = FALSE;
}
else if (mParent)
{
mParent->setKey(key);
}
closeFloater();
return result;
}
BOOL LLVoiceSetKeyDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
{
BOOL result = FALSE;
if (down
&& (clicktype == LLMouseHandler::CLICK_MIDDLE || clicktype == LLMouseHandler::CLICK_BUTTON4 || clicktype == LLMouseHandler::CLICK_BUTTON5)
&& mask == 0)
{
mParent->setMouse(clicktype);
result = TRUE;
closeFloater();
}
else
{
result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
}
return result;
}
//static
void LLVoiceSetKeyDialog::onCancel(void* user_data)
{
LLVoiceSetKeyDialog* self = (LLVoiceSetKeyDialog*)user_data;
self->closeFloater();
}
// global functions
@ -239,6 +319,37 @@ void handleAppearanceCameraMovementChanged(const LLSD& newvalue)
}
}
/*bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option && floater )
{
if ( floater )
{
floater->setAllIgnored();
// LLFirstUse::disableFirstUse();
floater->buildPopupLists();
}
}
return false;
}
bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if ( 0 == option && floater )
{
if ( floater )
{
floater->resetAllIgnored();
//LLFirstUse::resetFirstUse();
floater->buildPopupLists();
}
}
return false;
}
*/
void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator)
{
numerator = 0;
@ -263,7 +374,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mGotPersonalInfo(false),
mOriginalIMViaEmail(false),
mLanguageChanged(false),
mAvatarDataInitialized(false)
mAvatarDataInitialized(false),
mClickActionDirty(false)
{
LLConversationLog::instance().addObserver(this);
@ -272,7 +384,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
static bool registered_dialog = false;
if (!registered_dialog)
{
LLFloaterReg::add("keybind_dialog", "floater_select_key.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSetKeyBindDialog>);
LLFloaterReg::add("voice_set_key", "floater_select_key.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLVoiceSetKeyDialog>);
registered_dialog = true;
}
@ -285,6 +397,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.ResetCache", boost::bind(&LLFloaterPreference::onClickResetCache, this));
mCommitCallbackRegistrar.add("Pref.ClickSkin", boost::bind(&LLFloaterPreference::onClickSkin, this,_1, _2));
mCommitCallbackRegistrar.add("Pref.SelectSkin", boost::bind(&LLFloaterPreference::onSelectSkin, this));
mCommitCallbackRegistrar.add("Pref.VoiceSetKey", boost::bind(&LLFloaterPreference::onClickSetKey, this));
mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse", boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this));
mCommitCallbackRegistrar.add("Pref.SetSounds", boost::bind(&LLFloaterPreference::onClickSetSounds, this));
mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this));
mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this));
@ -311,6 +425,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
sSkin = gSavedSettings.getString("SkinCurrent");
mCommitCallbackRegistrar.add("Pref.ClickActionChange", boost::bind(&LLFloaterPreference::onClickActionChange, this));
gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2));
gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2));
gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2));
@ -577,6 +693,12 @@ void LLFloaterPreference::apply()
}
saveAvatarProperties();
if (mClickActionDirty)
{
updateClickActionSettings();
mClickActionDirty = false;
}
}
void LLFloaterPreference::cancel()
@ -609,6 +731,12 @@ void LLFloaterPreference::cancel()
// reverts any changes to current skin
gSavedSettings.setString("SkinCurrent", sSkin);
if (mClickActionDirty)
{
updateClickActionControls();
mClickActionDirty = false;
}
LLFloaterPreferenceProxy * advanced_proxy_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_proxy");
if (advanced_proxy_settings)
{
@ -690,6 +818,9 @@ void LLFloaterPreference::onOpen(const LLSD& key)
onChangeTextureFolder();
onChangeSoundFolder();
onChangeAnimationFolder();
// Load (double-)click to walk/teleport settings.
updateClickActionControls();
// Enabled/disabled popups, might have been changed by user actions
// while preferences floater was closed.
@ -1528,6 +1659,72 @@ void LLFloaterPreference::onChangeQuality(const LLSD& data)
refresh();
}
void LLFloaterPreference::onClickSetKey()
{
LLVoiceSetKeyDialog* dialog = LLFloaterReg::showTypedInstance<LLVoiceSetKeyDialog>("voice_set_key", LLSD(), TRUE);
if (dialog)
{
dialog->setParent(this);
}
}
void LLFloaterPreference::setKey(KEY key)
{
getChild<LLUICtrl>("modifier_combo")->setValue(LLKeyboard::stringFromKey(key));
// update the control right away since we no longer wait for apply
getChild<LLUICtrl>("modifier_combo")->onCommit();
}
void LLFloaterPreference::setMouse(LLMouseHandler::EClickType click)
{
std::string bt_name;
std::string ctrl_value;
switch (click)
{
case LLMouseHandler::CLICK_MIDDLE:
bt_name = "middle_mouse";
ctrl_value = MIDDLE_MOUSE_CV;
break;
case LLMouseHandler::CLICK_BUTTON4:
bt_name = "button4_mouse";
ctrl_value = MOUSE_BUTTON_4_CV;
break;
case LLMouseHandler::CLICK_BUTTON5:
bt_name = "button5_mouse";
ctrl_value = MOUSE_BUTTON_5_CV;
break;
default:
break;
}
if (!ctrl_value.empty())
{
LLUICtrl* p2t_line_editor = getChild<LLUICtrl>("modifier_combo");
// We are using text control names for readability and compatibility with voice
p2t_line_editor->setControlValue(ctrl_value);
LLPanel* advanced_preferences = dynamic_cast<LLPanel*>(p2t_line_editor->getParent());
if (advanced_preferences)
{
p2t_line_editor->setValue(advanced_preferences->getString(bt_name));
}
}
}
void LLFloaterPreference::onClickSetMiddleMouse()
{
LLUICtrl* p2t_line_editor = getChild<LLUICtrl>("modifier_combo");
// update the control right away since we no longer wait for apply
p2t_line_editor->setControlValue(MIDDLE_MOUSE_CV);
//push2talk button "middle mouse" control value is in English, need to localize it for presentation
LLPanel* advanced_preferences = dynamic_cast<LLPanel*>(p2t_line_editor->getParent());
if (advanced_preferences)
{
p2t_line_editor->setValue(advanced_preferences->getString("middle_mouse"));
}
}
void LLFloaterPreference::onClickSetSounds()
{
// Disable Enable gesture sounds checkbox if the master sound is disabled
@ -1535,6 +1732,18 @@ void LLFloaterPreference::onClickSetSounds()
getChild<LLCheckBoxCtrl>("gesture_audio_play_btn")->setEnabled(!gSavedSettings.getBOOL("MuteSounds"));
}
/*
void LLFloaterPreference::onClickSkipDialogs()
{
LLNotificationsUtil::add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, this));
}
void LLFloaterPreference::onClickResetDialogs()
{
LLNotificationsUtil::add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, this));
}
*/
void LLFloaterPreference::onClickEnablePopup()
{
LLScrollListCtrl& disabled_popups = getChildRef<LLScrollListCtrl>("disabled_popups");
@ -2014,6 +2223,11 @@ void LLFloaterPreference::onClickAdvanced()
}
}
void LLFloaterPreference::onClickActionChange()
{
mClickActionDirty = true;
}
void LLFloaterPreference::onClickPermsDefault()
{
LLFloaterReg::showInstance("perms_default");
@ -2051,6 +2265,26 @@ void LLFloaterPreference::onLogChatHistorySaved()
}
}
void LLFloaterPreference::updateClickActionSettings()
{
const int single_clk_action = getChild<LLComboBox>("single_click_action_combo")->getValue().asInteger();
const int double_clk_action = getChild<LLComboBox>("double_click_action_combo")->getValue().asInteger();
gSavedSettings.setBOOL("ClickToWalk", single_clk_action == 1);
gSavedSettings.setBOOL("DoubleClickAutoPilot", double_clk_action == 1);
gSavedSettings.setBOOL("DoubleClickTeleport", double_clk_action == 2);
}
void LLFloaterPreference::updateClickActionControls()
{
const bool click_to_walk = gSavedSettings.getBOOL("ClickToWalk");
const bool dbl_click_to_walk = gSavedSettings.getBOOL("DoubleClickAutoPilot");
const bool dbl_click_to_teleport = gSavedSettings.getBOOL("DoubleClickTeleport");
getChild<LLComboBox>("single_click_action_combo")->setValue((int)click_to_walk);
getChild<LLComboBox>("double_click_action_combo")->setValue(dbl_click_to_teleport ? 2 : (int)dbl_click_to_walk);
}
void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
{
LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue()));
@ -2232,6 +2466,25 @@ BOOL LLPanelPreference::postBuild()
getChild<LLTextBox>("mute_chb_label")->setClickedCallback(boost::bind(&toggleMuteWhenMinimized));
}
//////////////////////PanelAdvanced ///////////////////
if (hasChild("modifier_combo", TRUE))
{
//localizing if push2talk button is set to middle mouse
std::string modifier_value = getChild<LLUICtrl>("modifier_combo")->getValue().asString();
if (MIDDLE_MOUSE_CV == modifier_value)
{
getChild<LLUICtrl>("modifier_combo")->setValue(getString("middle_mouse"));
}
else if (MOUSE_BUTTON_4_CV == modifier_value)
{
getChild<LLUICtrl>("modifier_combo")->setValue(getString("button4_mouse"));
}
else if (MOUSE_BUTTON_5_CV == modifier_value)
{
getChild<LLUICtrl>("modifier_combo")->setValue(getString("button5_mouse"));
}
}
//////////////////////PanelSetup ///////////////////
if (hasChild("max_bandwidth"), TRUE)
{
@ -2512,7 +2765,7 @@ void LLPanelPreferenceGraphics::setPresetText()
}
}
if (hasDirtyChilds() && !preset_graphic_active.empty())
if (hasDirtyChilds() && !preset_graphic_active.empty())
{
gSavedSettings.setString("PresetGraphicActive", "");
preset_graphic_active.clear();
@ -2632,373 +2885,6 @@ void LLPanelPreferenceGraphics::setHardwareDefaults()
resetDirtyChilds();
}
//------------------------LLPanelPreferenceControls--------------------------------
static LLPanelInjector<LLPanelPreferenceControls> t_pref_contrls("panel_preference_controls");
LLPanelPreferenceControls::LLPanelPreferenceControls()
:LLPanelPreference(),
mEditingColumn(-1),
mEditingMode(0)
{
// MODE_COUNT - 1 because there are currently no settings assigned to 'saved settings'.
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
mConflictHandler[i].setLoadMode((LLKeyConflictHandler::ESourceMode)i);
}
}
LLPanelPreferenceControls::~LLPanelPreferenceControls()
{
}
BOOL LLPanelPreferenceControls::postBuild()
{
// populate list of controls
pControlsTable = getChild<LLScrollListCtrl>("controls_list");
pKeyModeBox = getChild<LLComboBox>("key_mode");
pControlsTable->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onListCommit, this));
pKeyModeBox->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onModeCommit, this));
getChild<LLButton>("restore_defaults")->setCommitCallback(boost::bind(&LLPanelPreferenceControls::onRestoreDefaultsBtn, this));
return TRUE;
}
void LLPanelPreferenceControls::regenerateControls()
{
mEditingMode = pKeyModeBox->getValue().asInteger();
mConflictHandler[mEditingMode].loadFromSettings((LLKeyConflictHandler::ESourceMode)mEditingMode);
populateControlTable();
}
void LLPanelPreferenceControls::populateControlTable()
{
pControlsTable->clearRows();
pControlsTable->clearColumns();
std::string filename;
switch ((LLKeyConflictHandler::ESourceMode)mEditingMode)
{
case LLKeyConflictHandler::MODE_THIRD_PERSON:
case LLKeyConflictHandler::MODE_FIRST_PERSON:
case LLKeyConflictHandler::MODE_EDIT_AVATAR:
case LLKeyConflictHandler::MODE_SITTING:
filename = "control_table_contents.xml";
break;
default:
// 'saved settings' mode doesn't have UI or actual settings yet
LL_INFOS() << "Unimplemented mode" << LL_ENDL;
return;
}
LLXMLNodePtr xmlNode;
LLScrollListCtrl::Contents contents;
if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode))
{
LL_WARNS() << "Failed to load " << filename << LL_ENDL;
return;
}
LLXUIParser parser;
parser.readXUI(xmlNode, contents, filename);
if (!contents.validateBlock())
{
return;
}
for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator col_it = contents.columns.begin();
col_it != contents.columns.end();
++col_it)
{
pControlsTable->addColumn(*col_it);
}
LLScrollListCell::Params cell_params;
// init basic cell params
cell_params.font = LLFontGL::getFontSansSerif();
cell_params.font_halign = LLFontGL::LEFT;
cell_params.column = "";
cell_params.value = "";
for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = contents.rows.begin();
row_it != contents.rows.end();
++row_it)
{
std::string control = row_it->value.getValue().asString();
if (!control.empty() && control != "menu_separator")
{
// At the moment 4 collumns are hardcoded
LLScrollListItem::Params item_params(*row_it);
bool enabled = mConflictHandler[mEditingMode].canAssignControl(control);
item_params.enabled.setValue(enabled);
cell_params.column = "lst_ctrl1";
cell_params.value = mConflictHandler[mEditingMode].getControlString(control, 0);
item_params.columns.add(cell_params);
cell_params.column = "lst_ctrl2";
cell_params.value = mConflictHandler[mEditingMode].getControlString(control, 1);
item_params.columns.add(cell_params);
cell_params.column = "lst_ctrl3";
cell_params.value = mConflictHandler[mEditingMode].getControlString(control, 2);
item_params.columns.add(cell_params);
pControlsTable->addRow(item_params, EAddPosition::ADD_BOTTOM);
}
else
{
pControlsTable->addRow(*row_it, EAddPosition::ADD_BOTTOM);
}
}
}
// Just a workaround to not care about first separator before headers (we can start from random header)
void LLPanelPreferenceControls::addSeparator()
{
if (pControlsTable->getItemCount() > 0)
{
pControlsTable->addSeparator(EAddPosition::ADD_BOTTOM);
}
}
void LLPanelPreferenceControls::updateTable()
{
mEditingControl.clear();
std::vector<LLScrollListItem*> list = pControlsTable->getAllData();
for (S32 i = 0; i < list.size(); ++i)
{
std::string control = list[i]->getValue();
if (!control.empty())
{
LLScrollListCell* cell = list[i]->getColumn(1);
cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 0));
cell = list[i]->getColumn(2);
cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 1));
cell = list[i]->getColumn(3);
cell->setValue(mConflictHandler[mEditingMode].getControlString(control, 2));
}
}
pControlsTable->deselectAllItems();
}
void LLPanelPreferenceControls::apply()
{
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
if (mConflictHandler[i].hasUnsavedChanges())
{
mConflictHandler[i].saveToSettings();
}
}
}
void LLPanelPreferenceControls::cancel()
{
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
if (mConflictHandler[i].hasUnsavedChanges())
{
mConflictHandler[i].clear();
}
}
pControlsTable->clear();
}
void LLPanelPreferenceControls::saveSettings()
{
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
if (mConflictHandler[i].hasUnsavedChanges())
{
mConflictHandler[i].saveToSettings();
mConflictHandler[i].clear();
}
}
S32 mode = pKeyModeBox->getValue().asInteger();
if (mConflictHandler[mode].empty())
{
regenerateControls();
}
}
void LLPanelPreferenceControls::resetDirtyChilds()
{
regenerateControls();
}
void LLPanelPreferenceControls::onListCommit()
{
LLScrollListItem* item = pControlsTable->getFirstSelected();
if (item == NULL)
{
return;
}
std::string control = item->getValue();
if (control.empty())
{
pControlsTable->deselectAllItems();
return;
}
if (!mConflictHandler[mEditingMode].canAssignControl(control))
{
pControlsTable->deselectAllItems();
return;
}
S32 cell_ind = item->getSelectedCell();
if (cell_ind <= 0)
{
pControlsTable->deselectAllItems();
return;
}
// List does not tell us what cell was clicked, so we have to figure it out manually, but
// fresh mouse coordinates are not yet accessible during onCommit() and there are other issues,
// so we cheat: remember item user clicked at, trigger 'key dialog' on hover that comes next,
// use coordinates from hover to calculate cell
LLScrollListCell* cell = item->getColumn(cell_ind);
if (cell)
{
LLSetKeyBindDialog* dialog = LLFloaterReg::getTypedInstance<LLSetKeyBindDialog>("keybind_dialog", LLSD());
if (dialog)
{
mEditingControl = control;
mEditingColumn = cell_ind;
dialog->setParent(this, pControlsTable, DEFAULT_KEY_FILTER);
LLFloater* root_floater = gFloaterView->getParentFloater(this);
if (root_floater)
root_floater->addDependentFloater(dialog);
dialog->openFloater();
dialog->setFocus(TRUE);
}
}
else
{
pControlsTable->deselectAllItems();
}
}
void LLPanelPreferenceControls::onModeCommit()
{
mEditingMode = pKeyModeBox->getValue().asInteger();
if (mConflictHandler[mEditingMode].empty())
{
// opening for first time
mConflictHandler[mEditingMode].loadFromSettings((LLKeyConflictHandler::ESourceMode)mEditingMode);
}
populateControlTable();
}
void LLPanelPreferenceControls::onRestoreDefaultsBtn()
{
LLNotificationsUtil::add("PreferenceControlsDefaults", LLSD(), LLSD(), boost::bind(&LLPanelPreferenceControls::onRestoreDefaultsResponse, this, _1, _2));
}
void LLPanelPreferenceControls::onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0: // All
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
mConflictHandler[i].resetToDefaults();
// Apply changes to viewer as 'temporary'
mConflictHandler[i].saveToSettings(true);
}
updateTable();
break;
case 1: // Current
mConflictHandler[mEditingMode].resetToDefaults();
// Apply changes to viewer as 'temporary'
mConflictHandler[mEditingMode].saveToSettings(true);
updateTable();
break;
case 2: // Cancel
default:
//exit;
break;
}
}
// todo: copy onSetKeyBind to interface and inherit from interface
bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes)
{
if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl))
{
return true;
}
if ( mEditingColumn > 0)
{
if (all_modes)
{
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
if (mConflictHandler[i].empty())
{
mConflictHandler[i].loadFromSettings((LLKeyConflictHandler::ESourceMode)i);
}
mConflictHandler[i].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true);
// Apply changes to viewer as 'temporary'
mConflictHandler[i].saveToSettings(true);
}
}
else
{
mConflictHandler[mEditingMode].registerControl(mEditingControl, mEditingColumn - 1, click, key, mask, true);
// Apply changes to viewer as 'temporary'
mConflictHandler[mEditingMode].saveToSettings(true);
}
}
updateTable();
return true;
}
void LLPanelPreferenceControls::onDefaultKeyBind(bool all_modes)
{
if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl))
{
return;
}
if (mEditingColumn > 0)
{
if (all_modes)
{
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
if (mConflictHandler[i].empty())
{
mConflictHandler[i].loadFromSettings((LLKeyConflictHandler::ESourceMode)i);
}
mConflictHandler[i].resetToDefault(mEditingControl, mEditingColumn - 1);
// Apply changes to viewer as 'temporary'
mConflictHandler[i].saveToSettings(true);
}
}
else
{
mConflictHandler[mEditingMode].resetToDefault(mEditingControl, mEditingColumn - 1);
// Apply changes to viewer as 'temporary'
mConflictHandler[mEditingMode].saveToSettings(true);
}
}
updateTable();
}
void LLPanelPreferenceControls::onCancelKeyBind()
{
pControlsTable->deselectAllItems();
}
LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const LLSD& key)
: LLFloater(key)
{

View File

@ -37,17 +37,13 @@
#include "llavatarpropertiesprocessor.h"
#include "llconversationlog.h"
#include "llsearcheditor.h"
#include "llsetkeybinddialog.h"
#include "llkeyconflict.h"
class LLConversationLogObserver;
class LLPanelPreference;
class LLPanelLCD;
class LLPanelDebug;
class LLMessageSystem;
class LLComboBox;
class LLScrollListCtrl;
class LLScrollListCell;
class LLSliderCtrl;
class LLSD;
class LLTextBox;
@ -131,6 +127,13 @@ protected:
// callback for when client turns on impostors
void onAvatarImpostorsEnable();
// callback for commit in the "Single click on land" and "Double click on land" comboboxes.
void onClickActionChange();
// updates click/double-click action settings depending on controls values
void updateClickActionSettings();
// updates click/double-click action controls depending on values from settings.xml
void updateClickActionControls();
public:
// This function squirrels away the current values of the controls so that
// cancel() can restore them.
@ -143,6 +146,10 @@ public:
void onClickResetCache();
void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
void onSelectSkin();
void onClickSetKey();
void setKey(KEY key);
void setMouse(LLMouseHandler::EClickType click);
void onClickSetMiddleMouse();
void onClickSetSounds();
void onClickEnablePopup();
void onClickDisablePopup();
@ -197,6 +204,7 @@ private:
static std::string sSkin;
notifications_map mNotificationOptions;
bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user.
bool mGotPersonalInfo;
bool mOriginalIMViaEmail;
bool mLanguageChanged;
@ -286,44 +294,6 @@ private:
LOG_CLASS(LLPanelPreferenceGraphics);
};
class LLPanelPreferenceControls : public LLPanelPreference, public LLKeyBindResponderInterface
{
LOG_CLASS(LLPanelPreferenceControls);
public:
LLPanelPreferenceControls();
virtual ~LLPanelPreferenceControls();
BOOL postBuild();
void apply();
void cancel();
void saveSettings();
void resetDirtyChilds();
void onListCommit();
void onModeCommit();
void onRestoreDefaultsBtn();
void onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response);
/*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);
/*virtual*/ void onDefaultKeyBind(bool all_modes);
/*virtual*/ void onCancelKeyBind();
private:
// reloads settings, discards current changes, updates table
void regenerateControls();
void populateControlTable();
void addSeparator();
void updateTable();
LLScrollListCtrl* pControlsTable;
LLComboBox *pKeyModeBox;
LLKeyConflictHandler mConflictHandler[LLKeyConflictHandler::MODE_COUNT];
std::string mEditingControl;
S32 mEditingColumn;
S32 mEditingMode;
};
class LLFloaterPreferenceGraphicsAdvanced : public LLFloater
{
public:

View File

@ -1,852 +0,0 @@
/**
* @file llkeyconflict.cpp
* @brief
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, 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$
*/
/*
* App-wide preferences. Note that these are not per-user,
* because we need to load many preferences before we have
* a login name.
*/
#include "llviewerprecompiledheaders.h"
#include "llkeyconflict.h"
#include "llinitparam.h"
#include "llkeyboard.h"
#include "lltrans.h"
#include "llviewercontrol.h"
#include "llviewerinput.h"
#include "llviewermenu.h"
#include "llxuiparser.h"
static const std::string saved_settings_key_controls[] = { "placeholder" }; // add settings from gSavedSettings here
static const std::string filename_default = "key_bindings.xml";
static const std::string filename_temporary = "key_bindings_tmp.xml"; // used to apply uncommited changes on the go.
// LLKeyboard::stringFromMask is meant for UI and is OS dependent,
// so this class uses it's own version
std::string string_from_mask(MASK mask)
{
std::string res;
if ((mask & MASK_CONTROL) != 0)
{
res = "CTL";
}
if ((mask & MASK_ALT) != 0)
{
if (!res.empty()) res += "_";
res += "ALT";
}
if ((mask & MASK_SHIFT) != 0)
{
if (!res.empty()) res += "_";
res += "SHIFT";
}
if (mask == MASK_NONE)
{
res = "NONE";
}
return res;
}
std::string string_from_mouse(EMouseClickType click, bool translate)
{
std::string res;
switch (click)
{
case CLICK_LEFT:
res = "LMB";
break;
case CLICK_MIDDLE:
res = "MMB";
break;
case CLICK_RIGHT:
res = "RMB";
break;
case CLICK_BUTTON4:
res = "MB4";
break;
case CLICK_BUTTON5:
res = "MB5";
break;
case CLICK_DOUBLELEFT:
res = "Double LMB";
break;
default:
break;
}
if (translate && !res.empty())
{
res = LLTrans::getString(res);
}
return res;
}
// LLKeyConflictHandler
S32 LLKeyConflictHandler::sTemporaryFileUseCount = 0;
LLKeyConflictHandler::LLKeyConflictHandler()
: mHasUnsavedChanges(false),
mUsesTemporaryFile(false),
mLoadMode(MODE_COUNT)
{
}
LLKeyConflictHandler::LLKeyConflictHandler(ESourceMode mode)
: mHasUnsavedChanges(false),
mUsesTemporaryFile(false),
mLoadMode(mode)
{
loadFromSettings(mode);
}
LLKeyConflictHandler::~LLKeyConflictHandler()
{
clearUnsavedChanges();
// Note: does not reset bindings if temporary file was used
}
bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask)
{
return mControlsMap[control_name].canHandle(mouse_ind, key, mask);
}
bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask)
{
return canHandleControl(control_name, CLICK_NONE, key, mask);
}
bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask)
{
return canHandleControl(control_name, mouse_ind, KEY_NONE, mask);
}
bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask)
{
return canHandleControl(control_name, (EMouseClickType)mouse_ind, KEY_NONE, mask);
}
bool LLKeyConflictHandler::canAssignControl(const std::string &control_name)
{
control_map_t::iterator iter = mControlsMap.find(control_name);
if (iter != mControlsMap.end())
{
return iter->second.mAssignable;
}
// If we don't know this control means it wasn't assigned by user yet and thus is editable
return true;
}
// static
bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask)
{
if (key == KEY_NONE)
{
return false;
}
return (gMenuBarView && gMenuBarView->hasAccelerator(key, mask))
|| (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(key, mask));
}
// static
bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data)
{
if (data.mMouse != CLICK_NONE || data.mKey == KEY_NONE)
{
return false;
}
return (gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask))
|| (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask));
}
bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
{
if (control_name.empty())
{
return false;
}
LLKeyConflict &type_data = mControlsMap[control_name];
if (!type_data.mAssignable)
{
LL_ERRS() << "Error in code, user or system should not be able to change certain controls" << LL_ENDL;
}
LLKeyData data(mouse, key, mask, ignore_mask);
if (type_data.mKeyBind.getKeyData(index) == data)
{
return true;
}
if (isReservedByMenu(data))
{
return false;
}
if (removeConflicts(data, type_data.mConflictMask))
{
type_data.mKeyBind.replaceKeyData(data, index);
mHasUnsavedChanges = true;
return true;
}
// control already in use/blocked
return false;
}
LLKeyData LLKeyConflictHandler::getControl(const std::string &control_name, U32 index)
{
if (control_name.empty())
{
return LLKeyData();
}
return mControlsMap[control_name].getKeyData(index);
}
// static
std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata)
{
std::string result;
if (keydata.mMask != MASK_NONE && keydata.mKey != KEY_NONE)
{
result = LLKeyboard::stringFromAccelerator(keydata.mMask, keydata.mKey);
}
else if (keydata.mKey != KEY_NONE)
{
result = LLKeyboard::stringFromKey(keydata.mKey);
}
else if (keydata.mMask != MASK_NONE)
{
result = LLKeyboard::stringFromAccelerator(keydata.mMask);
}
result += string_from_mouse(keydata.mMouse, true);
return result;
}
std::string LLKeyConflictHandler::getControlString(const std::string &control_name, U32 index)
{
if (control_name.empty())
{
return "";
}
return getStringFromKeyData(mControlsMap[control_name].getKeyData(index));
}
void LLKeyConflictHandler::loadFromControlSettings(const std::string &name)
{
LLControlVariablePtr var = gSavedSettings.getControl(name);
if (var)
{
LLKeyBind bind(var->getValue());
LLKeyConflict key(bind, true, 0);
mControlsMap[name] = key;
}
}
void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination)
{
for (LLInitParam::ParamIterator<LLViewerInput::KeyBinding>::const_iterator it = keymode.bindings.begin(),
end_it = keymode.bindings.end();
it != end_it;
++it)
{
KEY key;
MASK mask;
EMouseClickType mouse = CLICK_NONE;
if (it->mouse.isProvided())
{
LLViewerInput::mouseFromString(it->mouse.getValue(), &mouse);
}
if (it->key.getValue().empty())
{
key = KEY_NONE;
}
else
{
LLKeyboard::keyFromString(it->key, &key);
}
LLKeyboard::maskFromString(it->mask, &mask);
// Note: it->command is also the name of UI element, howhever xml we are loading from
// might not know all the commands, so UI will have to know what to fill by its own
LLKeyConflict &type_data = (*destination)[it->command];
type_data.mAssignable = true;
type_data.mKeyBind.addKeyData(mouse, key, mask, true);
}
}
bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination)
{
if (filename.empty())
{
return false;
}
bool res = false;
LLViewerInput::Keys keys;
LLSimpleXUIParser parser;
if (parser.readXUI(filename, keys)
&& keys.validateBlock())
{
switch (load_mode)
{
case MODE_FIRST_PERSON:
if (keys.first_person.isProvided())
{
loadFromSettings(keys.first_person, destination);
res = true;
}
break;
case MODE_THIRD_PERSON:
if (keys.third_person.isProvided())
{
loadFromSettings(keys.third_person, destination);
res = true;
}
break;
case MODE_EDIT_AVATAR:
if (keys.edit_avatar.isProvided())
{
loadFromSettings(keys.edit_avatar, destination);
res = true;
}
break;
case MODE_SITTING:
if (keys.sitting.isProvided())
{
loadFromSettings(keys.sitting, destination);
res = true;
}
break;
default:
LL_ERRS() << "Not implememted mode " << load_mode << LL_ENDL;
break;
}
}
return res;
}
void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode)
{
mControlsMap.clear();
mDefaultsMap.clear();
// E.X. In case we need placeholder keys for conflict resolution.
generatePlaceholders(load_mode);
if (load_mode == MODE_SAVED_SETTINGS)
{
// load settings clss knows about, but it also possible to load settings by name separately
const S32 size = std::extent<decltype(saved_settings_key_controls)>::value;
for (U32 i = 0; i < size; i++)
{
loadFromControlSettings(saved_settings_key_controls[i]);
}
}
else
{
// load defaults
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename_default);
if (!loadFromSettings(load_mode, filename, &mDefaultsMap))
{
LL_WARNS() << "Failed to load default settings, aborting" << LL_ENDL;
return;
}
// load user's
filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
if (!gDirUtilp->fileExists(filename) || !loadFromSettings(load_mode, filename, &mControlsMap))
{
// mind placeholders
mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
}
}
mLoadMode = load_mode;
}
void LLKeyConflictHandler::saveToSettings(bool temporary)
{
if (mControlsMap.empty())
{
return;
}
if (mLoadMode == MODE_SAVED_SETTINGS)
{
// Does not support 'temporary', preferences handle that themself
// so in case of saved settings we just do not clear mHasUnsavedChanges
control_map_t::iterator iter = mControlsMap.begin();
control_map_t::iterator end = mControlsMap.end();
for (; iter != end; ++iter)
{
if (iter->first.empty())
{
continue;
}
LLKeyConflict &key = iter->second;
key.mKeyBind.trimEmpty();
if (!key.mAssignable)
{
continue;
}
if (gSavedSettings.controlExists(iter->first))
{
gSavedSettings.setLLSD(iter->first, key.mKeyBind.asLLSD());
}
else if (!key.mKeyBind.empty())
{
// Note: this is currently not in use, might be better for load mechanics to ask for and retain control group
// otherwise settings loaded from other control groups will end in this one
LL_INFOS() << "Creating new keybinding " << iter->first << LL_ENDL;
gSavedSettings.declareLLSD(iter->first, key.mKeyBind.asLLSD(), "comment", LLControlVariable::PERSIST_ALWAYS);
}
}
}
else
{
// Determine what file to load and load full copy of that file
std::string filename;
if (temporary)
{
filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary);
if (!gDirUtilp->fileExists(filename))
{
filename.clear();
}
}
if (filename.empty())
{
filename = gDirUtilp->findFile(filename_default,
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
}
LLViewerInput::Keys keys;
LLSimpleXUIParser parser;
if (parser.readXUI(filename, keys)
&& keys.validateBlock())
{
// replace category we edited
// mode is a HACK to correctly reset bindings without reparsing whole file and avoid doing
// own param container (which will face issues with inasseesible members of LLInitParam)
LLViewerInput::KeyMode mode;
LLViewerInput::KeyBinding binding;
control_map_t::iterator iter = mControlsMap.begin();
control_map_t::iterator end = mControlsMap.end();
for (; iter != end; ++iter)
{
// By default xml have (had) up to 6 elements per function
// eventually it will be cleaned up and UI will only shows 3 per function,
// so make sure to cleanup.
// Also this helps in keeping file small.
iter->second.mKeyBind.trimEmpty();
U32 size = iter->second.mKeyBind.getDataCount();
for (U32 i = 0; i < size; ++i)
{
if (iter->first.empty())
{
continue;
}
LLKeyConflict &key = iter->second;
key.mKeyBind.trimEmpty();
if (key.mKeyBind.empty() || !key.mAssignable)
{
continue;
}
LLKeyData data = key.mKeyBind.getKeyData(i);
// Still write empty LLKeyData to make sure we will maintain UI position
if (data.mKey == KEY_NONE)
{
// Might be better idea to be consistent and use NONE. LLViewerInput can work with both cases
binding.key = "";
}
else
{
binding.key = LLKeyboard::stringFromKey(data.mKey, false /*Do not localize*/);
}
binding.mask = string_from_mask(data.mMask);
if (data.mMouse == CLICK_NONE)
{
binding.mouse.setProvided(false);
}
else
{
// set() because 'optional', for compatibility purposes
// just copy old keys.xml and rename to key_bindings.xml, it should work
binding.mouse.set(string_from_mouse(data.mMouse, false), true);
}
binding.command = iter->first;
mode.bindings.add(binding);
}
}
switch (mLoadMode)
{
case MODE_FIRST_PERSON:
if (keys.first_person.isProvided())
{
keys.first_person.bindings.set(mode.bindings, true);
}
break;
case MODE_THIRD_PERSON:
if (keys.third_person.isProvided())
{
keys.third_person.bindings.set(mode.bindings, true);
}
break;
case MODE_EDIT_AVATAR:
if (keys.edit_avatar.isProvided())
{
keys.edit_avatar.bindings.set(mode.bindings, true);
}
break;
case MODE_SITTING:
if (keys.sitting.isProvided())
{
keys.sitting.bindings.set(mode.bindings, true);
}
break;
default:
LL_ERRS() << "Not implememted mode " << mLoadMode << LL_ENDL;
break;
}
if (temporary)
{
// write to temporary xml and use it for gViewerInput
filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary);
if (!mUsesTemporaryFile)
{
mUsesTemporaryFile = true;
sTemporaryFileUseCount++;
}
}
else
{
// write back to user's xml and use it for gViewerInput
filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
// Don't reset mUsesTemporaryFile, it will be reset at cleanup stage
}
LLXMLNodePtr output_node = new LLXMLNode("keys", false);
LLXUIParser parser;
parser.writeXUI(output_node, keys);
// Write the resulting XML to file
if (!output_node->isNull())
{
LLFILE *fp = LLFile::fopen(filename, "w");
if (fp != NULL)
{
LLXMLNode::writeHeaderToFile(fp);
output_node->writeToFile(fp);
fclose(fp);
}
}
// Now force a rebind for keyboard
if (gDirUtilp->fileExists(filename))
{
// Ideally instead of rebinding immediately we should shedule
// the rebind since single file can have multiple handlers,
// one per mode, saving simultaneously.
// Or whatever uses LLKeyConflictHandler should control the process.
gViewerInput.loadBindingsXML(filename);
}
}
}
if (!temporary)
{
// will remove any temporary file if there were any
clearUnsavedChanges();
}
}
LLKeyData LLKeyConflictHandler::getDefaultControl(const std::string &control_name, U32 index)
{
if (control_name.empty())
{
return LLKeyData();
}
if (mLoadMode == MODE_SAVED_SETTINGS)
{
LLControlVariablePtr var = gSavedSettings.getControl(control_name);
if (var)
{
return LLKeyBind(var->getDefault()).getKeyData(index);
}
return LLKeyData();
}
else
{
control_map_t::iterator iter = mDefaultsMap.find(control_name);
if (iter != mDefaultsMap.end())
{
return iter->second.mKeyBind.getKeyData(index);
}
return LLKeyData();
}
}
void LLKeyConflictHandler::resetToDefault(const std::string &control_name, U32 index)
{
if (control_name.empty())
{
return;
}
LLKeyData data = getDefaultControl(control_name, index);
if (data != mControlsMap[control_name].getKeyData(index))
{
// reset controls that might have been switched to our current control
removeConflicts(data, mControlsMap[control_name].mConflictMask);
mControlsMap[control_name].setKeyData(data, index);
}
}
void LLKeyConflictHandler::resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts)
{
if (control_name.empty())
{
return;
}
if (mLoadMode == MODE_SAVED_SETTINGS)
{
LLControlVariablePtr var = gSavedSettings.getControl(control_name);
if (var)
{
LLKeyBind bind(var->getDefault());
if (!ignore_conflicts)
{
for (S32 i = 0; i < bind.getDataCount(); ++i)
{
removeConflicts(bind.getKeyData(i), mControlsMap[control_name].mConflictMask);
}
}
mControlsMap[control_name].mKeyBind = bind;
}
else
{
mControlsMap[control_name].mKeyBind.clear();
}
}
else
{
control_map_t::iterator iter = mDefaultsMap.find(control_name);
if (iter != mDefaultsMap.end())
{
if (!ignore_conflicts)
{
for (S32 i = 0; i < iter->second.mKeyBind.getDataCount(); ++i)
{
removeConflicts(iter->second.mKeyBind.getKeyData(i), mControlsMap[control_name].mConflictMask);
}
}
mControlsMap[control_name].mKeyBind = iter->second.mKeyBind;
}
else
{
mControlsMap[control_name].mKeyBind.clear();
}
}
}
void LLKeyConflictHandler::resetToDefault(const std::string &control_name)
{
// reset specific binding without ignoring conflicts
resetToDefaultAndResolve(control_name, false);
}
void LLKeyConflictHandler::resetToDefaults(ESourceMode mode)
{
if (mode == MODE_SAVED_SETTINGS)
{
control_map_t::iterator iter = mControlsMap.begin();
control_map_t::iterator end = mControlsMap.end();
for (; iter != end; ++iter)
{
resetToDefaultAndResolve(iter->first, true);
}
}
else
{
mControlsMap.clear();
generatePlaceholders(mode);
mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
}
mHasUnsavedChanges = true;
}
void LLKeyConflictHandler::resetToDefaults()
{
if (!empty())
{
resetToDefaults(mLoadMode);
}
else
{
// not optimal since:
// 1. We are not sure that mLoadMode was set
// 2. We are not sure if there are any changes in comparison to default
// 3. We are loading 'current' only to replace it
// but it is reliable and works Todo: consider optimizing.
loadFromSettings(mLoadMode);
resetToDefaults(mLoadMode);
}
}
void LLKeyConflictHandler::clear()
{
if (clearUnsavedChanges())
{
// temporary file was removed, this means we were using it and need to reload keyboard's bindings
resetKeyboardBindings();
}
mControlsMap.clear();
mDefaultsMap.clear();
}
// static
void LLKeyConflictHandler::resetKeyboardBindings()
{
// Try to load User's bindings first
std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
{
// Failed to load custom bindings, try default ones
key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename_default);
if (!gViewerInput.loadBindingsXML(key_bindings_file))
{
LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
}
}
}
void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
{
// These controls are meant to cause conflicts when user tries to assign same control somewhere else
// also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks
/*registerTemporaryControl(CONTROL_RESERVED_MENU, CLICK_RIGHT, KEY_NONE, MASK_NONE, 0);
registerTemporaryControl(CONTROL_DELETE, CLICK_NONE, KEY_DELETE, MASK_NONE, 0);*/
}
bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask)
{
if (conlict_mask == CONFLICT_NOTHING)
{
// Can't conflict
return true;
}
std::map<std::string, S32> conflict_list;
control_map_t::iterator cntrl_iter = mControlsMap.begin();
control_map_t::iterator cntrl_end = mControlsMap.end();
for (; cntrl_iter != cntrl_end; ++cntrl_iter)
{
S32 index = cntrl_iter->second.mKeyBind.findKeyData(data);
if (index >= 0
&& cntrl_iter->second.mConflictMask != CONFLICT_NOTHING
&& (cntrl_iter->second.mConflictMask & conlict_mask) != 0)
{
if (cntrl_iter->second.mAssignable)
{
// Potentially we can have multiple conflict flags conflicting
// including unassignable keys.
// So record the conflict and find all others before doing any changes.
// Assume that there is only one conflict per bind
conflict_list[cntrl_iter->first] = index;
}
else
{
return false;
}
}
}
std::map<std::string, S32>::iterator cnflct_iter = conflict_list.begin();
std::map<std::string, S32>::iterator cnflct_end = conflict_list.end();
for (; cnflct_iter != cnflct_end; ++cnflct_iter)
{
mControlsMap[cnflct_iter->first].mKeyBind.resetKeyData(cnflct_iter->second);
}
return true;
}
void LLKeyConflictHandler::registerTemporaryControl(const std::string &control_name, EMouseClickType mouse, KEY key, MASK mask, U32 conflict_mask)
{
LLKeyConflict *type_data = &mControlsMap[control_name];
type_data->mAssignable = false;
type_data->mConflictMask = conflict_mask;
type_data->mKeyBind.addKeyData(mouse, key, mask, false);
}
bool LLKeyConflictHandler::clearUnsavedChanges()
{
bool result = false;
mHasUnsavedChanges = false;
if (mUsesTemporaryFile)
{
mUsesTemporaryFile = false;
sTemporaryFileUseCount--;
if (!sTemporaryFileUseCount)
{
result = clearTemporaryFile();
}
// else: might be usefull to overwrite content of temp file with defaults
// but at the moment there is no such need
}
return result;
}
//static
bool LLKeyConflictHandler::clearTemporaryFile()
{
// At the moment single file needs five handlers (one per mode), so doing this
// will remove file for all hadlers
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_temporary);
if (gDirUtilp->fileExists(filename))
{
LLFile::remove(filename);
return true;
}
return false;
}

View File

@ -1,156 +0,0 @@
/**
* @file llkeyconflict.h
* @brief
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, 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_LLKEYCONFLICT_H
#define LL_LLKEYCONFLICT_H
#include "llkeybind.h"
#include "llviewerinput.h"
class LLKeyConflict
{
public:
LLKeyConflict() : mAssignable(true), mConflictMask(U32_MAX) {} //temporary assignable, don't forget to change once all keys are recorded
LLKeyConflict(bool assignable, U32 conflict_mask)
: mAssignable(assignable), mConflictMask(conflict_mask) {}
LLKeyConflict(const LLKeyBind &bind, bool assignable, U32 conflict_mask)
: mAssignable(assignable), mConflictMask(conflict_mask), mKeyBind(bind) {}
LLKeyData getPrimaryKeyData() { return mKeyBind.getKeyData(0); }
LLKeyData getKeyData(U32 index) { return mKeyBind.getKeyData(index); }
void setPrimaryKeyData(const LLKeyData& data) { mKeyBind.replaceKeyData(data, 0); }
void setKeyData(const LLKeyData& data, U32 index) { mKeyBind.replaceKeyData(data, index); }
bool canHandle(EMouseClickType mouse, KEY key, MASK mask) { return mKeyBind.canHandle(mouse, key, mask); }
LLKeyBind mKeyBind;
bool mAssignable; // whether user can change key or key simply acts as placeholder
U32 mConflictMask;
};
class LLKeyConflictHandler
{
public:
enum ESourceMode // partially repeats e_keyboard_mode
{
MODE_FIRST_PERSON,
MODE_THIRD_PERSON,
MODE_EDIT_AVATAR,
MODE_SITTING,
MODE_SAVED_SETTINGS, // for settings from saved settings
MODE_COUNT
};
const U32 CONFLICT_NOTHING = 0;
// at the moment this just means that key will conflict with everything that is identical
const U32 CONFLICT_ANY = U32_MAX;
// Note: missed selection and edition commands (would be really nice to go through selection via MB4/5 or wheel)
LLKeyConflictHandler();
LLKeyConflictHandler(ESourceMode mode);
~LLKeyConflictHandler();
bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask);
bool canHandleKey(const std::string &control_name, KEY key, MASK mask);
bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask);
bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask); //Just for convinience
bool canAssignControl(const std::string &control_name);
static bool isReservedByMenu(const KEY &key, const MASK &mask);
static bool isReservedByMenu(const LLKeyData &data);
bool registerControl(const std::string &control_name, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts?
LLKeyData getControl(const std::string &control_name, U32 data_index);
// localized string
static std::string getStringFromKeyData(const LLKeyData& keydata);
std::string getControlString(const std::string &control_name, U32 data_index);
// Load single control, overrides existing one if names match
void loadFromControlSettings(const std::string &name);
// Drops any changes loads controls with ones from 'saved settings' or from xml
void loadFromSettings(ESourceMode load_mode);
// Saves settings to 'saved settings' or to xml
// If 'temporary' is set, function will save settings to temporary
// file and reload input bindings from temporary file.
// 'temporary' does not support gSavedSettings, those are handled
// by preferences, so 'temporary' is such case will simply not
// reset mHasUnsavedChanges
void saveToSettings(bool apply_temporary = false);
LLKeyData getDefaultControl(const std::string &control_name, U32 data_index);
// Resets keybinding to default variant from 'saved settings' or xml
void resetToDefault(const std::string &control_name, U32 index);
void resetToDefault(const std::string &control_name);
// resets current mode to defaults
void resetToDefaults();
bool empty() { return mControlsMap.empty(); }
void clear();
// reloads bindings from last valid user's xml or from default xml
// to keyboard's handler
static void resetKeyboardBindings();
bool hasUnsavedChanges() { return mHasUnsavedChanges; }
void setLoadMode(ESourceMode mode) { mLoadMode = mode; }
ESourceMode getLoadMode() { return mLoadMode; }
private:
void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts);
void resetToDefaults(ESourceMode mode);
// at the moment these kind of control is not savable, but takes part will take part in conflict resolution
void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask);
typedef std::map<std::string, LLKeyConflict> control_map_t;
void loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination);
bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination);
void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values
// returns false in case user is trying to reuse control that can't be reassigned
bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask);
// removes flags and removes temporary file, returns 'true' if file was removed
bool clearUnsavedChanges();
// return true if there was a file to remove
static bool clearTemporaryFile();
control_map_t mControlsMap;
control_map_t mDefaultsMap;
bool mHasUnsavedChanges;
ESourceMode mLoadMode;
// To implement 'apply immediately'+revert on cancel, class applies changes to temporary file
// but this only works for settings from keybndings files (key_bindings.xml)
// saved setting rely onto external mechanism of preferences floater
bool mUsesTemporaryFile;
static S32 sTemporaryFileUseCount;
};
#endif // LL_LLKEYCONFLICT_H

View File

@ -832,8 +832,32 @@ void LLPanelPrimMediaControls::draw()
BOOL LLPanelPrimMediaControls::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
mInactivityTimer.start();
return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
mInactivityTimer.start();
BOOL res = FALSE;
// Unlike other mouse events, we need to handle scroll here otherwise
// it will be intercepted by camera and won't reach toolpie
if (LLViewerMediaFocus::getInstance()->isHoveringOverFocused())
{
// either let toolpie handle this or expose mHoverPick.mUVCoords in some way
res = LLToolPie::getInstance()->handleScrollWheel(x, y, clicks);
}
return res;
}
BOOL LLPanelPrimMediaControls::handleScrollHWheel(S32 x, S32 y, S32 clicks)
{
mInactivityTimer.start();
BOOL res = FALSE;
if (LLViewerMediaFocus::getInstance()->isHoveringOverFocused())
{
// either let toolpie handle this or expose mHoverPick.mUVCoords in some way
res = LLToolPie::getInstance()->handleScrollHWheel(x, y, clicks);
}
return res;
}
BOOL LLPanelPrimMediaControls::handleMouseDown(S32 x, S32 y, MASK mask)

View File

@ -48,6 +48,7 @@ public:
/*virtual*/ BOOL postBuild();
virtual void draw();
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);

View File

@ -1,346 +0,0 @@
/**
* @file llsetkeybinddialog.cpp
* @brief LLSetKeyBindDialog class implementation.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llsetkeybinddialog.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "lleventtimer.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llkeyconflict.h"
#include "llviewercontrol.h"
class LLSetKeyBindDialog::Updater : public LLEventTimer
{
public:
typedef boost::function<void(MASK)> callback_t;
Updater(callback_t cb, F32 period, MASK mask)
:LLEventTimer(period),
mMask(mask),
mCallback(cb)
{
mEventTimer.start();
}
virtual ~Updater(){}
protected:
BOOL tick()
{
mCallback(mMask);
// Deletes itseft after execution
return TRUE;
}
private:
MASK mMask;
callback_t mCallback;
};
bool LLSetKeyBindDialog::sRecordKeys = false;
LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key)
: LLModalDialog(key),
pParent(NULL),
mKeyFilterMask(DEFAULT_KEY_FILTER),
pUpdater(NULL),
mContextConeOpacity(0.f),
mContextConeInAlpha(0.f),
mContextConeOutAlpha(0.f),
mContextConeFadeTime(0.f)
{
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
}
LLSetKeyBindDialog::~LLSetKeyBindDialog()
{
}
//virtual
BOOL LLSetKeyBindDialog::postBuild()
{
childSetAction("SetEmpty", onBlank, this);
childSetAction("Default", onDefault, this);
childSetAction("Cancel", onCancel, this);
getChild<LLUICtrl>("Cancel")->setFocus(TRUE);
pCheckBox = getChild<LLCheckBoxCtrl>("apply_all");
pDesription = getChild<LLTextBase>("descritption");
gFocusMgr.setKeystrokesOnly(TRUE);
return TRUE;
}
//virtual
void LLSetKeyBindDialog::onOpen(const LLSD& data)
{
sRecordKeys = true;
LLModalDialog::onOpen(data);
}
//virtual
void LLSetKeyBindDialog::onClose(bool app_quiting)
{
sRecordKeys = false;
if (pParent)
{
pParent->onCancelKeyBind();
pParent = NULL;
}
if (pUpdater)
{
// Doubleclick timer has't fired, delete it
delete pUpdater;
pUpdater = NULL;
}
LLModalDialog::onClose(app_quiting);
}
void LLSetKeyBindDialog::drawFrustum()
{
static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
drawConeToOwner(mContextConeOpacity, max_opacity, mFrustumOrigin.get(), mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
}
//virtual
void LLSetKeyBindDialog::draw()
{
drawFrustum();
LLModalDialog::draw();
}
void LLSetKeyBindDialog::setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask)
{
pParent = parent;
mFrustumOrigin = frustum_origin->getHandle();
mKeyFilterMask = key_mask;
std::string input;
if ((key_mask & ALLOW_MOUSE) != 0)
{
input = getString("mouse");
}
if ((key_mask & ALLOW_KEYS) != 0)
{
if (!input.empty())
{
input += ", ";
}
input += getString("keyboard");
}
pDesription->setText(getString("basic_description"));
pDesription->setTextArg("[INPUT]", input);
}
// static
bool LLSetKeyBindDialog::recordKey(KEY key, MASK mask)
{
if (sRecordKeys)
{
LLSetKeyBindDialog* dialog = LLFloaterReg::getTypedInstance<LLSetKeyBindDialog>("keybind_dialog", LLSD());
if (dialog && dialog->getVisible())
{
return dialog->recordAndHandleKey(key, mask);
}
else
{
LL_WARNS() << "Key recording was set despite no open dialog" << LL_ENDL;
sRecordKeys = false;
}
}
return false;
}
bool LLSetKeyBindDialog::recordAndHandleKey(KEY key, MASK mask)
{
if ((key == 'Q' && mask == MASK_CONTROL)
|| key == KEY_ESCAPE)
{
sRecordKeys = false;
closeFloater();
return true;
}
if (key == KEY_DELETE)
{
setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
sRecordKeys = false;
closeFloater();
return false;
}
// forbidden keys
if (key == KEY_NONE
|| key == KEY_RETURN
|| key == KEY_BACKSPACE)
{
return false;
}
if ((mKeyFilterMask & ALLOW_MASKS) == 0
&& (key == KEY_CONTROL || key == KEY_SHIFT || key == KEY_ALT))
{
// mask by themself are not allowed
return false;
}
else if ((mKeyFilterMask & ALLOW_KEYS) == 0)
{
// basic keys not allowed
return false;
}
else if ((mKeyFilterMask & ALLOW_MASK_KEYS) == 0 && mask != 0)
{
// masked keys not allowed
return false;
}
if (LLKeyConflictHandler::isReservedByMenu(key, mask))
{
pDesription->setText(getString("reserved_by_menu"));
pDesription->setTextArg("[KEYSTR]", LLKeyboard::stringFromAccelerator(mask,key));
return true;
}
setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean());
sRecordKeys = false;
closeFloater();
return true;
}
BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
{
BOOL result = FALSE;
if (!pParent)
{
// we already processed 'down' event, this is 'up', consume
closeFloater();
result = TRUE;
}
if (!result && clicktype == CLICK_LEFT)
{
// try handling buttons first
if (down)
{
result = LLView::handleMouseDown(x, y, mask);
}
else
{
result = LLView::handleMouseUp(x, y, mask);
}
if (result)
{
setFocus(TRUE);
gFocusMgr.setKeystrokesOnly(TRUE);
}
// ignore selection related combinations
else if (down && (mask & (MASK_SHIFT | MASK_CONTROL)) == 0)
{
// this can be a double click, wait a bit;
if (!pUpdater)
{
// Note: default doubleclick time is 500ms, but can stretch up to 5s
pUpdater = new Updater(boost::bind(&onClickTimeout, this, _1), 0.7f, mask);
result = TRUE;
}
}
}
if (!result
&& (clicktype != CLICK_LEFT) // subcases were handled above
&& ((mKeyFilterMask & ALLOW_MOUSE) != 0)
&& (clicktype != CLICK_RIGHT || mask != 0) // reassigning menu button is not supported
&& ((mKeyFilterMask & ALLOW_MASK_MOUSE) != 0 || mask == 0)) // reserved for selection
{
setKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean());
result = TRUE;
if (!down)
{
// wait for 'up' event before closing
// alternative: set pUpdater
closeFloater();
}
}
return result;
}
//static
void LLSetKeyBindDialog::onCancel(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
self->closeFloater();
}
//static
void LLSetKeyBindDialog::onBlank(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
// tmp needs 'no key' button
self->setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
self->closeFloater();
}
//static
void LLSetKeyBindDialog::onDefault(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
if (self->pParent)
{
self->pParent->onDefaultKeyBind(self->pCheckBox->getValue().asBoolean());
self->pParent = NULL;
}
self->closeFloater();
}
//static
void LLSetKeyBindDialog::onClickTimeout(void* user_data, MASK mask)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
// timer will delete itself after timeout
self->pUpdater = NULL;
self->setKeyBind(CLICK_LEFT, KEY_NONE, mask, self->pCheckBox->getValue().asBoolean());
self->closeFloater();
}
void LLSetKeyBindDialog::setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes)
{
if (pParent)
{
pParent->onSetKeyBind(click, key, mask, all_modes);
pParent = NULL;
}
}

View File

@ -1,105 +0,0 @@
/**
* @file llsetkeybinddialog.h
* @brief LLSetKeyBindDialog class definition
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, 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_LLSETKEYBINDDIALOG_H
#define LL_LLSETKEYBINDDIALOG_H
#include "llmodaldialog.h"
class LLCheckBoxCtrl;
class LLTextBase;
// Filters for LLSetKeyBindDialog
static const U32 ALLOW_MOUSE = 1;
static const U32 ALLOW_MASK_MOUSE = 2;
static const U32 ALLOW_KEYS = 4; //keyboard
static const U32 ALLOW_MASK_KEYS = 8;
static const U32 ALLOW_MASKS = 16;
static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS;
class LLKeyBindResponderInterface
{
public:
virtual ~LLKeyBindResponderInterface() {};
virtual void onCancelKeyBind() = 0;
virtual void onDefaultKeyBind(bool all_modes) = 0;
// returns true if parent failed to set key due to key being in use
virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) = 0;
};
class LLSetKeyBindDialog : public LLModalDialog
{
public:
LLSetKeyBindDialog(const LLSD& key);
~LLSetKeyBindDialog();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& data);
/*virtual*/ void onClose(bool app_quiting);
/*virtual*/ void draw();
void setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask = DEFAULT_KEY_FILTER);
// Wrapper around recordAndHandleKey
// It does not record, it handles, but handleKey function is already in use
static bool recordKey(KEY key, MASK mask);
BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
static void onCancel(void* user_data);
static void onBlank(void* user_data);
static void onDefault(void* user_data);
static void onClickTimeout(void* user_data, MASK mask);
class Updater;
private:
bool recordAndHandleKey(KEY key, MASK mask);
void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);
LLKeyBindResponderInterface *pParent;
LLCheckBoxCtrl *pCheckBox;
LLTextBase *pDesription;
U32 mKeyFilterMask;
Updater *pUpdater;
static bool sRecordKeys; // for convinience and not to check instance each time
// drawFrustum
private:
void drawFrustum();
LLHandle <LLView> mFrustumOrigin;
F32 mContextConeOpacity;
F32 mContextConeInAlpha;
F32 mContextConeOutAlpha;
F32 mContextConeFadeTime;
};
#endif // LL_LLSETKEYBINDDIALOG_H

View File

@ -994,7 +994,7 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
}
LLSpatialGroup* group = drawablep->getSpatialGroup();
//llassert(group != NULL);
llassert(group != NULL);
if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
{

View File

@ -811,6 +811,7 @@ bool idle_startup()
show_debug_menus();
// Hide the splash screen
LL_DEBUGS("AppInit") << "Hide the splash screen and show window" << LL_ENDL;
LLSplashScreen::hide();
// Push our window frontmost
gViewerWindow->getWindow()->show();
@ -818,9 +819,12 @@ bool idle_startup()
// DEV-16927. The following code removes errant keystrokes that happen while the window is being
// first made visible.
#ifdef _WIN32
LL_DEBUGS("AppInit") << "Processing PeekMessage" << LL_ENDL;
MSG msg;
while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) )
{ }
{
}
LL_DEBUGS("AppInit") << "PeekMessage processed" << LL_ENDL;
#endif
display_startup();
timeout.reset();

View File

@ -60,7 +60,7 @@ LLTool::~LLTool()
}
}
BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
{
BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
@ -83,9 +83,9 @@ BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLTool left mouse down" << LL_ENDL;
}
// by default, didn't handle it
// AGENT_CONTROL_LBUTTON_DOWN is handled by scanMouse() and scanKey()
// LL_INFOS() << "LLTool::handleMouseDown" << LL_ENDL;
return FALSE;
gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
return TRUE;
}
BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
@ -95,8 +95,8 @@ BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLTool left mouse up" << LL_ENDL;
}
// by default, didn't handle it
// AGENT_CONTROL_LBUTTON_UP is handled by scanMouse() and scanKey()
// LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL;
gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
return TRUE;
}

View File

@ -49,7 +49,7 @@ public:
virtual BOOL isView() const { return FALSE; }
// Virtual functions inherited from LLMouseHandler
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);

View File

@ -83,6 +83,7 @@ LLToolPie::LLToolPie()
mMouseOutsideSlop( false ),
mMouseSteerX(-1),
mMouseSteerY(-1),
mBlockClickToWalk(false),
mClickAction(0),
mClickActionBuyEnabled( gSavedSettings.getBOOL("ClickActionBuyEnabled") ),
mClickActionPayEnabled( gSavedSettings.getBOOL("ClickActionPayEnabled") ),
@ -90,7 +91,7 @@ LLToolPie::LLToolPie()
{
}
BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
{
BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
@ -171,8 +172,10 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
mPick.mKeyMask = mask;
mMouseButtonDown = true;
handleLeftClickPick();
return handleLeftClickPick();
return TRUE;
}
// Spawn context menus on right mouse down so you can drag over and select
@ -200,14 +203,31 @@ BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
return LLTool::handleRightMouseUp(x, y, mask);
}
BOOL LLToolPie::handleScrollWheelAny(S32 x, S32 y, S32 clicks_x, S32 clicks_y)
{
BOOL res = FALSE;
// mHoverPick should have updated on its own and we should have a face
// in LLViewerMediaFocus in case of media, so just reuse mHoverPick
if (mHoverPick.mUVCoords.mV[VX] >= 0.f && mHoverPick.mUVCoords.mV[VY] >= 0.f)
{
res = LLViewerMediaFocus::getInstance()->handleScrollWheel(mHoverPick.mUVCoords, clicks_x, clicks_y);
}
else
{
// this won't provide correct coordinates in case of object selection
res = LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks_x, clicks_y);
}
return res;
}
BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
return handleScrollWheelAny(x, y, 0, clicks);
}
BOOL LLToolPie::handleScrollHWheel(S32 x, S32 y, S32 clicks)
{
return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
return handleScrollWheelAny(x, y, clicks, 0);
}
// True if you selected an object.
@ -371,6 +391,8 @@ BOOL LLToolPie::handleLeftClickPick()
// put focus back "in world"
if (gFocusMgr.getKeyboardFocus())
{
// don't click to walk on attempt to give focus to world
mBlockClickToWalk = true;
gFocusMgr.setKeyboardFocus(NULL);
}
@ -414,7 +436,7 @@ BOOL LLToolPie::handleLeftClickPick()
}
object = (LLViewerObject*)object->getParent();
}
if (object && object == gAgentAvatarp)
if (object && object == gAgentAvatarp && !gSavedSettings.getBOOL("ClickToWalk"))
{
// we left clicked on avatar, switch to focus mode
mMouseButtonDown = false;
@ -431,6 +453,7 @@ BOOL LLToolPie::handleLeftClickPick()
// LLFirstUse::useLeftClickNoHit();
/////////
// Eat the event
return LLTool::handleMouseDown(x, y, mask);
}
@ -537,97 +560,17 @@ void LLToolPie::resetSelection()
mClickAction = 0;
}
bool LLToolPie::walkToClickedLocation()
void LLToolPie::walkToClickedLocation()
{
if (gAgent.getFlying() // don't auto-navigate while flying until that works
|| !gAgentAvatarp
|| gAgentAvatarp->isSitting())
{
return false;
}
if(mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
mAutoPilotDestination->setPixelSize(5);
mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
mAutoPilotDestination->setDuration(3.f);
LLPickInfo saved_pick = mPick;
mPick = gViewerWindow->pickImmediate(mHoverPick.mMousePt.mX, mHoverPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore rigged */,
FALSE /* ignore particles */);
if (mPick.mPickType == LLPickInfo::PICK_OBJECT)
{
if (mPick.getObject() && mPick.getObject()->isHUDAttachment())
{
mPick = saved_pick;
return false;
}
}
LLViewerObject* avatar_object = mPick.getObject();
// get pointer to avatar
while (avatar_object && !avatar_object->isAvatar())
{
avatar_object = (LLViewerObject*)avatar_object->getParent();
}
if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
{
const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
// pretend we picked some point a bit in front of avatar
mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
}
if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
(mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
{
gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
if (mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
mAutoPilotDestination->setPixelSize(5);
mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
mAutoPilotDestination->setDuration(3.f);
LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
gAgent.startAutoPilotGlobal(pos, std::string(), NULL, NULL, NULL, 0.f, 0.03f, FALSE);
LLFirstUse::notMoving(false);
showVisualContextMenuEffect();
return true;
}
else
{
LL_DEBUGS() << "walk target was "
<< (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
<< ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
<< ", pick object was " << mPick.mObjectID
<< LL_ENDL;
mPick = saved_pick;
return false;
}
return true;
}
bool LLToolPie::teleportToClickedLocation()
{
LLViewerObject* objp = mHoverPick.getObject();
LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
bool is_in_world = mHoverPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
bool is_land = mHoverPick.mPickType == LLPickInfo::PICK_LAND;
bool pos_non_zero = !mHoverPick.mPosGlobal.isExactlyZero();
bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
bool has_click_action = final_click_action(objp);
if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
{
LLVector3d pos = mHoverPick.mPosGlobal;
pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
gAgent.teleportViaLocationLookAt(pos);
mPick = mHoverPick;
showVisualContextMenuEffect();
return true;
}
return false;
LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
gAgent.startAutoPilotGlobal(pos, std::string(), NULL, NULL, NULL, 0.f, 0.03f, FALSE);
}
// When we get object properties after left-clicking on an object
@ -703,7 +646,8 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL;
}
else if (!mMouseOutsideSlop
&& mMouseButtonDown)
&& mMouseButtonDown
&& gSavedSettings.getBOOL("ClickToWalk"))
{
S32 delta_x = x - mMouseDownX;
S32 delta_y = y - mMouseDownY;
@ -788,10 +732,70 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
mDoubleClickTimer.reset();
}
LLViewerObject* obj = mPick.getObject();
U8 click_action = final_click_action(obj);
// let media have first pass at click
if (handleMediaMouseUp() || LLViewerMediaFocus::getInstance()->getFocus())
{
mBlockClickToWalk = true;
}
stopCameraSteering();
mMouseButtonDown = false;
if (click_action == CLICK_ACTION_NONE // not doing 1-click action
&& gSavedSettings.getBOOL("ClickToWalk") // click to walk enabled
&& !gAgent.getFlying() // don't auto-navigate while flying until that works
&& gAgentAvatarp
&& !gAgentAvatarp->isSitting()
&& !mBlockClickToWalk // another behavior hasn't cancelled click to walk
)
{
// We may be doing click to walk, but we don't want to use a target on
// a transparent object because the user thought they were clicking on
// whatever they were seeing through it, so recompute what was clicked on
// ignoring transparent objects
LLPickInfo savedPick = mPick;
mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore rigged */,
FALSE /* ignore particles */);
if (!mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
&& (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
|| mPick.mObjectID.notNull())) // or on an object
{
// handle special cases of steering picks
LLViewerObject* avatar_object = mPick.getObject();
// get pointer to avatar
while (avatar_object && !avatar_object->isAvatar())
{
avatar_object = (LLViewerObject*)avatar_object->getParent();
}
if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
{
const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
// pretend we picked some point a bit in front of avatar
mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
}
gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
walkToClickedLocation();
LLFirstUse::notMoving(false);
return TRUE;
}
else
{
LL_DEBUGS("maint5901") << "walk target was "
<< (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
<< ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
<< ", pick object was " << mPick.mObjectID
<< LL_ENDL;
// we didn't click to walk, so restore the original target
mPick = savedPick;
}
}
gViewerWindow->setCursor(UI_CURSOR_ARROW);
if (hasMouseCapture())
{
@ -801,6 +805,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
LLToolMgr::getInstance()->clearTransientTool();
gAgentCamera.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on
mBlockClickToWalk = false;
return LLTool::handleMouseUp(x, y, mask);
}
@ -826,13 +831,66 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
return TRUE;
}
if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f))
if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f))
{
mDoubleClickTimer.stop();
return FALSE;
}
mDoubleClickTimer.stop();
if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
{
// We may be doing double click to walk, but we don't want to use a target on
// a transparent object because the user thought they were clicking on
// whatever they were seeing through it, so recompute what was clicked on
// ignoring transparent objects
LLPickInfo savedPick = mPick;
mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore rigged */,
FALSE /* ignore particles */);
if(mPick.mPickType == LLPickInfo::PICK_OBJECT)
{
if (mPick.getObject() && mPick.getObject()->isHUDAttachment())
{
mPick = savedPick;
return FALSE;
}
}
if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
(mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
{
walkToClickedLocation();
return TRUE;
}
else
{
// restore the original pick for any other purpose
mPick = savedPick;
}
}
else if (gSavedSettings.getBOOL("DoubleClickTeleport"))
{
LLViewerObject* objp = mPick.getObject();
LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
bool is_in_world = mPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND;
bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero();
bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
bool has_click_action = final_click_action(objp);
if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
{
LLVector3d pos = mPick.mPosGlobal;
pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
gAgent.teleportViaLocationLookAt(pos);
return TRUE;
}
}
return FALSE;
}
@ -1364,6 +1422,7 @@ void LLToolPie::VisitHomePage(const LLPickInfo& info)
void LLToolPie::handleSelect()
{
// tool is reselected when app gets focus, etc.
mBlockClickToWalk = true;
}
void LLToolPie::handleDeselect()
@ -1424,7 +1483,7 @@ void LLToolPie::stopCameraSteering()
bool LLToolPie::inCameraSteerMode()
{
return mMouseButtonDown && mMouseOutsideSlop;
return mMouseButtonDown && mMouseOutsideSlop && gSavedSettings.getBOOL("ClickToWalk");
}
// true if x,y outside small box around start_x,start_y
@ -1875,6 +1934,7 @@ void LLToolPie::startCameraSteering()
{
LLFirstUse::notMoving(false);
mMouseOutsideSlop = true;
mBlockClickToWalk = true;
if (gAgentCamera.getFocusOnAvatar())
{

View File

@ -42,13 +42,14 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
public:
// Virtual functions inherited from LLMouseHandler
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
BOOL handleScrollWheelAny(S32 x, S32 y, S32 clicks_x, S32 clicks_y);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleScrollHWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
@ -67,8 +68,8 @@ public:
LLViewerObject* getClickActionObject() { return mClickActionObject; }
LLObjectSelection* getLeftClickSelection() { return (LLObjectSelection*)mLeftClickSelection; }
void resetSelection();
bool walkToClickedLocation();
bool teleportToClickedLocation();
void walkToClickedLocation();
void blockClickToWalk() { mBlockClickToWalk = true; }
void stopClickToWalk();
static void selectionPropertiesReceived();
@ -110,6 +111,7 @@ private:
LLPointer<LLHUDEffectBlob> mAutoPilotDestination;
LLPointer<LLHUDEffectBlob> mMouseSteerGrabPoint;
bool mClockwise;
bool mBlockClickToWalk;
LLUUID mMediaMouseCaptureID;
LLPickInfo mPick;
LLPickInfo mHoverPick;

View File

@ -253,6 +253,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (gWindowResized)
{ //skip render on frames where window has been resized
LL_DEBUGS("Window") << "Resizing window" << LL_ENDL;
LL_RECORD_BLOCK_TIME(FTM_RESIZE_WINDOW);
gGL.flush();
glClear(GL_COLOR_BUFFER_BIT);

File diff suppressed because it is too large Load Diff

View File

@ -1,177 +0,0 @@
/**
* @file llviewerinput.h
* @brief LLViewerInput class header file
*
* $LicenseInfo:firstyear=2005&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_LLVIEWERINPUT_H
#define LL_LLVIEWERINPUT_H
#include "llkeyboard.h" // For EKeystate
#include "llinitparam.h"
const S32 MAX_KEY_BINDINGS = 128; // was 60
class LLNamedFunction
{
public:
LLNamedFunction() : mFunction(NULL) { };
~LLNamedFunction() { };
std::string mName;
LLKeyFunc mFunction;
};
class LLKeyboardBinding
{
public:
KEY mKey;
MASK mMask;
LLKeyFunc mFunction;
};
class LLMouseBinding
{
public:
EMouseClickType mMouse;
MASK mMask;
LLKeyFunc mFunction;
};
typedef enum e_keyboard_mode
{
MODE_FIRST_PERSON,
MODE_THIRD_PERSON,
MODE_EDIT_AVATAR,
MODE_SITTING,
MODE_COUNT
} EKeyboardMode;
class LLWindow;
void bind_keyboard_functions();
class LLViewerInput
{
public:
struct KeyBinding : public LLInitParam::Block<KeyBinding>
{
Mandatory<std::string> key,
mask,
command;
Optional<std::string> mouse; // Note, not mandatory for the sake of backward campatibility with keys.xml
KeyBinding();
};
struct KeyMode : public LLInitParam::Block<KeyMode>
{
Multiple<KeyBinding> bindings;
KeyMode();
};
struct Keys : public LLInitParam::Block<Keys>
{
Optional<KeyMode> first_person,
third_person,
sitting,
edit_avatar;
Keys();
};
LLViewerInput();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
BOOL handleKeyUp(KEY key, MASK mask);
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode() const;
static BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
static BOOL mouseFromString(const std::string& string, EMouseClickType *mode);// False on failure
bool scanKey(KEY key,
BOOL key_down,
BOOL key_up,
BOOL key_level) const;
// handleMouse() records state, scanMouse() goes through states, scanMouse(click) processes individual saved states after UI is done with them
BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
void scanMouse();
private:
bool scanKey(const std::vector<LLKeyboardBinding> &binding,
S32 binding_count,
KEY key,
MASK mask,
BOOL key_down,
BOOL key_up,
BOOL key_level,
bool repeat) const;
enum EMouseState
{
MOUSE_STATE_DOWN, // key down this frame
MOUSE_STATE_CLICK, // key went up and down in scope of same frame
MOUSE_STATE_LEVEL, // clicked again fast, or never released
MOUSE_STATE_UP, // went up this frame
MOUSE_STATE_SILENT // notified about 'up', do not notify again
};
bool scanMouse(EMouseClickType click, EMouseState state) const;
bool scanMouse(const std::vector<LLMouseBinding> &binding,
S32 binding_count,
EMouseClickType mouse,
MASK mask,
EMouseState state) const;
S32 loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode);
BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
BOOL bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name);
void resetBindings();
// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
// TODO: at some point it is better to remake this, especially keyaboard part
// would be much better to send to functions actual state of the button than
// to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
std::set<KEY> mKeysSkippedByUI;
BOOL mKeyHandledByUI[KEY_COUNT]; // key processed successfully by UI
// This is indentical to what llkeyboard does (mKeyRepeated, mKeyLevel, mKeyDown e t c),
// just instead of remembering individually as bools, we record state as enum
EMouseState mMouseLevel[CLICK_COUNT]; // records of key state
};
extern LLViewerInput gViewerInput;
#endif // LL_LLVIEWERINPUT_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
/**
* @file llviewerkeyboard.h
* @brief LLViewerKeyboard class header file
*
* $LicenseInfo:firstyear=2005&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_LLVIEWERKEYBOARD_H
#define LL_LLVIEWERKEYBOARD_H
#include "llkeyboard.h" // For EKeystate
#include "llinitparam.h"
const S32 MAX_NAMED_FUNCTIONS = 100;
const S32 MAX_KEY_BINDINGS = 128; // was 60
class LLNamedFunction
{
public:
LLNamedFunction() : mFunction(NULL) { };
~LLNamedFunction() { };
std::string mName;
LLKeyFunc mFunction;
};
typedef enum e_keyboard_mode
{
MODE_FIRST_PERSON,
MODE_THIRD_PERSON,
MODE_EDIT,
MODE_EDIT_AVATAR,
MODE_SITTING,
MODE_COUNT
} EKeyboardMode;
void bind_keyboard_functions();
class LLViewerKeyboard
{
public:
struct KeyBinding : public LLInitParam::Block<KeyBinding>
{
Mandatory<std::string> key,
mask,
command;
KeyBinding();
};
struct KeyMode : public LLInitParam::Block<KeyMode>
{
Multiple<KeyBinding> bindings;
EKeyboardMode mode;
KeyMode(EKeyboardMode mode);
};
struct Keys : public LLInitParam::Block<Keys>
{
Optional<KeyMode> first_person,
third_person,
edit,
sitting,
edit_avatar;
Keys();
};
LLViewerKeyboard();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
BOOL handleKeyUp(KEY key, MASK mask);
S32 loadBindings(const std::string& filename); // returns number bound, 0 on error
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode();
BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
private:
S32 loadBindingMode(const LLViewerKeyboard::KeyMode& keymode);
BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
S32 mBindingCount[MODE_COUNT];
LLKeyBinding mBindings[MODE_COUNT][MAX_KEY_BINDINGS];
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
std::set<KEY> mKeysSkippedByUI;
BOOL mKeyHandledByUI[KEY_COUNT]; // key processed successfully by UI
};
extern LLViewerKeyboard gViewerKeyboard;
#endif // LL_LLVIEWERKEYBOARD_H

View File

@ -2293,6 +2293,18 @@ void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
}
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::scrollWheel(const LLVector2& texture_coords, S32 scroll_x, S32 scroll_y, MASK mask)
{
if (mMediaSource)
{
S32 x, y;
scaleTextureCoords(texture_coords, &x, &y);
scrollWheel(x, y, scroll_x, scroll_y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask)
{

View File

@ -235,6 +235,7 @@ public:
void mouseMove(const LLVector2& texture_coords, MASK mask);
void mouseDoubleClick(const LLVector2& texture_coords, MASK mask);
void mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button = 0);
void scrollWheel(const LLVector2& texture_coords, S32 scroll_x, S32 scroll_y, MASK mask);
void scrollWheel(S32 x, S32 y, S32 scroll_x, S32 scroll_y, MASK mask);
void mouseCapture();

View File

@ -373,13 +373,26 @@ BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_pa
media_impl->handleUnicodeCharHere(uni_char);
return true;
}
BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
BOOL LLViewerMediaFocus::handleScrollWheel(const LLVector2& texture_coords, S32 clicks_x, S32 clicks_y)
{
BOOL retval = FALSE;
LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
if (media_impl && media_impl->hasMedia())
{
media_impl->scrollWheel(texture_coords, clicks_x, clicks_y, gKeyboard->currentMask(TRUE));
retval = TRUE;
}
return retval;
}
BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks_x, S32 clicks_y)
{
BOOL retval = FALSE;
LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
if(media_impl && media_impl->hasMedia())
{
media_impl->scrollWheel(x, y, 0, clicks, gKeyboard->currentMask(TRUE));
media_impl->scrollWheel(x, y, clicks_x, clicks_y, gKeyboard->currentMask(TRUE));
retval = TRUE;
}
return retval;

View File

@ -58,7 +58,8 @@ public:
/*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
/*virtual*/ BOOL handleKeyUp(KEY key, MASK mask, BOOL called_from_parent);
/*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
BOOL handleScrollWheel(const LLVector2& texture_coords, S32 clicks_x, S32 clicks_y);
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks_x, S32 clicks_y);
void update();
@ -67,7 +68,8 @@ public:
bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face);
bool isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face);
bool isHoveringOverFocused() { return mFocusedObjectID == mHoverObjectID && mFocusedObjectFace == mHoverObjectFace; };
// These look up (by uuid) and return the values that were set with setFocusFace. They will return null if the objects have been destroyed.
LLViewerMediaImpl* getFocusedMediaImpl();
LLViewerObject* getFocusedObject();

View File

@ -8031,6 +8031,7 @@ BOOL LLViewerMenuHolderGL::hideMenus()
if (LLMenuHolderGL::hideMenus())
{
LLToolPie::instance().blockClickToWalk();
handled = TRUE;
}

View File

@ -103,6 +103,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
if(mMediaImpl.isNull())
{
play(parcel);
return;
}
@ -159,6 +160,12 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
if (!gSavedSettings.getBOOL("AudioStreamingMedia"))
return;
// This test appears all over the code and really should be facotred out into a single
// call that returns true/false (with option ask dialog) but that is outside of scope
// for this work so we'll just directly.
if (gSavedSettings.getS32("ParcelMediaAutoPlayEnable") == 0 )
return;
std::string media_url = parcel->getMediaURL();
std::string media_current_url = parcel->getMediaCurrentURL();
std::string mime_type = parcel->getMediaType();

View File

@ -45,8 +45,7 @@
#include "llmeshrepository.h"
#include "llnotificationhandler.h"
#include "llpanellogin.h"
#include "llsetkeybinddialog.h"
#include "llviewerinput.h"
#include "llviewerkeyboard.h"
#include "llviewermenu.h"
#include "llviewquery.h"
@ -174,7 +173,7 @@
#include "llviewergesture.h"
#include "llviewertexturelist.h"
#include "llviewerinventory.h"
#include "llviewerinput.h"
#include "llviewerkeyboard.h"
#include "llviewermedia.h"
#include "llviewermediafocus.h"
#include "llviewermenu.h"
@ -915,18 +914,7 @@ LLViewerWindow::Params::Params()
{}
void LLViewerWindow::handlePieMenu(S32 x, S32 y, MASK mask)
{
if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
{
// If the current tool didn't process the click, we should show
// the pie menu. This can be done by passing the event to the pie
// menu tool.
LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
}
}
BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down)
BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
{
const char* buttonname = "";
const char* buttonstatestr = "";
@ -950,30 +938,28 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m
switch (clicktype)
{
case CLICK_LEFT:
case LLMouseHandler::CLICK_LEFT:
mLeftMouseDown = down;
buttonname = "Left";
break;
case CLICK_RIGHT:
case LLMouseHandler::CLICK_RIGHT:
mRightMouseDown = down;
buttonname = "Right";
break;
case CLICK_MIDDLE:
case LLMouseHandler::CLICK_MIDDLE:
mMiddleMouseDown = down;
buttonname = "Middle";
break;
case CLICK_DOUBLELEFT:
case LLMouseHandler::CLICK_DOUBLELEFT:
mLeftMouseDown = down;
buttonname = "Left Double Click";
break;
case CLICK_BUTTON4:
case LLMouseHandler::CLICK_BUTTON4:
buttonname = "Button 4";
break;
case CLICK_BUTTON5:
case LLMouseHandler::CLICK_BUTTON5:
buttonname = "Button 5";
break;
default:
break; // COUNT and NONE
}
LLView::sMouseHandlerMessage.clear();
@ -1024,11 +1010,6 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m
LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname));
}
else if (down && clicktype == CLICK_RIGHT)
{
handlePieMenu(x, y, mask);
r = TRUE;
}
return r;
}
@ -1075,12 +1056,7 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m
return TRUE;
}
if (down && clicktype == CLICK_RIGHT)
{
handlePieMenu(x, y, mask);
return TRUE;
}
// If we got this far on a down-click, it wasn't handled.
// Up-clicks, though, are always handled as far as the OS is concerned.
BOOL default_rtn = !down;
@ -1099,8 +1075,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask
mMouseDownTimer.reset();
}
BOOL down = TRUE;
//handleMouse() loops back to LLViewerWindow::handleAnyMouseClick
return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down);
return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
}
BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask)
@ -1108,7 +1083,8 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma
// try handling as a double-click first, then a single-click if that
// wasn't handled.
BOOL down = TRUE;
if (gViewerInput.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down))
if (handleAnyMouseClick(window, pos, mask,
LLMouseHandler::CLICK_DOUBLELEFT, down))
{
return TRUE;
}
@ -1122,24 +1098,47 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
mMouseDownTimer.stop();
}
BOOL down = FALSE;
return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down);
return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
}
BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
S32 x = pos.mX;
S32 y = pos.mY;
x = ll_round((F32)x / mDisplayScale.mV[VX]);
y = ll_round((F32)y / mDisplayScale.mV[VY]);
BOOL down = TRUE;
return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down);
BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
if (handle)
return handle;
// *HACK: this should be rolled into the composite tool logic, not
// hardcoded at the top level.
if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
{
// If the current tool didn't process the click, we should show
// the pie menu. This can be done by passing the event to the pie
// menu tool.
LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
// show_context_menu( x, y, mask );
}
return TRUE;
}
BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down);
return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
}
BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = TRUE;
gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, true);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
// Always handled as far as the OS is concerned.
return TRUE;
@ -1294,7 +1293,8 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, false);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
// Always handled as far as the OS is concerned.
return TRUE;
@ -1305,10 +1305,12 @@ BOOL LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask
switch (button)
{
case 4:
gViewerInput.handleMouse(window, pos, mask, CLICK_BUTTON4, down);
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON4, down);
handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON4, down);
break;
case 5:
gViewerInput.handleMouse(window, pos, mask, CLICK_BUTTON5, down);
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON5, down);
handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON5, down);
break;
default:
break;
@ -1455,6 +1457,9 @@ void LLViewerWindow::handleFocusLost(LLWindow *window)
BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
{
// Let the voice chat code check for its PTT key. Note that this never affects event processing.
LLVoiceClient::getInstance()->keyDown(key, mask);
if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME)
{
gAgent.clearAFK();
@ -1473,12 +1478,14 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
return FALSE;
}
// remaps, handles ignored cases and returns back to viewer window.
return gViewerInput.handleKey(key, mask, repeated);
return gViewerKeyboard.handleKey(key, mask, repeated);
}
BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
{
// Let the voice chat code check for its PTT key. Note that this never affects event processing.
LLVoiceClient::getInstance()->keyUp(key, mask);
// Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera
LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance();
if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp)
@ -1486,13 +1493,13 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
tool_inspectp->keyUp(key, mask);
}
return gViewerInput.handleKeyUp(key, mask);
return gViewerKeyboard.handleKeyUp(key, mask);
}
void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
{
LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
gViewerInput.scanKey(key, key_down, key_up, key_level);
gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
return; // Be clear this function returns nothing
}
@ -2732,14 +2739,6 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
// hide tooltips on keypress
LLToolTipMgr::instance().blockToolTips();
// let menus handle navigation keys for navigation
if (LLSetKeyBindDialog::recordKey(key, mask))
{
LL_DEBUGS() << "Key handled by LLSetKeyBindDialog" << LL_ENDL;
LLViewerEventRecorder::instance().logKeyEvent(key,mask);
return TRUE;
}
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if (keyboard_focus
@ -2955,8 +2954,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
{
if (mask != MASK_ALT)
{
// remaps, handles ignored cases and returns back to viewer window.
return gViewerInput.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
}
}

View File

@ -175,9 +175,8 @@ public:
void initWorldUI();
void setUIVisibility(bool);
bool getUIVisibility();
void handlePieMenu(S32 x, S32 y, MASK mask);
BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
//
// LLWindowCallback interface implementation

View File

@ -200,6 +200,8 @@ const LLVoiceVersionInfo LLVoiceClient::getVersion()
void LLVoiceClient::updateSettings()
{
setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled"));
std::string keyString = gSavedSettings.getString("PushToTalkButton");
setPTTKey(keyString);
setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
mDisableMic = gSavedSettings.getBOOL("VoiceDisableMic");
@ -635,6 +637,32 @@ bool LLVoiceClient::getPTTIsToggle()
return mPTTIsToggle;
}
void LLVoiceClient::setPTTKey(std::string &key)
{
// Value is stored as text for readability
if(key == "MiddleMouse")
{
mPTTMouseButton = LLMouseHandler::CLICK_MIDDLE;
}
else if(key == "MouseButton4")
{
mPTTMouseButton = LLMouseHandler::CLICK_BUTTON4;
}
else if (key == "MouseButton5")
{
mPTTMouseButton = LLMouseHandler::CLICK_BUTTON5;
}
else
{
mPTTMouseButton = 0;
if(!LLKeyboard::keyFromString(key, &mPTTKey))
{
// If the call failed, don't match any key.
key = KEY_NONE;
}
}
}
void LLVoiceClient::inputUserControlState(bool down)
{
if(mPTTIsToggle)
@ -655,6 +683,43 @@ void LLVoiceClient::toggleUserPTTState(void)
setUserPTTState(!getUserPTTState());
}
void LLVoiceClient::keyDown(KEY key, MASK mask)
{
if (gKeyboard->getKeyRepeated(key))
{
// ignore auto-repeat keys
return;
}
if (mPTTMouseButton == 0 && LLAgent::isActionAllowed("speak") && (key == mPTTKey))
{
bool down = gKeyboard->getKeyDown(mPTTKey);
if (down)
{
inputUserControlState(down);
}
}
}
void LLVoiceClient::keyUp(KEY key, MASK mask)
{
if (mPTTMouseButton == 0 && (key == mPTTKey))
{
bool down = gKeyboard->getKeyDown(mPTTKey);
if (!down)
{
inputUserControlState(down);
}
}
}
void LLVoiceClient::updateMouseState(S32 click, bool down)
{
if(mPTTMouseButton == click && LLAgent::isActionAllowed("speak"))
{
inputUserControlState(down);
}
}
//-------------------------------------------
// nearby speaker accessors

View File

@ -408,10 +408,16 @@ public:
void setUsePTT(bool usePTT);
void setPTTIsToggle(bool PTTIsToggle);
bool getPTTIsToggle();
void setPTTKey(std::string &key);
void updateMicMuteLogic();
BOOL lipSyncEnabled();
// PTT key triggering
void keyDown(KEY key, MASK mask);
void keyUp(KEY key, MASK mask);
void updateMouseState(S32 click, bool down);
boost::signals2::connection MicroChangedCallback(const micro_changed_signal_t::slot_type& cb ) { return mMicroChangedSignal.connect(cb); }

View File

@ -37,7 +37,7 @@
#include "llview.h"
#include "llviewinject.h"
#include "llviewerwindow.h"
#include "llviewerinput.h"
#include "llviewerkeyboard.h"
#include "llrootview.h"
#include "llsdutil.h"
#include "stringize.h"
@ -279,7 +279,7 @@ void LLWindowListener::keyDown(LLSD const & evt)
response.setResponse(target_view->getInfo());
gFocusMgr.setKeyboardFocus(target_view);
gViewerInput.handleKey(key, mask, false);
gViewerKeyboard.handleKey(key, mask, false);
if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
}
else
@ -291,7 +291,7 @@ void LLWindowListener::keyDown(LLSD const & evt)
}
else
{
gViewerInput.handleKey(key, mask, false);
gViewerKeyboard.handleKey(key, mask, false);
if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
}
}

View File

@ -1,625 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<contents>
<columns
relative_width="0.34"
label="Action"
name="lst_action" />
<columns
relative_width="0.22"
label="Primary Control"
name="lst_ctrl1" />
<columns
relative_width="0.22"
label="Alternate 1"
name="lst_ctrl2" />
<columns
relative_width="0.22"
label="Alternate 2"
name="lst_ctrl3" />
<rows
enabled="false"
name="move_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Move Actions"
name="lst_action"
value="Move_Walk_Off" />
</rows>
<rows
name="walk_to"
value="walk_to">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Walk to location mouse cursor points to"
value="Walk to" />
</rows>
<rows
name="teleport_to"
value="teleport_to">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Teleport to location mouse cursor points to, but not all locations allow direct teleportation so you might be teleported closer to destination instead"
value="Teleport to" />
</rows>
<rows
name="push_forward"
value="push_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Move Forward" />
</rows>
<rows
name="push_backward"
value="push_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Move Backward" />
</rows>
<rows
name="turn_left"
value="turn_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Left" />
</rows>
<rows
name="turn_right"
value="turn_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Right" />
</rows>
<rows
name="slide_left"
value="slide_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Strafe left" />
</rows>
<rows
name="slide_right"
value="slide_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Strafe right" />
</rows>
<rows
name="jump"
value="jump">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Jump/Up" />
</rows>
<rows
name="push_down"
value="push_down">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Down" />
</rows>
<rows
name="run_forward"
value="run_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Forward" />
</rows>
<rows
name="run_backward"
value="run_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Backward" />
</rows>
<rows
name="run_left"
value="run_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Left" />
</rows>
<rows
name="run_right"
value="run_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Right" />
</rows>
<rows
name="toggle_run"
value="toggle_run">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Toggle Run" />
</rows>
<rows
name="toggle_fly"
value="toggle_fly">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Fly/Stop flying" />
</rows>
<rows
name="toggle_sit"
value="toggle_sit">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Sit/Stand" />
</rows>
<rows
name="stop_moving"
value="stop_moving">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Stop Moving" />
</rows>
<rows
enabled="false">
<columns
type="icon"
color="0 0 0 0.7"
halign="center"
value="menu_separator" />
</rows>
<rows
enabled="false"
name="camera_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Camera"
name="lst_action"
value="Cam_FreeCam_Off" />
</rows>
<rows
name="look_up"
value="look_up">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Look Up" />
</rows>
<rows
name="look_down"
value="look_down">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Look Down" />
</rows>
<rows
name="move_forward"
value="move_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward" />
</rows>
<rows
name="move_backward"
value="move_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward" />
</rows>
<rows
name="move_forward_fast"
value="move_forward_fast">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward Fast" />
</rows>
<rows
name="move_backward_fast"
value="move_backward_fast">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward Fast" />
</rows>
<rows
name="move_forward_sitting"
value="move_forward_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward Sitting" />
</rows>
<rows
name="move_backward_sitting"
value="move_backward_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward Sitting" />
</rows>
<rows
name="spin_over"
value="spin_over">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Over" />
</rows>
<rows
name="spin_under"
value="spin_under">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Under" />
</rows>
<rows
name="spin_over_sitting"
value="spin_over_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Over" />
</rows>
<rows
name="spin_under_sitting"
value="spin_under_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Under" />
</rows>
<rows
name="pan_up"
value="pan_up">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Up" />
</rows>
<rows
name="pan_down"
value="pan_down">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Down" />
</rows>
<rows
name="pan_left"
value="pan_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Left" />
</rows>
<rows
name="pan_right"
value="pan_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Right" />
</rows>
<rows
name="pan_in"
value="pan_in">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan In" />
</rows>
<rows
name="pan_out"
value="pan_out">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Out" />
</rows>
<rows
name="spin_around_ccw"
value="spin_around_ccw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around counterclockwise"
value="Counterclockwise" />
</rows>
<rows
name="spin_around_cw"
value="spin_around_cw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around clockwise"
value="Clockwise" />
</rows>
<rows
name="spin_around_ccw_sitting"
value="spin_around_ccw_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around counterclockwise sitting"
value="Counterclockwise Sitting" />
</rows>
<rows
name="spin_around_cw_sitting"
value="spin_around_cw_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around clockwise sitting"
value="Clockwise Sitting" />
</rows>
<rows
enabled="false">
<columns
type="icon"
color="0 0 0 0.7"
halign="center"
value="menu_separator" />
</rows>
<rows
enabled="false"
name="editing_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Editing"
name="lst_action"
value="Tool_Dozer" />
</rows>
<rows
name="edit_avatar_spin_ccw"
value="edit_avatar_spin_ccw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around avatar counterclockwise"
value="Counterclockwise" />
</rows>
<rows
name="edit_avatar_spin_cw"
value="edit_avatar_spin_cw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around avatar clockwise"
value="Clockwise" />
</rows>
<rows
name="edit_avatar_spin_over"
value="edit_avatar_spin_over">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin over avatar"
value="Camera Spin Over" />
</rows>
<rows
name="edit_avatar_spin_under"
value="edit_avatar_spin_under">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin under avatar"
value="Camera Spin Under" />
</rows>
<rows
name="edit_avatar_move_forward"
value="edit_avatar_move_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward" />
</rows>
<rows
name="edit_avatar_move_backward"
value="edit_avatar_move_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward" />
</rows>
<rows
enabled="false">
<columns
type="icon"
color="0 0 0 0.7"
halign="center"
value="menu_separator" />
</rows>
<rows
enabled="false"
name="media_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Sound and Media"
name="lst_action"
value="Audio_Press" />
</rows>
<rows
name="toggle_pause_media"
value="toggle_pause_media">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Play/Pause Media" />
</rows>
<rows
name="toggle_enable_media"
value="toggle_enable_media">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Play/Stop All Media" />
</rows>
<rows
name="voice_follow_key"
value="voice_follow_key">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Voice" />
</rows>
<rows
name="toggle_voice"
value="toggle_voice">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Toggle Voice" />
</rows>
<rows
name="start_chat"
value="start_chat">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Start Chat" />
</rows>
<rows
name="start_gesture"
value="start_gesture">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Start Gesture" />
</rows>
</contents>

View File

@ -169,13 +169,6 @@ https://accounts.secondlife.com/change_email/
layout="topleft"
help_topic="preferences_uploads_tab"
name="uploads" />
<panel
class="panel_preference_controls"
filename="panel_preferences_controls.xml"
label="Controls"
layout="topleft"
help_topic="preferences_controls_tab"
name="controls" />
</tab_container>
</floater>

View File

@ -4,27 +4,10 @@
border="false"
can_close="false"
can_minimize="false"
height="116"
height="90"
layout="topleft"
name="modal container"
width="272">
<floater.string
name="keyboard">
Keyboard
</floater.string>
<floater.string
name="mouse">
Mouse Buttons
</floater.string>
<floater.string
name="basic_description">
Press a key to set your trigger.
Allowed input: [INPUT].
</floater.string>
<floater.string
name="reserved_by_menu">
Combination [KEYSTR] is reserved by menu.
</floater.string>
width="240">
<text
type="string"
halign="center"
@ -33,47 +16,19 @@ Combination [KEYSTR] is reserved by menu.
height="30"
layout="topleft"
left="30"
name="descritption"
name="Save item as:"
top="25"
word_wrap="true"
width="212">
Press a key to set your trigger.
Allowed input: [INPUT].
width="180">
Press a key to set your Speak button trigger.
</text>
<check_box
follows="top|left"
height="20"
initial_value="false"
label="Apply to all"
layout="topleft"
left="90"
name="apply_all"
tool_tip="Viewer uses different control combinations depending on what you are doing in world, setting this will apply your change to all combinations"
top_pad="8"
width="160" />
<button
height="23"
label="Set Empty"
layout="topleft"
left="8"
name="SetEmpty"
top_pad="6"
width="80" />
<button
height="23"
label="Default"
layout="topleft"
left_pad="8"
name="Default"
top_delta="0"
width="80" />
<button
height="23"
label="Cancel"
label_selected="Cancel"
layout="topleft"
left_pad="8"
right="-10"
name="Cancel"
top_delta="0"
width="80" />
top_pad="8"
width="100" />
</floater>

View File

@ -11420,19 +11420,6 @@ Cannot create large prims that intersect other residents. Please re-try when ot
notext="Cancel"
yestext="OK"/>
</notification>
<notification
icon="alertmodal.tga"
name="PreferenceControlsDefaults"
type="alertmodal">
Do you want to restore default values for controls?
<tag>confirm</tag>
<usetemplate
canceltext="Cancel"
name="yesnocancelbuttons"
notext="Current mode"
yestext="All modes"/>
</notification>
<notification
icon="alertmodal.tga"

View File

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<panel
border="true"
follows="all"
height="408"
label="Controls"
layout="topleft"
left="102"
name="controls"
top="1"
width="517">
<combo_box
follows="top|left"
layout="topleft"
top="6"
left="10"
height="23"
width="140"
name="key_mode">
<combo_box.item
label="Third Person "
name="third_person"
value="1"/>
<combo_box.item
label="First Person (Mouselook)"
name="first_person"
value="0"/>
<combo_box.item
label="Edit Avatar"
name="edit_avatar"
value="2"/>
<combo_box.item
label="Sitting"
name="sitting"
value="3"/>
</combo_box>
<button
follows="top|left"
layout="topleft"
top="6"
right="-10"
height="23"
width="140"
label="Restore Defaults"
tool_tip="Restores default values for all control modes."
name="restore_defaults"/>
<scroll_list
draw_heading="true"
follows="all"
layout="topleft"
column_padding="0"
selection_type="header"
top="31"
left="3"
bottom="-3"
right="-3"
can_sort="false"
multi_select="false"
name="controls_list"
fg_disable_color="ScrollUnselectedColor"/>
</panel>

View File

@ -195,6 +195,70 @@
name="invert_mouse"
top_delta="0"
width="128" />
<text
follows="left|top"
type="string"
length="1"
height="10"
layout="topleft"
left="86"
name="single_click_action_lbl"
width="150"
top_pad="20">
Single click on land:
</text>
<combo_box
height="23"
layout="topleft"
left_pad="10"
top_delta="-6"
name="single_click_action_combo"
width="200">
<combo_box.item
label="No action"
name="0"
value="0"/>
<combo_box.item
label="Move to clicked point"
name="1"
value="1"/>
<combo_box.commit_callback
function="Pref.ClickActionChange"/>
</combo_box>
<text
follows="left|top"
type="string"
length="1"
height="10"
layout="topleft"
left="86"
name="double_click_action_lbl"
width="150"
top_pad="12">
Double click on land:
</text>
<combo_box
height="23"
layout="topleft"
left_pad="10"
top_delta="-6"
name="double_click_action_combo"
width="200">
<combo_box.item
label="No action"
name="0"
value="0"/>
<combo_box.item
label="Move to clicked point"
name="1"
value="1"/>
<combo_box.item
label="Teleport to clicked point"
name="2"
value="2"/>
<combo_box.commit_callback
function="Pref.ClickActionChange"/>
</combo_box>
<button
height="23"
label="Other Devices"

View File

@ -463,13 +463,52 @@
enabled_control="EnableVoiceChat"
control_name="PushToTalkToggle"
height="15"
label="Toggle speak on/off when I press button in toolbar"
label="Toggle speak on/off when I press:"
layout="topleft"
left="44"
name="push_to_talk_toggle_check"
width="237"
tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."
top_pad="3"/>
<line_editor
follows="top|left"
control_name="PushToTalkButton"
enabled="false"
enabled_control="EnableVoiceChat"
height="23"
left="80"
max_length_bytes="200"
name="modifier_combo"
label="Push-to-Speak trigger"
top_pad="3"
width="200" />
<button
layout="topleft"
follows="top|left"
enabled_control="EnableVoiceChat"
height="23"
label="Set Key"
left_pad="5"
name="set_voice_hotkey_button"
width="100">
<button.commit_callback
function="Pref.VoiceSetKey" />
</button>
<button
enabled_control="EnableVoiceChat"
follows="top|left"
halign="center"
height="23"
image_overlay="Refresh_Off"
layout="topleft"
tool_tip="Reset to Middle Mouse Button"
mouse_opaque="true"
name="set_voice_middlemouse_button"
left_pad="5"
width="25">
<button.commit_callback
function="Pref.VoiceSetMiddleMouse" />
</button>
<button
control_name="ShowDeviceSettings"
follows="left|top"

View File

@ -4089,15 +4089,6 @@ Try enclosing path to the editor with double quotes.
<string name="Z">Z</string>
<!-- Key names end -->
<!-- Mouse button names (short) begin -->
<string name="LMB">LMB</string>
<string name="MMB">MMB</string>
<string name="RMB">RMB</string>
<string name="MB4">MB4</string>
<string name="MB5">MB5</string>
<string name="Double LMB">Double LMB</string>
<!-- Mouse button names end -->
<!-- llviewerwindow -->
<string name="BeaconParticle">Viewing particle beacons (blue)</string>
<string name="BeaconPhysical">Viewing physical object beacons (green)</string>

View File

@ -599,13 +599,11 @@ class WindowsManifest(ViewerManifest):
config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release'
with self.prefix(src=os.path.join(pkgdir, 'bin', config)):
self.path("chrome_elf.dll")
self.path("d3dcompiler_43.dll")
self.path("d3dcompiler_47.dll")
self.path("libcef.dll")
self.path("libEGL.dll")
self.path("libGLESv2.dll")
self.path("dullahan_host.exe")
self.path("natives_blob.bin")
self.path("snapshot_blob.bin")
self.path("v8_context_snapshot.bin")
@ -800,6 +798,7 @@ class WindowsManifest(ViewerManifest):
for exe in (
self.final_exe(),
"SLVersionChecker.exe",
"llplugin/dullahan_host.exe",
):
self.sign(exe)
@ -833,13 +832,13 @@ class WindowsManifest(ViewerManifest):
def sign(self, exe):
sign_py = os.environ.get('SIGN', r'C:\buildscripts\code-signing\sign.py')
python = os.environ.get('PYTHON', 'python')
python = os.environ.get('PYTHON', sys.executable)
if os.path.exists(sign_py):
dst_path = self.dst_path_of(exe)
print "about to run signing of: ", dst_path
self.run_command([python, sign_py, dst_path])
else:
print "Skipping code signing of %s: %s not found" % (exe, sign_py)
print "Skipping code signing of %s %s: %s not found" % (self.dst_path_of(exe), exe, sign_py)
def escape_slashes(self, path):
return path.replace('\\', '\\\\\\\\')
@ -1110,46 +1109,55 @@ class DarwinManifest(ViewerManifest):
# $viewer_app/Contents/Frameworks/Chromium Embedded Framework.framework
SLPlugin_framework = self.relsymlinkf(CEF_framework, catch=False)
# copy DullahanHelper.app
self.path2basename(relpkgdir, 'DullahanHelper.app')
# for all the multiple CEF/Dullahan (as of CEF 76) helper app bundles we need:
for helper in (
"DullahanHelper",
"DullahanHelper (GPU)",
"DullahanHelper (Renderer)",
"DullahanHelper (Plugin)",
):
# app is the directory name of the app bundle, with app/Contents/MacOS/helper as the executable
app = helper + ".app"
# and fix that up with a Frameworks/CEF symlink too
with self.prefix(dst=os.path.join(
'DullahanHelper.app', 'Contents', 'Frameworks')):
# from Dullahan Helper.app/Contents/Frameworks/Chromium Embedded
# Framework.framework back to
# SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework
# Since SLPlugin_framework is itself a
# symlink, don't let relsymlinkf() resolve --
# explicitly call relpath(symlink=True) and
# create that symlink here.
DullahanHelper_framework = \
self.symlinkf(self.relpath(SLPlugin_framework, symlink=True),
catch=False)
# copy DullahanHelper.app
self.path2basename(relpkgdir, app)
# change_command includes install_name_tool, the
# -change subcommand and the old framework rpath
# stamped into the executable. To use it with
# run_command(), we must still append the new
# framework path and the pathname of the
# executable to change.
change_command = [
'install_name_tool', '-change',
'@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework']
# and fix that up with a Frameworks/CEF symlink too
with self.prefix(dst=os.path.join(
app, 'Contents', 'Frameworks')):
# from Dullahan Helper *.app/Contents/Frameworks/Chromium Embedded
# Framework.framework back to
# SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework
# Since SLPlugin_framework is itself a
# symlink, don't let relsymlinkf() resolve --
# explicitly call relpath(symlink=True) and
# create that symlink here.
helper_framework = \
self.symlinkf(self.relpath(SLPlugin_framework, symlink=True), catch=False)
with self.prefix(dst=os.path.join(
'DullahanHelper.app', 'Contents', 'MacOS')):
# Now self.get_dst_prefix() is, at runtime,
# @executable_path. Locate the helper app
# framework (which is a symlink) from here.
newpath = os.path.join(
'@executable_path',
self.relpath(DullahanHelper_framework, symlink=True),
frameworkname)
# and restamp the DullahanHelper executable
self.run_command(
change_command +
[newpath, self.dst_path_of('DullahanHelper')])
# change_command includes install_name_tool, the
# -change subcommand and the old framework rpath
# stamped into the executable. To use it with
# run_command(), we must still append the new
# framework path and the pathname of the
# executable to change.
change_command = [
'install_name_tool', '-change',
'@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework']
with self.prefix(dst=os.path.join(
app, 'Contents', 'MacOS')):
# Now self.get_dst_prefix() is, at runtime,
# @executable_path. Locate the helper app
# framework (which is a symlink) from here.
newpath = os.path.join(
'@executable_path',
self.relpath(helper_framework, symlink=True),
frameworkname)
# and restamp the Dullahan Helper executable itself
self.run_command(
change_command +
[newpath, self.dst_path_of(helper)])
# SLPlugin plugins
with self.prefix(dst="llplugin"):