llfocusmgr.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:12k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfocusmgr.cpp
  3.  * @brief LLFocusMgr base class
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llfocusmgr.h"
  34. #include "lluictrl.h"
  35. #include "v4color.h"
  36. const F32 FOCUS_FADE_TIME = 0.3f;
  37. // NOTE: the LLFocusableElement implementation has been moved here from lluictrl.cpp.
  38. LLFocusableElement::LLFocusableElement()
  39. : mFocusLostCallback(NULL),
  40. mFocusReceivedCallback(NULL),
  41. mFocusChangedCallback(NULL),
  42. mTopLostCallback(NULL)
  43. {
  44. }
  45. // virtual
  46. BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent)
  47. {
  48. return FALSE;
  49. }
  50. // virtual
  51. BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
  52. {
  53. return FALSE;
  54. }
  55. // virtual
  56. LLFocusableElement::~LLFocusableElement()
  57. {
  58. delete mFocusLostCallback;
  59. delete mFocusReceivedCallback;
  60. delete mFocusChangedCallback;
  61. delete mTopLostCallback;
  62. }
  63. void LLFocusableElement::onFocusReceived()
  64. {
  65. if (mFocusReceivedCallback) (*mFocusReceivedCallback)(this);
  66. if (mFocusChangedCallback) (*mFocusChangedCallback)(this);
  67. }
  68. void LLFocusableElement::onFocusLost()
  69. {
  70. if (mFocusLostCallback) (*mFocusLostCallback)(this);
  71. if (mFocusChangedCallback) (*mFocusChangedCallback)(this);
  72. }
  73. void LLFocusableElement::onTopLost()
  74. {
  75. if (mTopLostCallback) (*mTopLostCallback)(this);
  76. }
  77. BOOL LLFocusableElement::hasFocus() const
  78. {
  79. return gFocusMgr.getKeyboardFocus() == this;
  80. }
  81. void LLFocusableElement::setFocus(BOOL b)
  82. {
  83. }
  84. boost::signals2::connection LLFocusableElement::setFocusLostCallback( const focus_signal_t::slot_type& cb)
  85. if (!mFocusLostCallback) mFocusLostCallback = new focus_signal_t();
  86. return mFocusLostCallback->connect(cb);
  87. }
  88. boost::signals2::connection LLFocusableElement::setFocusReceivedCallback(const focus_signal_t::slot_type& cb)
  89. if (!mFocusReceivedCallback) mFocusReceivedCallback = new focus_signal_t();
  90. return mFocusReceivedCallback->connect(cb);
  91. }
  92. boost::signals2::connection LLFocusableElement::setFocusChangedCallback(const focus_signal_t::slot_type& cb)
  93. {
  94. if (!mFocusChangedCallback) mFocusChangedCallback = new focus_signal_t();
  95. return mFocusChangedCallback->connect(cb);
  96. }
  97. boost::signals2::connection LLFocusableElement::setTopLostCallback(const focus_signal_t::slot_type& cb)
  98. if (!mTopLostCallback) mTopLostCallback = new focus_signal_t();
  99. return mTopLostCallback->connect(cb);
  100. }
  101. LLFocusMgr gFocusMgr;
  102. LLFocusMgr::LLFocusMgr()
  103. :
  104. mLockedView( NULL ),
  105. mMouseCaptor( NULL ),
  106. mKeyboardFocus( NULL ),
  107. mLastKeyboardFocus( NULL ),
  108. mDefaultKeyboardFocus( NULL ),
  109. mKeystrokesOnly(FALSE),
  110. mTopCtrl( NULL ),
  111. mAppHasFocus(TRUE)   // Macs don't seem to notify us that we've gotten focus, so default to true
  112. #ifdef _DEBUG
  113. , mMouseCaptorName("none")
  114. , mKeyboardFocusName("none")
  115. , mTopCtrlName("none")
  116. #endif
  117. {
  118. }
  119. void LLFocusMgr::releaseFocusIfNeeded( const LLView* view )
  120. {
  121. if( childHasMouseCapture( view ) )
  122. {
  123. setMouseCapture( NULL );
  124. }
  125. if( childHasKeyboardFocus( view ))
  126. {
  127. if (view == mLockedView)
  128. {
  129. mLockedView = NULL;
  130. setKeyboardFocus( NULL );
  131. }
  132. else
  133. {
  134. setKeyboardFocus( mLockedView );
  135. }
  136. }
  137. if( childIsTopCtrl( view ) )
  138. {
  139. setTopCtrl( NULL );
  140. }
  141. }
  142. void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only)
  143. {
  144. // notes if keyboard focus is changed again (by onFocusLost/onFocusReceived)
  145.     // making the rest of our processing unnecessary since it will already be
  146.     // handled by the recursive call
  147. static bool focus_dirty;
  148. focus_dirty = false;
  149. if (mLockedView && 
  150. (new_focus == NULL || 
  151. (new_focus != mLockedView 
  152. && dynamic_cast<LLView*>(new_focus)
  153. && !dynamic_cast<LLView*>(new_focus)->hasAncestor(mLockedView))))
  154. {
  155. // don't allow focus to go to anything that is not the locked focus
  156. // or one of its descendants
  157. return;
  158. }
  159. mKeystrokesOnly = keystrokes_only;
  160. if( new_focus != mKeyboardFocus )
  161. {
  162. mLastKeyboardFocus = mKeyboardFocus;
  163. mKeyboardFocus = new_focus;
  164. // list of the focus and it's ancestors
  165. view_handle_list_t old_focus_list = mCachedKeyboardFocusList;
  166. view_handle_list_t new_focus_list;
  167. // walk up the tree to root and add all views to the new_focus_list
  168. for (LLView* ctrl = dynamic_cast<LLView*>(mKeyboardFocus); ctrl; ctrl = ctrl->getParent())
  169. {
  170. new_focus_list.push_back(ctrl->getHandle());
  171. }
  172. // remove all common ancestors since their focus is unchanged
  173. while (!new_focus_list.empty() &&
  174.    !old_focus_list.empty() &&
  175.    new_focus_list.back() == old_focus_list.back())
  176. {
  177. new_focus_list.pop_back();
  178. old_focus_list.pop_back();
  179. }
  180. // walk up the old focus branch calling onFocusLost
  181. // we bubble up the tree to release focus, and back down to add
  182. for (view_handle_list_t::iterator old_focus_iter = old_focus_list.begin();
  183.  old_focus_iter != old_focus_list.end() && !focus_dirty;
  184.  old_focus_iter++)
  185. {
  186. LLView* old_focus_view = old_focus_iter->get();
  187. if (old_focus_view)
  188. {
  189. mCachedKeyboardFocusList.pop_front();
  190. old_focus_view->onFocusLost();
  191. }
  192. }
  193. // walk down the new focus branch calling onFocusReceived
  194. for (view_handle_list_t::reverse_iterator new_focus_riter = new_focus_list.rbegin();
  195.  new_focus_riter != new_focus_list.rend() && !focus_dirty;
  196.  new_focus_riter++)
  197. {
  198. LLView* new_focus_view = new_focus_riter->get();
  199. if (new_focus_view)
  200. {
  201.                 mCachedKeyboardFocusList.push_front(new_focus_view->getHandle());
  202. new_focus_view->onFocusReceived();
  203. }
  204. }
  205. // if focus was changed as part of an onFocusLost or onFocusReceived call
  206. // stop iterating on current list since it is now invalid
  207. if (focus_dirty)
  208. {
  209. return;
  210. }
  211. #ifdef _DEBUG
  212. LLUICtrl* focus_ctrl = dynamic_cast<LLUICtrl*>(new_focus);
  213. mKeyboardFocusName = focus_ctrl ? focus_ctrl->getName() : std::string("none");
  214. #endif
  215. // If we've got a default keyboard focus, and the caller is
  216. // releasing keyboard focus, move to the default.
  217. if (mDefaultKeyboardFocus != NULL && mKeyboardFocus == NULL)
  218. {
  219. mDefaultKeyboardFocus->setFocus(TRUE);
  220. }
  221. LLView* focus_subtree = dynamic_cast<LLView*>(mKeyboardFocus);
  222. LLView* viewp = dynamic_cast<LLView*>(mKeyboardFocus);
  223. // find root-most focus root
  224. while(viewp)
  225. {
  226. if (viewp->isFocusRoot())
  227. {
  228. focus_subtree = viewp;
  229. }
  230. viewp = viewp->getParent();
  231. }
  232. if (focus_subtree)
  233. {
  234. LLView* focused_view = dynamic_cast<LLView*>(mKeyboardFocus);
  235. mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle<LLView>(); 
  236. }
  237. }
  238. if (lock)
  239. {
  240. lockFocus();
  241. }
  242. focus_dirty = true;
  243. }
  244. // Returns TRUE is parent or any descedent of parent has keyboard focus.
  245. BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const
  246. {
  247. LLView* focus_view = dynamic_cast<LLView*>(mKeyboardFocus);
  248. while( focus_view )
  249. {
  250. if( focus_view == parent )
  251. {
  252. return TRUE;
  253. }
  254. focus_view = focus_view->getParent();
  255. }
  256. return FALSE;
  257. }
  258. // Returns TRUE is parent or any descedent of parent is the mouse captor.
  259. BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const
  260. {
  261. if( mMouseCaptor && dynamic_cast<LLView*>(mMouseCaptor) != NULL )
  262. {
  263. LLView* captor_view = (LLView*)mMouseCaptor;
  264. while( captor_view )
  265. {
  266. if( captor_view == parent )
  267. {
  268. return TRUE;
  269. }
  270. captor_view = captor_view->getParent();
  271. }
  272. }
  273. return FALSE;
  274. }
  275. void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus )
  276. {
  277. // should be ok to unlock here, as you have to know the locked view
  278. // in order to unlock it
  279. if (focus == mLockedView)
  280. {
  281. mLockedView = NULL;
  282. }
  283. if( mKeyboardFocus == focus )
  284. {
  285. mKeyboardFocus = NULL;
  286. #ifdef _DEBUG
  287. mKeyboardFocusName = std::string("none");
  288. #endif
  289. }
  290. }
  291. void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor )
  292. {
  293. //if (mFocusLocked)
  294. //{
  295. // return;
  296. //}
  297. if( new_captor != mMouseCaptor )
  298. {
  299. LLMouseHandler* old_captor = mMouseCaptor;
  300. mMouseCaptor = new_captor;
  301. if (LLView::sDebugMouseHandling)
  302. {
  303. if (new_captor)
  304. {
  305. llinfos << "New mouse captor: " << new_captor->getName() << llendl;
  306. }
  307. else
  308. {
  309. llinfos << "New mouse captor: NULL" << llendl;
  310. }
  311. }
  312. if( old_captor )
  313. {
  314. old_captor->onMouseCaptureLost();
  315. }
  316. #ifdef _DEBUG
  317. mMouseCaptorName = new_captor ? new_captor->getName() : std::string("none");
  318. #endif
  319. }
  320. }
  321. void LLFocusMgr::removeMouseCaptureWithoutCallback( const LLMouseHandler* captor )
  322. {
  323. //if (mFocusLocked)
  324. //{
  325. // return;
  326. //}
  327. if( mMouseCaptor == captor )
  328. {
  329. mMouseCaptor = NULL;
  330. #ifdef _DEBUG
  331. mMouseCaptorName = std::string("none");
  332. #endif
  333. }
  334. }
  335. BOOL LLFocusMgr::childIsTopCtrl( const LLView* parent ) const
  336. {
  337. LLView* top_view = (LLView*)mTopCtrl;
  338. while( top_view )
  339. {
  340. if( top_view == parent )
  341. {
  342. return TRUE;
  343. }
  344. top_view = top_view->getParent();
  345. }
  346. return FALSE;
  347. }
  348. // set new_top = NULL to release top_view.
  349. void LLFocusMgr::setTopCtrl( LLUICtrl* new_top  )
  350. {
  351. LLUICtrl* old_top = mTopCtrl;
  352. if( new_top != old_top )
  353. {
  354. mTopCtrl = new_top;
  355. #ifdef _DEBUG
  356. mTopCtrlName = new_top ? new_top->getName() : std::string("none");
  357. #endif
  358. if (old_top)
  359. {
  360. old_top->onTopLost();
  361. }
  362. }
  363. }
  364. void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view )
  365. {
  366. if( mTopCtrl == top_view )
  367. {
  368. mTopCtrl = NULL;
  369. #ifdef _DEBUG
  370. mTopCtrlName = std::string("none");
  371. #endif
  372. }
  373. }
  374. void LLFocusMgr::lockFocus()
  375. {
  376. mLockedView = dynamic_cast<LLUICtrl*>(mKeyboardFocus); 
  377. }
  378. void LLFocusMgr::unlockFocus()
  379. {
  380. mLockedView = NULL; 
  381. }
  382. F32 LLFocusMgr::getFocusFlashAmt() const
  383. {
  384. return clamp_rescale(mFocusFlashTimer.getElapsedTimeF32(), 0.f, FOCUS_FADE_TIME, 1.f, 0.f);
  385. }
  386. LLColor4 LLFocusMgr::getFocusColor() const
  387. {
  388. static LLUIColor focus_color_cached = LLUIColorTable::instance().getColor("FocusColor");
  389. LLColor4 focus_color = lerp(focus_color_cached, LLColor4::white, getFocusFlashAmt());
  390. // de-emphasize keyboard focus when app has lost focus (to avoid typing into wrong window problem)
  391. if (!mAppHasFocus)
  392. {
  393. focus_color.mV[VALPHA] *= 0.4f;
  394. }
  395. return focus_color;
  396. }
  397. void LLFocusMgr::triggerFocusFlash()
  398. {
  399. mFocusFlashTimer.reset();
  400. }
  401. void LLFocusMgr::setAppHasFocus(BOOL focus) 
  402. if (!mAppHasFocus && focus)
  403. {
  404. triggerFocusFlash();
  405. }
  406. // release focus from "top ctrl"s, which generally hides them
  407. if (!focus && mTopCtrl)
  408. {
  409. setTopCtrl(NULL);
  410. }
  411. mAppHasFocus = focus; 
  412. }
  413. LLUICtrl* LLFocusMgr::getLastFocusForGroup(LLView* subtree_root) const
  414. {
  415. if (subtree_root)
  416. {
  417. focus_history_map_t::const_iterator found_it = mFocusHistory.find(subtree_root->getHandle());
  418. if (found_it != mFocusHistory.end())
  419. {
  420. // found last focus for this subtree
  421. return static_cast<LLUICtrl*>(found_it->second.get());
  422. }
  423. }
  424. return NULL;
  425. }
  426. void LLFocusMgr::clearLastFocusForGroup(LLView* subtree_root)
  427. {
  428. if (subtree_root)
  429. {
  430. mFocusHistory.erase(subtree_root->getHandle());
  431. }
  432. }