widget.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269
  1. //*****************************************************************************
  2. //
  3. // widget.c - Generic widget tree handling code.
  4. //
  5. // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Texas Instruments (TI) is supplying this software for use solely and
  9. // exclusively on TI's microcontroller products. The software is owned by
  10. // TI and/or its suppliers, and is protected under applicable copyright
  11. // laws. You may not combine this software with "viral" open-source
  12. // software in order to form a larger program.
  13. //
  14. // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  15. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  16. // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  18. // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  19. // DAMAGES, FOR ANY REASON WHATSOEVER.
  20. //
  21. // This is part of revision 6288 of the Stellaris Graphics Library.
  22. //
  23. //*****************************************************************************
  24. #include "debug.h"
  25. #include "grlib.h"
  26. #include "widget.h"
  27. //*****************************************************************************
  28. //
  29. //! \addtogroup widget_api
  30. //! @{
  31. //
  32. //*****************************************************************************
  33. //*****************************************************************************
  34. //
  35. // Flags that indicate how messages from the message queue are processed. They
  36. // can be sent via either a pre-order or post-order search, and can optionally
  37. // be sent to no other widgets once one accepts the message.
  38. //
  39. //*****************************************************************************
  40. #define MQ_FLAG_POST_ORDER 1
  41. #define MQ_FLAG_STOP_ON_SUCCESS 2
  42. //*****************************************************************************
  43. //
  44. // The size of the message queue. In order to make the queue pointer
  45. // arithmetic more efficient, this should be a power of two.
  46. //
  47. //*****************************************************************************
  48. #define QUEUE_SIZE 16
  49. #ifdef DEBUG_MSGQ
  50. //*****************************************************************************
  51. //
  52. // In debug builds, keep track of the number of cases where a message was
  53. // lost due to the queue being full. We count the following occurrences:
  54. //
  55. // 1. All messages discarded due to queue overflow (g_ulMQOverflow)
  56. // 2. Messages other than WIDGET_MSG_PTR_MOVE discarded due to queue
  57. // overflow (g_ulMQNonMouseOverflow). In this case, we also remember the
  58. // last message that was discarded (g_ulMQLastLostMsg).
  59. // 3. The number of calls to WidgetMessageQueueAdd that fail due to the queue
  60. // mutex already being held.
  61. // 4. The number of cases where WidgetMessageQueueAdd reused an unread
  62. // WIDGET_MSG_PTR_MOVE message when a second one arrived before the previous
  63. // one had been processed.
  64. //
  65. //*****************************************************************************
  66. unsigned int g_ulMQOverflow = 0;
  67. unsigned int g_ulMQNonMouseOverflow = 0;
  68. unsigned int g_ulMQLastLostMsg = 0;
  69. unsigned int g_ulMQMutexClash = 0;
  70. unsigned int g_ulMQMoveOverwrite = 0;
  71. #endif
  72. //*****************************************************************************
  73. //
  74. // This structure describes the message queue used to hold widget messages.
  75. //
  76. //*****************************************************************************
  77. typedef struct
  78. {
  79. //
  80. // The flags that describe how this message should be processed; this is
  81. // defined by the MQ_FLAG_xxx flags.
  82. //
  83. unsigned int ulFlags;
  84. //
  85. // The widget (or widget tree) to which the message should be sent.
  86. //
  87. tWidget *pWidget;
  88. //
  89. // The message to be sent.
  90. //
  91. unsigned int ulMessage;
  92. //
  93. // The first parameter to the message.
  94. //
  95. unsigned int ulParam1;
  96. //
  97. // The second parameter to the message.
  98. //
  99. unsigned int ulParam2;
  100. }
  101. tWidgetMessageQueue;
  102. //*****************************************************************************
  103. //
  104. // The root of the widget tree. This is the widget used when no parent is
  105. // specified when adding a widget, or when no widget is specified when sending
  106. // a message. The parent and sibling of this widget are always zero. This
  107. // should not be directly referenced by applications; WIDGET_ROOT should be
  108. // used instead.
  109. //
  110. //*****************************************************************************
  111. tWidget g_sRoot =
  112. {
  113. sizeof(tWidget),
  114. 0,
  115. 0,
  116. 0,
  117. 0,
  118. {
  119. 0,
  120. 0,
  121. 0,
  122. 0,
  123. },
  124. WidgetDefaultMsgProc
  125. };
  126. //*****************************************************************************
  127. //
  128. // The widget that has captured pointer messages. When a pointer down message
  129. // is accepted by a widget, that widget is saved in this variable and all
  130. // subsequent pointer move and pointer up messages are sent directly to this
  131. // widget.
  132. //
  133. //*****************************************************************************
  134. static tWidget *g_pPointerWidget = 0;
  135. //*****************************************************************************
  136. //
  137. // The message queue that holds messages that are waiting to be processed.
  138. //
  139. //*****************************************************************************
  140. static volatile tWidgetMessageQueue g_pMQ[QUEUE_SIZE];
  141. //*****************************************************************************
  142. //
  143. // The offset to the next message to be read from the message queue. The
  144. // message queue is empty when this has the same value as g_ulMQWrite.
  145. //
  146. //*****************************************************************************
  147. static unsigned int g_ulMQRead = 0;
  148. //*****************************************************************************
  149. //
  150. // The offset to the next message to be written to the message queue. The
  151. // message queue is full when this value is one less than g_ulMQRead (modulo
  152. // the queue size).
  153. //
  154. //*****************************************************************************
  155. static volatile unsigned int g_ulMQWrite = 0;
  156. //*****************************************************************************
  157. //
  158. // The mutex used to protect access to the message queue.
  159. //
  160. //*****************************************************************************
  161. static unsigned char g_ucMQMutex = 0;
  162. //*****************************************************************************
  163. //
  164. //! Initializes a mutex to the unowned state.
  165. //!
  166. //! \param pcMutex is a pointer to mutex that is to be initialized.
  167. //!
  168. //! This function initializes a mutual exclusion semaphore (mutex) to its
  169. //! unowned state in preparation for use with WidgetMutexGet() and
  170. //! WidgetMutexPut(). A mutex is a two state object typically used to
  171. //! serialize access to a shared resource. An application will call
  172. //! WidgetMutexGet() to request ownership of the mutex. If ownership is
  173. //! granted, the caller may safely access the resource then release the mutex
  174. //! using WidgetMutexPut() once it is finished. If ownership is not granted,
  175. //! the caller knows that some other context is currently modifying the shared
  176. //! resource and it must not access the resource at that time.
  177. //!
  178. //! Note that this function must not be called if the mutex passed in \e pcMutex
  179. //! is already in use since this will have the effect of releasing the lock even
  180. //! if some caller currently owns it.
  181. //!
  182. //! \return None.
  183. //
  184. //*****************************************************************************
  185. void
  186. WidgetMutexInit(unsigned char *pcMutex)
  187. {
  188. //
  189. // Catch NULL pointers in a debug build.
  190. //
  191. ASSERT(pcMutex);
  192. //
  193. // Clear the mutex location to set it to the unowned state.
  194. //
  195. *pcMutex = 0;
  196. }
  197. //*****************************************************************************
  198. //
  199. //! Attempts to acquire a mutex.
  200. //!
  201. //! \param pcMutex is a pointer to mutex that is to be acquired.
  202. //!
  203. //! This function attempts to acquire a mutual exclusion semaphore (mutex) on
  204. //! behalf of the caller. If the mutex is not already held, 0 is returned to
  205. //! indicate that the caller may safely access whichever resource the mutex is
  206. //! protecting. If the mutex is already held, 1 is returned and the caller
  207. //! must not access the shared resource.
  208. //!
  209. //! When access to the shared resource is complete, the mutex owner should call
  210. //! WidgetMutexPut() to release the mutex and relinquish ownership of the
  211. //! shared resource.
  212. //!
  213. //! \return Returns 0 if the mutex is acquired successfully or 1 if it is
  214. //! already held by another caller.
  215. //
  216. //*****************************************************************************
  217. #if defined(ewarm) || defined(DOXYGEN)
  218. unsigned int
  219. WidgetMutexGet(unsigned char *pcMutex)
  220. {
  221. //
  222. // Acquire the mutex if possible.
  223. //
  224. __asm(" mov r1, #1\n"
  225. " ldrexb r2, [r0]\n"
  226. " cmp r2, #0\n"
  227. " it eq\n"
  228. " strexb r2, r1, [r0]\n"
  229. " mov r0, r2\n");
  230. //
  231. // "Warning[Pe940]: missing return statement at end of non-void function"
  232. // is suppressed here to avoid putting a "bx lr" in the inline assembly
  233. // above and a superfluous return statement here.
  234. //
  235. #pragma diag_suppress=Pe940
  236. }
  237. #pragma diag_default=Pe940
  238. #elif defined(codered) || defined(gcc) || defined(sourcerygxx)
  239. unsigned int __attribute__((naked))
  240. WidgetMutexGet(unsigned char *pcMutex)
  241. {
  242. unsigned int ulRet;
  243. //
  244. // Acquire the mutex if possible.
  245. //
  246. __asm(" mov r1, #1\n"
  247. " ldrexb r2, [r0]\n"
  248. " cmp r2, #0\n"
  249. " it eq\n"
  250. " strexbeq r2, r1, [r0]\n"
  251. " mov r0, r2\n"
  252. " bx lr\n"
  253. : "=r" (ulRet));
  254. //
  255. // The return is handled in the inline assembly, but the compiler will
  256. // still complain if there is not an explicit return here (despite the fact
  257. // that this does not result in any code being produced because of the
  258. // naked attribute).
  259. //
  260. return(ulRet);
  261. }
  262. #elif defined(rvmdk) || defined(__ARMCC_VERSION)
  263. __asm unsigned int
  264. WidgetMutexGet(unsigned char *pcMutex)
  265. {
  266. mov r1, #1
  267. ldrexb r2, [r0]
  268. cmp r2, #0
  269. it eq
  270. strexbeq r2, r1, [r0]
  271. mov r0, r2
  272. bx lr
  273. }
  274. #elif defined(ccs)
  275. unsigned int
  276. WidgetMutexGet(unsigned char *pcMutex)
  277. {
  278. //
  279. // Acquire the mutex if possible.
  280. //
  281. __asm(" mov r1, #1\n"
  282. " ldrexb r2, [r0]\n"
  283. " cmp r2, #0\n"
  284. " it EQ\n" // TI assembler requires upper case cond
  285. " strexbeq r2, r1, [r0]\n"
  286. " mov r0, r2\n"
  287. " bx lr\n");
  288. //
  289. // The following keeps the TI compiler from optimizing away the code.
  290. //
  291. return((unsigned int)pcMutex + 1);
  292. }
  293. #elif defined (__TMS470__)
  294. __asm(" .sect \".text:WidgetMutexGet\"\n"
  295. " .clink\n"
  296. " .global WidgetMutexGet\n"
  297. "WidgetMutexGet:\n"
  298. " mov r1, #1\n"
  299. " swpb r1, r1, [r0]\n"
  300. " mov r0, r1\n"
  301. " bx lr\n");
  302. #elif defined (_TMS320C6X)
  303. unsigned int WidgetMutexGet(unsigned char *pcMutex)
  304. {
  305. char temp;
  306. unsigned int restore_value;
  307. // Acquire the mutex if possible (disable interrupts to make atomic)
  308. restore_value = _disable_interrupts();
  309. temp = *pcMutex;
  310. *pcMutex = 1;
  311. _restore_interrupts(restore_value);
  312. return ((unsigned int) temp);
  313. }
  314. #elif defined (__IAR_SYSTEMS_ICC__)
  315. unsigned int WidgetMutexGet(unsigned char *pcMutex)
  316. {
  317. __asm(" mov r1, #1\n"
  318. " swpb r1, r1, [r0]\n"
  319. " mov r0, r1\n"
  320. "bx lr\n");
  321. #pragma diag_suppress=Pe940
  322. }
  323. #pragma diag_suppress=Pe940
  324. #else
  325. unsigned int __attribute__((naked)) WidgetMutexGet(unsigned char *pcMutex)
  326. {
  327. // Acquire the mutex if possible.
  328. __asm(" mov r1, #1\n"
  329. " swpb r1, r1, [r0]\n"
  330. " mov r0, r1\n"
  331. " bx lr\n");
  332. // The following keeps the TI compiler from optimizing away the code.
  333. return((unsigned int)(*pcMutex));
  334. }
  335. #endif
  336. //*****************************************************************************
  337. //
  338. //! Release a mutex.
  339. //!
  340. //! \param pcMutex is a pointer to mutex that is to be released.
  341. //!
  342. //! This function releases a mutual exclusion semaphore (mutex), leaving it in
  343. //! the unowned state.
  344. //!
  345. //! \return None.
  346. //
  347. //*****************************************************************************
  348. void
  349. WidgetMutexPut(unsigned char *pcMutex)
  350. {
  351. //
  352. // Release the mutex.
  353. //
  354. *pcMutex = 0;
  355. }
  356. //*****************************************************************************
  357. //
  358. // Determines if a widget exists in the tree below a given point.
  359. //
  360. // \param pWidget is a pointer to the widget tree.
  361. // \param pFind is a pointer to the widget that is being searched for.
  362. //
  363. // This function searches the widget tree below pWidget to determine whether
  364. // or not the widget pointed to by \e pFind exists in the subtree.
  365. //
  366. // \return Returns 1 if \e pFind exists in the subtree or 0 if it does not.
  367. //
  368. //*****************************************************************************
  369. static int
  370. WidgetIsInTree(tWidget *pWidget, tWidget *pFind)
  371. {
  372. tWidget *pTemp;
  373. //
  374. // Check the arguments.
  375. //
  376. ASSERT(pWidget);
  377. ASSERT(pFind);
  378. //
  379. // Loop through the tree under the widget until every widget is searched.
  380. //
  381. for(pTemp = pWidget; pTemp != pWidget->pParent; )
  382. {
  383. //
  384. // See if this widget has a child.
  385. //
  386. if(pTemp->pChild)
  387. {
  388. //
  389. // Go to this widget's child first.
  390. //
  391. pTemp = pTemp->pChild;
  392. }
  393. //
  394. // This widget does not have a child, so either a sibling or a parent
  395. // must be checked. When moving back to the parent, another move must
  396. // be performed as well to avoid getting stuck in a loop (since the
  397. // parent's children have already been searched.
  398. //
  399. else
  400. {
  401. //
  402. // Loop until returning to the parent of the starting widget. This
  403. // loop will be explicitly broken out of if an intervening widget
  404. // is encountered that has not been searched.
  405. //
  406. while(pTemp != pWidget->pParent)
  407. {
  408. if(pTemp == pFind)
  409. {
  410. return(1);
  411. }
  412. //
  413. // See if this widget has a sibling.
  414. //
  415. if(pTemp->pNext)
  416. {
  417. //
  418. // Visit the sibling of this widget.
  419. //
  420. pTemp = pTemp->pNext;
  421. //
  422. // Since this widget has not been searched yet, break out
  423. // of the controlling loop.
  424. //
  425. break;
  426. }
  427. else
  428. {
  429. //
  430. // This widget has no siblings, so go to its parent. Since
  431. // the parent has already been searched, the same sibling
  432. // vs. parent decision must be made on this widget as well.
  433. //
  434. pTemp = pTemp->pParent;
  435. }
  436. }
  437. }
  438. }
  439. //
  440. // The widget could not be found.
  441. //
  442. return(0);
  443. }
  444. //*****************************************************************************
  445. //
  446. //! Handles widget messages.
  447. //!
  448. //! \param pWidget is a pointer to the widget.
  449. //! \param ulMessage is the message to be processed.
  450. //! \param ulParam1 is the first parameter to the message.
  451. //! \param ulParam2 is the second parameter to the message.
  452. //!
  453. //! This function is a default handler for widget messages; it simply ignores
  454. //! all messages sent to it. This is used as the message handler for the root
  455. //! widget, and should be called by the message handler for other widgets when
  456. //! they do not explicitly handle the provided message (in case new messages
  457. //! are added that require some default but override-able processing).
  458. //!
  459. //! \return Always returns 0.
  460. //
  461. //*****************************************************************************
  462. int
  463. WidgetDefaultMsgProc(tWidget *pWidget, unsigned int ulMessage,
  464. unsigned int ulParam1, unsigned int ulParam2)
  465. {
  466. //
  467. // Check the arguments.
  468. //
  469. ASSERT(pWidget);
  470. //
  471. // Return zero for all messages.
  472. //
  473. return(0);
  474. }
  475. //*****************************************************************************
  476. //
  477. //! Adds a widget to the widget tree.
  478. //!
  479. //! \param pParent is the parent for the widget. To add to the root of the tree
  480. //! set this parameter to \b WIDGET_ROOT.
  481. //! \param pWidget is the widget to add.
  482. //!
  483. //! This function adds a widget to the widget tree at the given position within
  484. //! the tree. The widget will become the last child of its parent, and will
  485. //! therefore be searched after the existing children.
  486. //!
  487. //! The added widget can be a full widget tree, allowing addition of an entire
  488. //! heirarchy all at once (for example, adding an entire screen to the widget
  489. //! tree all at once). In this case, it is the responsibility of the caller to
  490. //! ensure that the pParent field of each widget in the added tree is correctly
  491. //! set (in other words, only the widget pointed to by \e pWidget is updated to
  492. //! properly reside in the tree).
  493. //!
  494. //! It is the responsibility of the caller to initialize the pNext and pChild
  495. //! field of the added widget; either of these fields being non-zero results in
  496. //! a pre-defined tree of widgets being added instead of a single one.
  497. //!
  498. //! \return None.
  499. //
  500. //*****************************************************************************
  501. void
  502. WidgetAdd(tWidget *pParent, tWidget *pWidget)
  503. {
  504. //
  505. // Check the arguments.
  506. //
  507. ASSERT(pParent);
  508. ASSERT(pWidget);
  509. //
  510. // Make this widget be a child of its parent.
  511. //
  512. pWidget->pParent = pParent;
  513. //
  514. // See if this parent already has children.
  515. //
  516. if(pParent->pChild)
  517. {
  518. //
  519. // Find the last child of this parent and also check that widget is not
  520. // already present at this level of the tree.
  521. //
  522. for(pParent = pParent->pChild; pParent->pNext;
  523. pParent = pParent->pNext)
  524. {
  525. //
  526. // If we find this widget here already, just return. If we don't
  527. // do this, we allow errant programs to add the same child twice
  528. // resulting in looping on message processing.
  529. //
  530. if(pParent == pWidget)
  531. {
  532. return;
  533. }
  534. }
  535. //
  536. // We perform one final check to see if we are about to add the widget
  537. // twice. We need this to catch the case of a single child which
  538. // causes the previous loop to exit before performing the widget check.
  539. //
  540. if(pParent == pWidget)
  541. {
  542. return;
  543. }
  544. //
  545. // Add this widget to the end of the list of children of this parent.
  546. //
  547. pParent->pNext = pWidget;
  548. }
  549. else
  550. {
  551. //
  552. // Make this widget be the first (and only) child of this parent.
  553. //
  554. pParent->pChild = pWidget;
  555. }
  556. }
  557. //*****************************************************************************
  558. //
  559. //! Removes a widget from the widget tree.
  560. //!
  561. //! \param pWidget is the widget to be removed.
  562. //!
  563. //! This function removes a widget from the widget tree. The removed widget
  564. //! can be a full widget tree, allowing removal of an entire heirarchy all at
  565. //! once (for example, removing an entire screen from the widget tree).
  566. //!
  567. //! \return None.
  568. //
  569. //*****************************************************************************
  570. void
  571. WidgetRemove(tWidget *pWidget)
  572. {
  573. tWidget *pTemp;
  574. //
  575. // Check the argument.
  576. //
  577. ASSERT(pWidget);
  578. //
  579. // Make sure that the supplied widget is actually in the tree section
  580. // owned by its parent and, hence, removeable.
  581. //
  582. if(!pWidget->pParent || !WidgetIsInTree(pWidget->pParent, pWidget))
  583. {
  584. return;
  585. }
  586. //
  587. // See if this widget is the first child of its parent.
  588. //
  589. if(pWidget->pParent->pChild == pWidget)
  590. {
  591. //
  592. // Make the first child of this widgets parent be this widget's
  593. // sibling.
  594. //
  595. pWidget->pParent->pChild = pWidget->pNext;
  596. }
  597. else
  598. {
  599. //
  600. // Find the sibling directly before this widget.
  601. //
  602. for(pTemp = pWidget->pParent->pChild; pTemp->pNext != pWidget;
  603. pTemp = pTemp->pNext)
  604. {
  605. }
  606. //
  607. // Make the previous sibling point to the next sibling, removing this
  608. // widget from the sibling chain.
  609. //
  610. pTemp->pNext = pWidget->pNext;
  611. }
  612. //
  613. // Check to see if the widget which currently owns the pointer has just
  614. // been removed and, if so, clear the pointer focus.
  615. //
  616. if(g_pPointerWidget && !WidgetIsInTree(&g_sRoot, g_pPointerWidget))
  617. {
  618. g_pPointerWidget = 0;
  619. }
  620. //
  621. // Clear the next pointer of the widget.
  622. //
  623. pWidget->pNext = 0;
  624. }
  625. //*****************************************************************************
  626. //
  627. //! Sends a message to a widget tree via a pre-order, depth-first search.
  628. //!
  629. //! \param pWidget is a pointer to the widget tree.
  630. //! \param ulMessage is the message to send.
  631. //! \param ulParam1 is the first parameter to the message.
  632. //! \param ulParam2 is the second parameter to the message.
  633. //! \param bStopOnSuccess is true if the search should be stopped when the
  634. //! first widget is found that returns success in response to the message.
  635. //!
  636. //! This function performs a pre-order, depth-first search of the widget tree,
  637. //! sending a message to each widget encountered. In a depth-first search, the
  638. //! children of a widget are searched before its siblings (preferring to go
  639. //! deeper into the tree, hence the name depth-first). A pre-order search
  640. //! means that the message is sent to a widget before any of its children are
  641. //! searched.
  642. //!
  643. //! An example use of the pre-order search is for paint messages; the larger
  644. //! enclosing widgets should be drawn on the screen before the smaller widgets
  645. //! that reside within the parent widget (otherwise, the children would be
  646. //! overwritten by the parent).
  647. //!
  648. //! \return Returns 0 if \e bStopOnSuccess is false or no widget returned
  649. //! success in response to the message, or the value returned by the first
  650. //! widget to successfully process the message.
  651. //
  652. //*****************************************************************************
  653. unsigned int
  654. WidgetMessageSendPreOrder(tWidget *pWidget, unsigned int ulMessage,
  655. unsigned int ulParam1, unsigned int ulParam2,
  656. unsigned int bStopOnSuccess)
  657. {
  658. unsigned int ulRet;
  659. tWidget *pTemp;
  660. //
  661. // Check the arguments.
  662. //
  663. ASSERT(pWidget);
  664. //
  665. // Send the message to the initial widget and return if it succeeded and
  666. // the search should stop on success.
  667. //
  668. ulRet = pWidget->pfnMsgProc(pWidget, ulMessage, ulParam1, ulParam2);
  669. if((ulRet != 0) && bStopOnSuccess)
  670. {
  671. return(ulRet);
  672. }
  673. //
  674. // Return if the widget does not have any children.
  675. //
  676. if(!pWidget->pChild)
  677. {
  678. return(0);
  679. }
  680. //
  681. // Loop through the tree under the widget until every widget is searched.
  682. //
  683. for(pTemp = pWidget->pChild; pTemp != pWidget; )
  684. {
  685. //
  686. // Send the message to this widget and return if it succeeded and the
  687. // search should stop on success.
  688. //
  689. ulRet = pTemp->pfnMsgProc(pTemp, ulMessage, ulParam1, ulParam2);
  690. if((ulRet != 0) && bStopOnSuccess)
  691. {
  692. return(ulRet);
  693. }
  694. //
  695. // Find the next widget to examine. If this widget has a child, then
  696. // that is the next widget to examine.
  697. //
  698. if(pTemp->pChild)
  699. {
  700. pTemp = pTemp->pChild;
  701. }
  702. //
  703. // This widget does not have a child, so either a sibling or a parent
  704. // must be checked. When moving back to the parent, another move must
  705. // be performed as well to avoid getting stuck in a loop (since the
  706. // parent's children have already been searched).
  707. //
  708. else
  709. {
  710. //
  711. // Loop until returning to the starting widget. This loop will be
  712. // explicitly broken out of if an intervening widget is encountered
  713. // that has not be searched.
  714. //
  715. while(pTemp != pWidget)
  716. {
  717. //
  718. // See if this widget has a sibling.
  719. //
  720. if(pTemp->pNext)
  721. {
  722. //
  723. // Visit the sibling of this widget.
  724. //
  725. pTemp = pTemp->pNext;
  726. //
  727. // Since this widget has not been searched yet, break out
  728. // of the controlling loop.
  729. //
  730. break;
  731. }
  732. else
  733. {
  734. //
  735. // This widget has no siblings, so go to its parent. Since
  736. // the parent has already been searched, the same sibling
  737. // vs. parent decision must be made on this widget as well.
  738. //
  739. pTemp = pTemp->pParent;
  740. }
  741. }
  742. }
  743. }
  744. //
  745. // No widget returned success for the message, or bStopOnSuccess was zero,
  746. // so return zero.
  747. //
  748. return(0);
  749. }
  750. //*****************************************************************************
  751. //
  752. //! Sends a message to a widget tree via a post-order, depth-first search.
  753. //!
  754. //! \param pWidget is a pointer to the widget tree; if this is zero then the
  755. //! root of the widget tree willb e used.
  756. //! \param ulMessage is the message to send.
  757. //! \param ulParam1 is the first parameter to the message.
  758. //! \param ulParam2 is the second parameter to the message.
  759. //! \param bStopOnSuccess is true if the search should be stopped when the
  760. //! first widget is found that returns success in response to the message.
  761. //!
  762. //! This function performs a post-order, depth-first search of the widget tree,
  763. //! sending a message to each widget encountered. In a depth-first search, the
  764. //! children of a widget are searched before its sibling (preferring to go
  765. //! deeper into the tree, hence the name depth-first). A post-order search
  766. //! means that the message is sent to a widget after all of its children are
  767. //! searched.
  768. //!
  769. //! An example use of the post-order search is for pointer-related messages;
  770. //! those messages should be delivered to the lowest widget in the tree before
  771. //! its parents (in other words, the widget deepest in the tree that has a hit
  772. //! should get the message, not the higher up widgets that also include the hit
  773. //! location).
  774. //!
  775. //! Special handling is performed for pointer-related messages. The widget
  776. //! that accepts \b #WIDGET_MSG_PTR_DOWN is remembered and subsequent
  777. //! \b #WIDGET_MSG_PTR_MOVE and \b #WIDGET_MSG_PTR_UP messages are sent
  778. //! directly to that widget.
  779. //!
  780. //! \return Returns 0 if \e bStopOnSuccess is false or no widget returned
  781. //! success in response to the message, or the value returned by the first
  782. //! widget to successfully process the message.
  783. //
  784. //*****************************************************************************
  785. unsigned int
  786. WidgetMessageSendPostOrder(tWidget *pWidget, unsigned int ulMessage,
  787. unsigned int ulParam1, unsigned int ulParam2,
  788. unsigned int bStopOnSuccess)
  789. {
  790. unsigned int ulRet;
  791. tWidget *pTemp;
  792. //
  793. // Check the arguments.
  794. //
  795. ASSERT(pWidget);
  796. //
  797. // See if this is a pointer move or up message.
  798. //
  799. if((ulMessage == WIDGET_MSG_PTR_MOVE) || (ulMessage == WIDGET_MSG_PTR_UP))
  800. {
  801. //
  802. // If there is not a widget that has captured pointer messages, then
  803. // simply drop this message.
  804. //
  805. if(!g_pPointerWidget)
  806. {
  807. return(0);
  808. }
  809. //
  810. // Send the message directly to the widget that has captured pointer
  811. // messages.
  812. //
  813. ulRet = g_pPointerWidget->pfnMsgProc(g_pPointerWidget, ulMessage,
  814. ulParam1, ulParam2);
  815. //
  816. // See if this is a pointer up message.
  817. //
  818. if(ulMessage == WIDGET_MSG_PTR_UP)
  819. {
  820. //
  821. // Since this was a pointer up, the widget no longer has pointer
  822. // messages captured.
  823. //
  824. g_pPointerWidget = 0;
  825. }
  826. //
  827. // Return the value returned by the pointer capture widget.
  828. //
  829. return(ulRet);
  830. }
  831. //
  832. // Loop through the tree under the widget until every widget is searched.
  833. //
  834. for(pTemp = pWidget; pTemp != pWidget->pParent; )
  835. {
  836. //
  837. // See if this widget has a child.
  838. //
  839. if(pTemp->pChild)
  840. {
  841. //
  842. // Go to this widget's child first.
  843. //
  844. pTemp = pTemp->pChild;
  845. }
  846. //
  847. // This widget does not have a child, so either a sibling or a parent
  848. // must be checked. When moving back to the parent, another move must
  849. // be performed as well to avoid getting stuck in a loop (since the
  850. // parent's children have already been searched.
  851. //
  852. else
  853. {
  854. //
  855. // Loop until returning to the parent of the starting widget. This
  856. // loop will be explicitly broken out of if an intervening widget
  857. // is encountered that has not been searched.
  858. //
  859. while(pTemp != pWidget->pParent)
  860. {
  861. //
  862. // Send the message to this widget.
  863. //
  864. ulRet = pTemp->pfnMsgProc(pTemp, ulMessage, ulParam1,
  865. ulParam2);
  866. //
  867. // If this is a pointer down message, the widget accepted the
  868. // message and the handler didn't modify the tree such that
  869. // this widget is no longer present, then save a pointer to the
  870. // widget for subsequent pointer move or pointer up messages.
  871. //
  872. if((ulMessage == WIDGET_MSG_PTR_DOWN) && (ulRet != 0))
  873. {
  874. //
  875. // Is the current widget still in the tree?
  876. //
  877. if(WidgetIsInTree(&g_sRoot, pTemp))
  878. {
  879. //
  880. // The widget is still in the tree so save it for later
  881. // use.
  882. //
  883. g_pPointerWidget = pTemp;
  884. }
  885. else
  886. {
  887. //
  888. // Although this widget handled the PTR_DOWN message,
  889. // it's message handler rearranged the widget tree and
  890. // removed itself so we don't want to send any more
  891. // messages directly to it after all.
  892. //
  893. g_pPointerWidget = 0;
  894. }
  895. }
  896. //
  897. // If the widget returned success and the search should stop on
  898. // success then return immediately.
  899. //
  900. if((ulRet != 0) && bStopOnSuccess)
  901. {
  902. return(ulRet);
  903. }
  904. //
  905. // See if this widget has a sibling.
  906. //
  907. if(pTemp->pNext)
  908. {
  909. //
  910. // Visit the sibling of this widget.
  911. //
  912. pTemp = pTemp->pNext;
  913. //
  914. // Since this widget has not been searched yet, break out
  915. // of the controlling loop.
  916. //
  917. break;
  918. }
  919. else
  920. {
  921. //
  922. // This widget has no siblings, so go to its parent. Since
  923. // the parent has already been searched, the same sibling
  924. // vs. parent decision must be made on this widget as well.
  925. //
  926. pTemp = pTemp->pParent;
  927. }
  928. }
  929. }
  930. }
  931. //
  932. // No widget returned success for the message, or bStopOnSuccess was zero,
  933. // so return zero.
  934. //
  935. return(0);
  936. }
  937. //*****************************************************************************
  938. //
  939. //! Adds a message to the widget message queue.
  940. //!
  941. //! \param pWidget is the widget to which the message should be sent.
  942. //! \param ulMessage is the message to be sent.
  943. //! \param ulParam1 is the first parameter to the message.
  944. //! \param ulParam2 is the second parameter to the message.
  945. //! \param bPostOrder is \b true if the message should be sent via a post-order
  946. //! search, and \b false if it should be sent via a pre-order search.
  947. //! \param bStopOnSuccess is \b true if the message should be sent to widgets
  948. //! until one returns success, and \b false if it should be sent to all
  949. //! widgets.
  950. //!
  951. //! This function places a widget message into the message queue for later
  952. //! processing. The messages are removed from the queue by
  953. //! WidgetMessageQueueProcess() and sent to the appropriate place.
  954. //!
  955. //! It is safe for code which interrupts WidgetMessageQueueProcess() (or called
  956. //! by it) to call this function to send a message. It is not safe for code
  957. //! which interrupts this function to call this function as well; it is up to
  958. //! the caller to guarantee that the later sequence never occurs.
  959. //!
  960. //! \return Returns 1 if the message was added to the queue, and 0 if it could
  961. //! not be added since either the queue is full or another context is currently
  962. //! adding a message to the queue.
  963. //
  964. //*****************************************************************************
  965. int
  966. WidgetMessageQueueAdd(tWidget *pWidget, unsigned int ulMessage,
  967. unsigned int ulParam1, unsigned int ulParam2,
  968. unsigned int bPostOrder, unsigned int bStopOnSuccess)
  969. {
  970. unsigned int ulNext;
  971. unsigned int ulOwned;
  972. //
  973. // Check the arguments.
  974. //
  975. ASSERT(pWidget);
  976. //
  977. // Get the mutex we use to protect access to the message queue.
  978. //
  979. ulOwned = WidgetMutexGet(&g_ucMQMutex);
  980. if(ulOwned)
  981. {
  982. //
  983. // The mutex is already being held by some other caller so return a
  984. // failure.
  985. //
  986. #ifdef DEBUG_MSGQ
  987. g_ulMQMutexClash++;
  988. #endif
  989. return(0);
  990. }
  991. //
  992. // Compute the next value for the write pointer.
  993. //
  994. ulNext = (g_ulMQWrite + 1) % QUEUE_SIZE;
  995. //
  996. // If the queue is not empty, and this is a pointer move message, see if
  997. // the previous message was also a move and, if so, replace the
  998. // coordinates. Without this, the message queue can very quickly overflow
  999. // if the application is busy doing something while the user keeps pressing
  1000. // the display.
  1001. //
  1002. if(ulMessage == WIDGET_MSG_PTR_MOVE)
  1003. {
  1004. //
  1005. // Is the message queue empty?
  1006. //
  1007. if(g_ulMQRead != g_ulMQWrite)
  1008. {
  1009. //
  1010. // No - what is the index of the previous message?
  1011. //
  1012. ulOwned = (g_ulMQWrite == 0) ? (QUEUE_SIZE - 1) : (g_ulMQWrite - 1);
  1013. //
  1014. // Was this a pointer move message?
  1015. //
  1016. if(g_pMQ[g_ulMQWrite].ulMessage == WIDGET_MSG_PTR_MOVE)
  1017. {
  1018. //
  1019. // Yes - overwrite this message with the new
  1020. // coordinate information.
  1021. //
  1022. g_pMQ[ulOwned].ulParam1 = ulParam1;
  1023. g_pMQ[ulOwned].ulParam2 = ulParam2;
  1024. #ifdef DEBUG_MSGQ
  1025. g_ulMQMoveOverwrite++;
  1026. #endif
  1027. //
  1028. // Release the message queue mutex.
  1029. //
  1030. WidgetMutexPut(&g_ucMQMutex);
  1031. //
  1032. // Success.
  1033. //
  1034. return(1);
  1035. }
  1036. }
  1037. }
  1038. //
  1039. // Return a failure if the message queue is full.
  1040. //
  1041. if(ulNext == g_ulMQRead)
  1042. {
  1043. #ifdef DEBUG_MSGQ
  1044. g_ulMQOverflow++;
  1045. if(ulMessage != WIDGET_MSG_PTR_MOVE)
  1046. {
  1047. g_ulMQNonMouseOverflow++;
  1048. g_ulMQLastLostMsg = ulMessage;
  1049. }
  1050. #endif
  1051. //
  1052. // Release the message queue mutex.
  1053. //
  1054. WidgetMutexPut(&g_ucMQMutex);
  1055. return(0);
  1056. }
  1057. //
  1058. // Write this message into the next location in the message queue.
  1059. //
  1060. g_pMQ[g_ulMQWrite].ulFlags = ((bPostOrder ? MQ_FLAG_POST_ORDER : 0) |
  1061. (bStopOnSuccess ? MQ_FLAG_STOP_ON_SUCCESS :
  1062. 0));
  1063. g_pMQ[g_ulMQWrite].pWidget = pWidget;
  1064. g_pMQ[g_ulMQWrite].ulMessage = ulMessage;
  1065. g_pMQ[g_ulMQWrite].ulParam1 = ulParam1;
  1066. g_pMQ[g_ulMQWrite].ulParam2 = ulParam2;
  1067. //
  1068. // Update the message queue write pointer.
  1069. //
  1070. g_ulMQWrite = ulNext;
  1071. //
  1072. // Release the message queue mutex.
  1073. //
  1074. WidgetMutexPut(&g_ucMQMutex);
  1075. //
  1076. // Success.
  1077. //
  1078. return(1);
  1079. }
  1080. //*****************************************************************************
  1081. //
  1082. //! Processes the messages in the widget message queue.
  1083. //!
  1084. //! This function extracts messages from the widget message queue one at a time
  1085. //! and processes them. If the processing of a widget message requires that a
  1086. //! new message be sent, it is acceptable to call WidgetMessageQueueAdd(). It
  1087. //! is also acceptable for code which interrupts this function to call
  1088. //! WidgetMessageQueueAdd() to send more messages. In both cases, the newly
  1089. //! added message will also be processed before this function returns.
  1090. //!
  1091. //! \return None.
  1092. //
  1093. //*****************************************************************************
  1094. void
  1095. WidgetMessageQueueProcess(void)
  1096. {
  1097. tWidget *pWidget;
  1098. unsigned int ulFlags, ulMessage, ulParam1, ulParam2;
  1099. //
  1100. // Loop while there are more messages in the message queue.
  1101. //
  1102. while(g_ulMQRead != g_ulMQWrite)
  1103. {
  1104. //
  1105. // Copy the contents of this message into local variables.
  1106. //
  1107. pWidget = g_pMQ[g_ulMQRead].pWidget;
  1108. ulFlags = g_pMQ[g_ulMQRead].ulFlags;
  1109. ulMessage = g_pMQ[g_ulMQRead].ulMessage;
  1110. ulParam1 = g_pMQ[g_ulMQRead].ulParam1;
  1111. ulParam2 = g_pMQ[g_ulMQRead].ulParam2;
  1112. //
  1113. // Remove this message from the queue.
  1114. //
  1115. g_ulMQRead = (g_ulMQRead + 1) % QUEUE_SIZE;
  1116. //
  1117. // See if this message should be sent via a post-order or pre-order
  1118. // search.
  1119. //
  1120. if(ulFlags & MQ_FLAG_POST_ORDER)
  1121. {
  1122. //
  1123. // Send this message with a post-order search of the widget tree.
  1124. //
  1125. WidgetMessageSendPostOrder(pWidget, ulMessage, ulParam1, ulParam2,
  1126. ((ulFlags & MQ_FLAG_STOP_ON_SUCCESS) ?
  1127. 1 : 0));
  1128. }
  1129. else
  1130. {
  1131. //
  1132. // Send this message with a pre-order search of the widget tree.
  1133. //
  1134. WidgetMessageSendPreOrder(pWidget, ulMessage, ulParam1, ulParam2,
  1135. ((ulFlags & MQ_FLAG_STOP_ON_SUCCESS) ?
  1136. 1 : 0));
  1137. }
  1138. }
  1139. }
  1140. //*****************************************************************************
  1141. //
  1142. //! Sends a pointer message.
  1143. //!
  1144. //! \param ulMessage is the pointer message to be sent.
  1145. //! \param lX is the X coordinate associated with the message.
  1146. //! \param lY is the Y coordinate associated with the message.
  1147. //!
  1148. //! This function sends a pointer message to the root widget. A pointer driver
  1149. //! (such as a touch screen driver) can use this function to deliver pointer
  1150. //! activity to the widget tree without having to have direct knowledge of the
  1151. //! structure of the widget framework.
  1152. //!
  1153. //! \return Returns 1 if the message was added to the queue, and 0 if it could
  1154. //! not be added since the queue is full.
  1155. //
  1156. //*****************************************************************************
  1157. int
  1158. WidgetPointerMessage(unsigned int ulMessage, int lX, int lY)
  1159. {
  1160. //
  1161. // Add the message to the widget message queue.
  1162. //
  1163. return(WidgetMessageQueueAdd(WIDGET_ROOT, ulMessage, lX, lY, 1, 1));
  1164. }
  1165. //*****************************************************************************
  1166. //
  1167. // Close the Doxygen group.
  1168. //! @}
  1169. //
  1170. //*****************************************************************************