SL-6109 Better menu accelerator support and slight reorganization
parent
b6890180ea
commit
b8c5ae8d8f
|
|
@ -3514,6 +3514,27 @@ S32 LLMenuBarGL::getRightmostMenuEdge()
|
|||
return (*item_iter)->getRect().mRight;
|
||||
}
|
||||
|
||||
bool LLMenuBarGL::hasAccelerator(const KEY &key, const MASK &mask) const
|
||||
{
|
||||
if (key == KEY_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLMenuKeyboardBinding *accelerator = NULL;
|
||||
std::list<LLMenuKeyboardBinding*>::const_iterator list_it;
|
||||
for (list_it = mAccelerators.begin(); list_it != mAccelerators.end(); ++list_it)
|
||||
{
|
||||
accelerator = *list_it;
|
||||
if ((accelerator->mKey == key) && (accelerator->mMask == (mask & MASK_NORMALKEYS)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// add a vertical separator to this menu
|
||||
BOOL LLMenuBarGL::addSeparator()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -792,6 +792,8 @@ public:
|
|||
|
||||
void resetMenuTrigger() { mAltKeyTrigger = FALSE; }
|
||||
|
||||
bool hasAccelerator(const KEY &key, const MASK &mask) const;
|
||||
|
||||
private:
|
||||
// add a menu - this will create a drop down menu.
|
||||
virtual BOOL appendMenu( LLMenuGL* menu );
|
||||
|
|
|
|||
|
|
@ -551,6 +551,7 @@ set(viewer_SOURCE_FILES
|
|||
llsecapi.cpp
|
||||
llsechandler_basic.cpp
|
||||
llselectmgr.cpp
|
||||
llsetkeybinddialog.cpp
|
||||
llshareavatarhandler.cpp
|
||||
llsidepanelappearance.cpp
|
||||
llsidepanelinventory.cpp
|
||||
|
|
@ -1172,6 +1173,7 @@ set(viewer_HEADER_FILES
|
|||
llsecapi.h
|
||||
llsechandler_basic.h
|
||||
llselectmgr.h
|
||||
llsetkeybinddialog.h
|
||||
llsidepanelappearance.h
|
||||
llsidepanelinventory.h
|
||||
llsidepanelinventorysubpanel.h
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
#include "llcombobox.h"
|
||||
#include "llcommandhandler.h"
|
||||
#include "lldirpicker.h"
|
||||
#include "lldrawfrustum.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llfeaturemanager.h"
|
||||
#include "llfocusmgr.h"
|
||||
|
|
@ -161,306 +160,6 @@ struct LabelTable : public LLInitParam::Block<LabelTable>
|
|||
{}
|
||||
};
|
||||
|
||||
// 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 CAN_IGNORE_MASKS = 32; // For example W (aka Forward) should work regardless of SHIFT being pressed
|
||||
static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS | CAN_IGNORE_MASKS;
|
||||
|
||||
class LLSetKeyBindDialog : public LLModalDialog, public LLDrawFrustum
|
||||
{
|
||||
public:
|
||||
LLSetKeyBindDialog(const LLSD& key);
|
||||
~LLSetKeyBindDialog();
|
||||
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void onClose(bool app_quiting);
|
||||
/*virtual*/ void draw();
|
||||
|
||||
void setParent(LLPanelPreferenceControls* parent, U32 key_mask = DEFAULT_KEY_FILTER);
|
||||
|
||||
BOOL handleKeyHere(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:
|
||||
void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore);
|
||||
LLPanelPreferenceControls* pParent;
|
||||
LLCheckBoxCtrl* pCheckBox;
|
||||
|
||||
U32 mKeyFilterMask;
|
||||
Updater *pUpdater;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key)
|
||||
: LLModalDialog(key),
|
||||
pParent(NULL),
|
||||
mKeyFilterMask(DEFAULT_KEY_FILTER),
|
||||
pUpdater(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
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>("ignore_masks");
|
||||
|
||||
gFocusMgr.setKeystrokesOnly(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLSetKeyBindDialog::onClose(bool app_quiting)
|
||||
{
|
||||
if (pParent)
|
||||
{
|
||||
pParent->onCancelKeyBind();
|
||||
pParent = NULL;
|
||||
}
|
||||
if (pUpdater)
|
||||
{
|
||||
// Doubleclick timer has't fired, delete it
|
||||
delete pUpdater;
|
||||
pUpdater = NULL;
|
||||
}
|
||||
LLModalDialog::onClose(app_quiting);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLSetKeyBindDialog::draw()
|
||||
{
|
||||
LLRect local_rect;
|
||||
drawFrustum(local_rect, this, (LLView*)getDragHandle(), hasFocus());
|
||||
LLModalDialog::draw();
|
||||
}
|
||||
|
||||
void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_mask)
|
||||
{
|
||||
pParent = parent;
|
||||
setFrustumOrigin(parent);
|
||||
mKeyFilterMask = key_mask;
|
||||
|
||||
LLTextBase *text_ctrl = getChild<LLTextBase>("descritption");
|
||||
|
||||
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");
|
||||
}
|
||||
text_ctrl->setTextArg("[INPUT]", input);
|
||||
|
||||
bool can_ignore_masks = (key_mask & CAN_IGNORE_MASKS) != 0;
|
||||
pCheckBox->setVisible(can_ignore_masks);
|
||||
pCheckBox->setValue(false);
|
||||
}
|
||||
|
||||
BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask)
|
||||
{
|
||||
if ((key == 'Q' && mask == MASK_CONTROL)
|
||||
|| key == KEY_ESCAPE)
|
||||
{
|
||||
closeFloater();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (key == KEY_DELETE)
|
||||
{
|
||||
setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, 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;
|
||||
}
|
||||
|
||||
setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean());
|
||||
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->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 ignore)
|
||||
{
|
||||
if (pParent)
|
||||
{
|
||||
pParent->onSetKeyBind(click, key, mask, ignore);
|
||||
pParent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// global functions
|
||||
|
||||
|
|
@ -3248,11 +2947,11 @@ void LLPanelPreferenceControls::onModeCommit()
|
|||
}
|
||||
|
||||
// todo: copy onSetKeyBind to interface and inherit from interface
|
||||
void LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask)
|
||||
bool LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask)
|
||||
{
|
||||
if (!mConflictHandler[mEditingMode].canAssignControl(mEditingControl))
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( mEditingColumn > 0)
|
||||
|
|
@ -3261,6 +2960,7 @@ void LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MAS
|
|||
}
|
||||
|
||||
updateTable();
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLPanelPreferenceControls::onRestoreDefaults()
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llavatarpropertiesprocessor.h"
|
||||
#include "llconversationlog.h"
|
||||
#include "llsearcheditor.h"
|
||||
#include "llsetkeybinddialog.h"
|
||||
#include "llkeyconflict.h"
|
||||
|
||||
class LLConversationLogObserver;
|
||||
|
|
@ -285,7 +286,7 @@ private:
|
|||
LOG_CLASS(LLPanelPreferenceGraphics);
|
||||
};
|
||||
|
||||
class LLPanelPreferenceControls : public LLPanelPreference
|
||||
class LLPanelPreferenceControls : public LLPanelPreference, public LLKeyBindResponderInterface
|
||||
{
|
||||
LOG_CLASS(LLPanelPreferenceControls);
|
||||
public:
|
||||
|
|
@ -301,7 +302,7 @@ public:
|
|||
|
||||
void onListCommit();
|
||||
void onModeCommit();
|
||||
void onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask);
|
||||
bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore_mask);
|
||||
void onRestoreDefaults();
|
||||
void onDefaultKeyBind();
|
||||
void onCancelKeyBind();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "llkeyboard.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewerinput.h"
|
||||
#include "llviewermenu.h"
|
||||
#include "llxuiparser.h"
|
||||
//#include "llstring.h"
|
||||
|
||||
|
|
@ -170,6 +171,22 @@ bool LLKeyConflictHandler::canAssignControl(const std::string &control_name)
|
|||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask)
|
||||
{
|
||||
return gMenuBarView->hasAccelerator(key, mask) || gLoginMenuBarView->hasAccelerator(key, mask);
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data)
|
||||
{
|
||||
if (data.mMouse != CLICK_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return gMenuBarView->hasAccelerator(data.mKey, data.mMask) || 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())
|
||||
|
|
@ -186,6 +203,10 @@ bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32
|
|||
{
|
||||
return true;
|
||||
}
|
||||
if (isReservedByMenu(data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (removeConflicts(data, type_data.mConflictMask))
|
||||
{
|
||||
type_data.mKeyBind.replaceKeyData(data, index);
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ public:
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include "llbutton.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterpreference.h"
|
||||
#include "llpresetsmanager.h"
|
||||
#include "llsliderctrl.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,298 @@
|
|||
/**
|
||||
* @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 "llkeyboard.h"
|
||||
|
||||
#include "llbutton.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llfocusmgr.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;
|
||||
};
|
||||
|
||||
LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key)
|
||||
: LLModalDialog(key),
|
||||
pParent(NULL),
|
||||
mKeyFilterMask(DEFAULT_KEY_FILTER),
|
||||
pUpdater(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
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>("ignore_masks");
|
||||
|
||||
gFocusMgr.setKeystrokesOnly(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLSetKeyBindDialog::onClose(bool app_quiting)
|
||||
{
|
||||
if (pParent)
|
||||
{
|
||||
pParent->onCancelKeyBind();
|
||||
pParent = NULL;
|
||||
}
|
||||
if (pUpdater)
|
||||
{
|
||||
// Doubleclick timer has't fired, delete it
|
||||
delete pUpdater;
|
||||
pUpdater = NULL;
|
||||
}
|
||||
LLModalDialog::onClose(app_quiting);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLSetKeyBindDialog::draw()
|
||||
{
|
||||
LLRect local_rect;
|
||||
drawFrustum(local_rect, this, (LLView*)getDragHandle(), hasFocus());
|
||||
LLModalDialog::draw();
|
||||
}
|
||||
|
||||
void LLSetKeyBindDialog::setParent(LLPanelPreferenceControls* parent, U32 key_mask)
|
||||
{
|
||||
pParent = parent;
|
||||
setFrustumOrigin(parent);
|
||||
mKeyFilterMask = key_mask;
|
||||
|
||||
LLTextBase *text_ctrl = getChild<LLTextBase>("descritption");
|
||||
|
||||
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");
|
||||
}
|
||||
text_ctrl->setTextArg("[INPUT]", input);
|
||||
|
||||
bool can_ignore_masks = (key_mask & CAN_IGNORE_MASKS) != 0;
|
||||
pCheckBox->setVisible(can_ignore_masks);
|
||||
pCheckBox->setValue(false);
|
||||
}
|
||||
|
||||
BOOL LLSetKeyBindDialog::handleKeyHere(KEY key, MASK mask)
|
||||
{
|
||||
if ((key == 'Q' && mask == MASK_CONTROL)
|
||||
|| key == KEY_ESCAPE)
|
||||
{
|
||||
closeFloater();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (key == KEY_DELETE)
|
||||
{
|
||||
setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, 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;
|
||||
}
|
||||
|
||||
setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean());
|
||||
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->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 ignore)
|
||||
{
|
||||
if (pParent)
|
||||
{
|
||||
pParent->onSetKeyBind(click, key, mask, ignore);
|
||||
pParent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* @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"
|
||||
#include "lldrawfrustum.h"
|
||||
|
||||
class LLCheckBoxCtrl;
|
||||
|
||||
// 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 CAN_IGNORE_MASKS = 32; // For example W (aka Forward) should work regardless of SHIFT being pressed
|
||||
static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASK_KEYS | CAN_IGNORE_MASKS;
|
||||
|
||||
|
||||
class LLKeyBindResponderInterface
|
||||
{
|
||||
public:
|
||||
virtual ~LLKeyBindResponderInterface();
|
||||
|
||||
virtual void onCancelKeyBind();
|
||||
virtual void onDefaultKeyBind();
|
||||
// returns true if parent failed to set key due to key being in use
|
||||
virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore);
|
||||
};
|
||||
|
||||
class LLSetKeyBindDialog : public LLModalDialog, public LLDrawFrustum
|
||||
{
|
||||
public:
|
||||
LLSetKeyBindDialog(const LLSD& key);
|
||||
~LLSetKeyBindDialog();
|
||||
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void onClose(bool app_quiting);
|
||||
/*virtual*/ void draw();
|
||||
|
||||
void setParent(LLKeyBindResponderInterface* parent, U32 key_mask = DEFAULT_KEY_FILTER);
|
||||
|
||||
BOOL handleKeyHere(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:
|
||||
void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool ignore);
|
||||
LLKeyBindResponderInterface* pParent;
|
||||
LLCheckBoxCtrl* pCheckBox;
|
||||
|
||||
U32 mKeyFilterMask;
|
||||
Updater *pUpdater;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLSETKEYBINDDIALOG_H
|
||||
|
|
@ -106,7 +106,6 @@
|
|||
//#include "llfirstuse.h"
|
||||
#include "llfloaterhud.h"
|
||||
#include "llfloaterland.h"
|
||||
#include "llfloaterpreference.h"
|
||||
#include "llfloatertopobjects.h"
|
||||
#include "llfloaterworldmap.h"
|
||||
#include "llgesturemgr.h"
|
||||
|
|
|
|||
Loading…
Reference in New Issue