/** * @file llfocusmgr.cpp * @brief LLFocusMgr base class * * Copyright (c) 2002-2007, Linden Research, Inc. * * 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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. */ #include "linden_common.h" #include "llfocusmgr.h" #include "lluictrl.h" #include "v4color.h" const F32 FOCUS_FADE_TIME = 0.3f; LLFocusMgr gFocusMgr; LLFocusMgr::LLFocusMgr() : mLockedView( NULL ), mKeyboardLockedFocusLostCallback( NULL ), mMouseCaptor( NULL ), mMouseCaptureLostCallback( NULL ), mKeyboardFocus( NULL ), mDefaultKeyboardFocus( NULL ), mKeyboardFocusLostCallback( NULL ), mTopView( NULL ), mTopViewLostCallback( NULL ), mFocusWeight(0.f), mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true #ifdef _DEBUG , mMouseCaptorName("none") , mKeyboardFocusName("none") , mTopViewName("none") #endif { } LLFocusMgr::~LLFocusMgr() { mFocusHistory.clear(); } void LLFocusMgr::releaseFocusIfNeeded( LLView* view ) { if( childHasMouseCapture( view ) ) { setMouseCapture( NULL, NULL ); } if( childHasKeyboardFocus( view )) { if (view == mLockedView) { mLockedView = NULL; mKeyboardLockedFocusLostCallback = NULL; setKeyboardFocus( NULL, NULL ); } else { setKeyboardFocus( mLockedView, mKeyboardLockedFocusLostCallback ); } } if( childIsTopView( view ) ) { setTopView( NULL, NULL ); } } void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focus_lost, BOOL lock) { if (mLockedView && (new_focus == NULL || (new_focus != mLockedView && !new_focus->hasAncestor(mLockedView)))) { // don't allow focus to go to anything that is not the locked focus // or one of its descendants return; } FocusLostCallback old_callback = mKeyboardFocusLostCallback; mKeyboardFocusLostCallback = on_focus_lost; //llinfos << "Keyboard focus handled by " << (new_focus ? new_focus->getName() : "nothing") << llendl; if( new_focus != mKeyboardFocus ) { LLUICtrl* old_focus = mKeyboardFocus; mKeyboardFocus = new_focus; // clear out any existing flash if (new_focus) { mFocusWeight = 0.f; } mFocusTimer.reset(); if( old_callback ) { old_callback( old_focus ); } #ifdef _DEBUG mKeyboardFocusName = new_focus ? new_focus->getName() : "none"; #endif // If we've got a default keyboard focus, and the caller is // releasing keyboard focus, move to the default. if (mDefaultKeyboardFocus != NULL && new_focus == NULL) { mDefaultKeyboardFocus->setFocus(TRUE); } LLView* focus_subtree = new_focus; LLView* viewp = new_focus; // find root-most focus root while(viewp) { if (viewp->isFocusRoot()) { focus_subtree = viewp; } viewp = viewp->getParent(); } if (focus_subtree) { mFocusHistory[focus_subtree->mViewHandle] = new_focus ? new_focus->mViewHandle : LLViewHandle::sDeadHandle; } } if (lock) { mLockedView = new_focus; mKeyboardLockedFocusLostCallback = on_focus_lost; } } void LLFocusMgr::setDefaultKeyboardFocus(LLUICtrl* default_focus) { mDefaultKeyboardFocus = default_focus; } // Returns TRUE is parent or any descedent of parent has keyboard focus. BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const { LLView* focus_view = mKeyboardFocus; while( focus_view ) { if( focus_view == parent ) { return TRUE; } focus_view = focus_view->getParent(); } return FALSE; } // Returns TRUE is parent or any descedent of parent is the mouse captor. BOOL LLFocusMgr::childHasMouseCapture( LLView* parent ) { if( mMouseCaptor && mMouseCaptor->isView() ) { LLView* captor_view = (LLView*)mMouseCaptor; while( captor_view ) { if( captor_view == parent ) { return TRUE; } captor_view = captor_view->getParent(); } } return FALSE; } void LLFocusMgr::removeKeyboardFocusWithoutCallback( LLView* focus ) { // should be ok to unlock here, as you have to know the locked view // in order to unlock it if (focus == mLockedView) { mLockedView = NULL; mKeyboardLockedFocusLostCallback = NULL; } if( mKeyboardFocus == focus ) { mKeyboardFocus = NULL; mKeyboardFocusLostCallback = NULL; #ifdef _DEBUG mKeyboardFocusName = "none"; #endif } } void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor, void (*on_capture_lost)(LLMouseHandler* old_captor) ) { //if (mFocusLocked) //{ // return; //} void (*old_callback)(LLMouseHandler*) = mMouseCaptureLostCallback; mMouseCaptureLostCallback = on_capture_lost; if( new_captor != mMouseCaptor ) { LLMouseHandler* old_captor = mMouseCaptor; mMouseCaptor = new_captor; /* if (new_captor) { if ( new_captor->getName() == "Stickto") { llinfos << "New mouse captor: " << new_captor->getName() << llendl; } else { llinfos << "New mouse captor: " << new_captor->getName() << llendl; } } else { llinfos << "New mouse captor: NULL" << llendl; } */ if( old_callback ) { old_callback( old_captor ); } #ifdef _DEBUG mMouseCaptorName = new_captor ? new_captor->getName() : "none"; #endif } } void LLFocusMgr::removeMouseCaptureWithoutCallback( LLMouseHandler* captor ) { //if (mFocusLocked) //{ // return; //} if( mMouseCaptor == captor ) { mMouseCaptor = NULL; mMouseCaptureLostCallback = NULL; #ifdef _DEBUG mMouseCaptorName = "none"; #endif } } BOOL LLFocusMgr::childIsTopView( LLView* parent ) { LLView* top_view = mTopView; while( top_view ) { if( top_view == parent ) { return TRUE; } top_view = top_view->getParent(); } return FALSE; } // set new_top = NULL to release top_view. void LLFocusMgr::setTopView( LLView* new_top, void (*on_top_lost)(LLView* old_top) ) { void (*old_callback)(LLView*) = mTopViewLostCallback; mTopViewLostCallback = on_top_lost; if( new_top != mTopView ) { LLView* old_top = mTopView; mTopView = new_top; if( old_callback ) { old_callback( old_top ); } mTopView = new_top; #ifdef _DEBUG mTopViewName = new_top ? new_top->getName() : "none"; #endif } } void LLFocusMgr::removeTopViewWithoutCallback( LLView* top_view ) { if( mTopView == top_view ) { mTopView = NULL; mTopViewLostCallback = NULL; #ifdef _DEBUG mTopViewName = "none"; #endif } } void LLFocusMgr::unlockFocus() { mLockedView = NULL; mKeyboardLockedFocusLostCallback = NULL; } F32 LLFocusMgr::getFocusFlashAmt() { return clamp_rescale(getFocusTime(), 0.f, FOCUS_FADE_TIME, mFocusWeight, 0.f); } LLColor4 LLFocusMgr::getFocusColor() { LLColor4 focus_color = lerp(LLUI::sColorsGroup->getColor( "FocusColor" ), 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(); } mAppHasFocus = focus; } LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) { if (subtree_root) { focus_history_map_t::iterator found_it = mFocusHistory.find(subtree_root->mViewHandle); if (found_it != mFocusHistory.end()) { // found last focus for this subtree return static_cast(LLView::getViewByHandle(found_it->second)); } } return NULL; } void LLFocusMgr::clearLastFocusForGroup(LLView* subtree_root) { if (subtree_root) { mFocusHistory.erase(subtree_root->mViewHandle); } }