summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llmenugl.cpp21
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llfloaterpreference.cpp306
-rw-r--r--indra/newview/llfloaterpreference.h5
-rw-r--r--indra/newview/llkeyconflict.cpp21
-rw-r--r--indra/newview/llkeyconflict.h2
-rw-r--r--indra/newview/llpanelpresetspulldown.cpp1
-rw-r--r--indra/newview/llsetkeybinddialog.cpp298
-rw-r--r--indra/newview/llsetkeybinddialog.h88
-rw-r--r--indra/newview/llstartup.cpp1
11 files changed, 440 insertions, 307 deletions
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index c266bec777..d97bf2d674 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3536,6 +3536,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()
{
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index b47b6a5214..adcb2ca2f9 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -795,6 +795,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 );
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 340f1f8a22..111aefe186 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -558,6 +558,7 @@ set(viewer_SOURCE_FILES
llsecapi.cpp
llsechandler_basic.cpp
llselectmgr.cpp
+ llsetkeybinddialog.cpp
llsettingspicker.cpp
llsettingsvo.cpp
llshareavatarhandler.cpp
@@ -1181,6 +1182,7 @@ set(viewer_HEADER_FILES
llsecapi.h
llsechandler_basic.h
llselectmgr.h
+ llsetkeybinddialog.h
llsettingspicker.h
llsettingsvo.h
llsidepanelappearance.h
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 3668f71feb..e71c7d58e2 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -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
@@ -3197,11 +2896,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)
@@ -3210,6 +2909,7 @@ void LLPanelPreferenceControls::onSetKeyBind(EMouseClickType click, KEY key, MAS
}
updateTable();
+ return true;
}
void LLPanelPreferenceControls::onRestoreDefaults()
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 90697341cb..9c4f6fad46 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -37,6 +37,7 @@
#include "llavatarpropertiesprocessor.h"
#include "llconversationlog.h"
#include "llsearcheditor.h"
+#include "llsetkeybinddialog.h"
#include "llkeyconflict.h"
class LLConversationLogObserver;
@@ -286,7 +287,7 @@ private:
LOG_CLASS(LLPanelPreferenceGraphics);
};
-class LLPanelPreferenceControls : public LLPanelPreference
+class LLPanelPreferenceControls : public LLPanelPreference, public LLKeyBindResponderInterface
{
LOG_CLASS(LLPanelPreferenceControls);
public:
@@ -302,7 +303,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();
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index 01230ea26a..bad4e4a2d8 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -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);
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index e339264aaa..5c3b860ec6 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -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);
diff --git a/indra/newview/llpanelpresetspulldown.cpp b/indra/newview/llpanelpresetspulldown.cpp
index aa5ba3f210..8a3bcf7172 100644
--- a/indra/newview/llpanelpresetspulldown.cpp
+++ b/indra/newview/llpanelpresetspulldown.cpp
@@ -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"
diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp
new file mode 100644
index 0000000000..0ad71cb372
--- /dev/null
+++ b/indra/newview/llsetkeybinddialog.cpp
@@ -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;
+ }
+}
+
diff --git a/indra/newview/llsetkeybinddialog.h b/indra/newview/llsetkeybinddialog.h
new file mode 100644
index 0000000000..fb3b2a2269
--- /dev/null
+++ b/indra/newview/llsetkeybinddialog.h
@@ -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
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 1be1c4ba96..d44c81d1a4 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -108,7 +108,6 @@
//#include "llfirstuse.h"
#include "llfloaterhud.h"
#include "llfloaterland.h"
-#include "llfloaterpreference.h"
#include "llfloatertopobjects.h"
#include "llfloaterworldmap.h"
#include "llgesturemgr.h"