123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- /**
- * @file llfocusmgr.cpp
- * @brief LLFocusMgr base class
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "lluictrl.h" // Also includes llfocusmgr.h
- #include "llcolor4.h"
- constexpr F32 FOCUS_FADE_TIME = 0.3f;
- LLFocusMgr gFocusMgr;
- ///////////////////////////////////////////////////////////////////////////////
- // LLFocusableElement class
- ///////////////////////////////////////////////////////////////////////////////
- LLFocusableElement::LLFocusableElement()
- : mFocusLostCallback(NULL),
- mFocusReceivedCallback(NULL),
- mFocusChangedCallback(NULL),
- mFocusCallbackUserData(NULL)
- {
- }
- void LLFocusableElement::setFocusLostCallback(void (*cb)(LLFocusableElement*,
- void*),
- void* user_data)
- {
- mFocusLostCallback = cb;
- mFocusCallbackUserData = user_data;
- }
- void LLFocusableElement::setFocusReceivedCallback(void (*cb)(LLFocusableElement*,
- void*),
- void* user_data)
- {
- mFocusReceivedCallback = cb;
- mFocusCallbackUserData = user_data;
- }
- void LLFocusableElement::setFocusChangedCallback(void (*cb)(LLFocusableElement*,
- void*),
- void* user_data)
- {
- mFocusChangedCallback = cb;
- mFocusCallbackUserData = user_data;
- }
- void LLFocusableElement::onFocusReceived()
- {
- if (mFocusReceivedCallback)
- {
- mFocusReceivedCallback(this, mFocusCallbackUserData);
- }
- if (mFocusChangedCallback)
- {
- mFocusChangedCallback(this, mFocusCallbackUserData);
- }
- }
- void LLFocusableElement::onFocusLost()
- {
- if (mFocusLostCallback)
- {
- mFocusLostCallback(this, mFocusCallbackUserData);
- }
- if (mFocusChangedCallback)
- {
- mFocusChangedCallback(this, mFocusCallbackUserData);
- }
- }
- bool LLFocusableElement::hasFocus() const
- {
- return gFocusMgr.getKeyboardFocus() == this;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLFocusMgr class
- ///////////////////////////////////////////////////////////////////////////////
- LLFocusMgr::LLFocusMgr()
- : mLockedView(NULL),
- mMouseCaptor(NULL),
- mKeyboardFocus(NULL),
- mLastKeyboardFocus(NULL),
- mDefaultKeyboardFocus(NULL),
- mKeystrokesOnly(false),
- mTopCtrl(NULL),
- mFocusWeight(0.f),
- mFocusColor(LLColor4::white),
- #if LL_DEBUG
- mMouseCaptorName("none"),
- mKeyboardFocusName("none"),
- mTopCtrlName("none"),
- #endif
- // macOS does not seem to notify us that we have gotten focus, so default
- // to true
- mAppHasFocus(true)
- {
- }
- LLFocusMgr::~LLFocusMgr()
- {
- mFocusHistory.clear();
- }
- void LLFocusMgr::releaseFocusIfNeeded(const LLView* viewp)
- {
- if (childHasMouseCapture(viewp))
- {
- setMouseCapture(NULL);
- }
- if (childHasKeyboardFocus(viewp))
- {
- if (viewp == mLockedView)
- {
- mLockedView = NULL;
- setKeyboardFocus(NULL);
- }
- else
- {
- setKeyboardFocus(mLockedView, false, mKeystrokesOnly);
- }
- }
- if (childIsTopCtrl(viewp))
- {
- setTopCtrl(NULL);
- }
- }
- LLUICtrl* LLFocusMgr::getKeyboardFocusUICtrl()
- {
- if (mKeyboardFocus && mKeyboardFocus->isFocusableCtrl())
- {
- return (LLUICtrl*)mKeyboardFocus;
- }
- return NULL;
- }
- LLUICtrl* LLFocusMgr::getLastKeyboardFocusUICtrl()
- {
- if (mLastKeyboardFocus && mLastKeyboardFocus->isFocusableCtrl())
- {
- return (LLUICtrl*)mLastKeyboardFocus;
- }
- return NULL;
- }
- void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focusp,
- bool lock, bool keystrokes_only)
- {
- // When locked, do not allow focus to go to anything that is not the locked
- // focus or one of its descendants
- if (mLockedView)
- {
- if (!new_focusp)
- {
- return;
- }
- if (new_focusp != mLockedView)
- {
- LLView* viewp = dynamic_cast<LLView*>(new_focusp);
- if (!viewp || !viewp->hasAncestor(mLockedView))
- {
- return;
- }
- }
- }
- mKeystrokesOnly = keystrokes_only;
- if (LLView::sDebugKeys)
- {
- llinfos << "mKeystrokesOnly = " << mKeystrokesOnly << llendl;
- }
- if (new_focusp != mKeyboardFocus)
- {
- mLastKeyboardFocus = mKeyboardFocus;
- mKeyboardFocus = new_focusp;
- if (mLastKeyboardFocus)
- {
- mLastKeyboardFocus->onFocusLost();
- }
- // Clear out any existing flash
- if (new_focusp)
- {
- mFocusWeight = 0.f;
- new_focusp->onFocusReceived();
- }
- mFocusTimer.reset();
- #if LL_DEBUG
- LLUICtrl* ctrlp = NULL;
- if (new_focusp && new_focusp->isFocusableCtrl())
- {
- ctrlp = (LLUICtrl*)new_focusp;
- }
- mKeyboardFocusName = ctrlp ? ctrlp->getName() : std::string("none");
- #endif
- // If we have got a default keyboard focus, and the caller is releasing
- // keyboard focus, move to the default.
- if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL)
- {
- mDefaultKeyboardFocus->setFocus(true);
- }
- LLView* focused_viewp = dynamic_cast<LLView*>(mKeyboardFocus);
- LLView* focus_subtreep = focused_viewp;
- LLView* viewp = focus_subtreep;
- // Find root-most focus root
- while (viewp)
- {
- if (viewp->isFocusRoot())
- {
- focus_subtreep = viewp;
- }
- viewp = viewp->getParent();
- }
- if (focus_subtreep)
- {
- mFocusHistory[focus_subtreep->getHandle()] =
- focused_viewp ? focused_viewp->getHandle()
- : LLHandle<LLView>();
- }
- }
- if (lock)
- {
- lockFocus();
- }
- }
- // Returns true is parent or any descedent of parent has keyboard focus.
- bool LLFocusMgr::childHasKeyboardFocus(const LLView* parentp) const
- {
- LLView* focus_viewp = dynamic_cast<LLView*>(mKeyboardFocus);
- while (focus_viewp)
- {
- if (focus_viewp == parentp)
- {
- return true;
- }
- focus_viewp = focus_viewp->getParent();
- }
- return false;
- }
- // Returns true is parent or any descedent of parent is the mouse captor.
- bool LLFocusMgr::childHasMouseCapture(const LLView* parentp) const
- {
- if (mMouseCaptor && mMouseCaptor->isView())
- {
- LLView* captor_viewp = (LLView*)mMouseCaptor;
- while (captor_viewp)
- {
- if (captor_viewp == parentp)
- {
- return true;
- }
- captor_viewp = captor_viewp->getParent();
- }
- }
- return false;
- }
- void LLFocusMgr::removeKeyboardFocusWithoutCallback(const LLFocusableElement* focusp)
- {
- // should be ok to unlock here, as you have to know the locked view
- // in order to unlock it
- if (mLockedView == focusp)
- {
- mLockedView = NULL;
- }
- if (mKeyboardFocus == focusp)
- {
- mKeyboardFocus = NULL;
- #if LL_DEBUG
- mKeyboardFocusName = "none";
- #endif
- }
- }
- void LLFocusMgr::setMouseCapture(LLMouseHandler* new_captorp)
- {
- #if 0
- if (mFocusLocked)
- {
- return;
- }
- #endif
- if (new_captorp != mMouseCaptor)
- {
- LLMouseHandler* old_captorp = mMouseCaptor;
- mMouseCaptor = new_captorp;
- if (old_captorp)
- {
- old_captorp->onMouseCaptureLost();
- }
- #if LL_DEBUG
- mMouseCaptorName = new_captorp ? new_captorp->getName()
- : std::string("none");
- #endif
- }
- }
- void LLFocusMgr::removeMouseCaptureWithoutCallback(const LLMouseHandler* captorp)
- {
- #if 0
- if (mFocusLocked)
- {
- return;
- }
- #endif
- if (mMouseCaptor == captorp)
- {
- mMouseCaptor = NULL;
- #if LL_DEBUG
- mMouseCaptorName = "none";
- #endif
- }
- }
- bool LLFocusMgr::childIsTopCtrl(const LLView* parentp) const
- {
- LLView* top_viewp = (LLView*)mTopCtrl;
- while (top_viewp)
- {
- if (top_viewp == parentp)
- {
- return true;
- }
- top_viewp = top_viewp->getParent();
- }
- return false;
- }
- // Set ctrlp = NULL to release top_view.
- void LLFocusMgr::setTopCtrl(LLUICtrl* ctrlp)
- {
- LLUICtrl* old_topp = mTopCtrl;
- if (ctrlp != old_topp)
- {
- mTopCtrl = ctrlp;
- #if LL_DEBUG
- mTopCtrlName = ctrlp ? ctrlp->getName() : std::string("none");
- #endif
- if (old_topp)
- {
- old_topp->onLostTop();
- }
- }
- }
- void LLFocusMgr::removeTopCtrlWithoutCallback(const LLUICtrl* ctrlp)
- {
- if (mTopCtrl == ctrlp)
- {
- mTopCtrl = NULL;
- #if LL_DEBUG
- mTopCtrlName = "none";
- #endif
- }
- }
- void LLFocusMgr::lockFocus()
- {
- if (mKeyboardFocus && mKeyboardFocus->isFocusableCtrl())
- {
- mLockedView = (LLUICtrl*)mKeyboardFocus;
- }
- else
- {
- mLockedView = NULL;
- }
- }
- F32 LLFocusMgr::getFocusFlashAmt() const
- {
- return clamp_rescale(getFocusTime(), 0.f, FOCUS_FADE_TIME, mFocusWeight,
- 0.f);
- }
- LLColor4 LLFocusMgr::getFocusColor() const
- {
- LLColor4 focus_color = lerp(mFocusColor, LLColor4::white,
- getFocusFlashAmt());
- // De-emphasize keyboard focus when app has lost focus (to avoid typing
- // into wrong window problem)
- if (!mAppHasFocus)
- {
- focus_color.mV[VALPHA] *= 0.4f;
- }
- return focus_color;
- }
- void LLFocusMgr::triggerFocusFlash()
- {
- mFocusTimer.reset();
- mFocusWeight = 1.f;
- }
- void LLFocusMgr::setAppHasFocus(bool focus)
- {
- if (!mAppHasFocus && focus)
- {
- triggerFocusFlash();
- }
- // Release focus from "top ctrl"s, which generally hides them
- if (!focus && mTopCtrl)
- {
- setTopCtrl(NULL);
- }
- mAppHasFocus = focus;
- }
- LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* viewp) const
- {
- if (viewp)
- {
- focus_history_map_t::const_iterator it =
- mFocusHistory.find(viewp->getHandle());
- if (it != mFocusHistory.end())
- {
- // Found last focus for this subtree
- return (LLUICtrl*)it->second.get();
- }
- }
- return NULL;
- }
- void LLFocusMgr::clearLastFocusForGroup(LLView* viewp)
- {
- if (viewp)
- {
- mFocusHistory.erase(viewp->getHandle());
- }
- }
|