topwin.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. /*
  2. * File : topwin.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2009-10-16 Bernard first version
  13. * 2012-02-25 Grissiom rewrite topwin implementation
  14. */
  15. #include "topwin.h"
  16. #include "mouse.h"
  17. #include <rtservice.h>
  18. #include <rtgui/event.h>
  19. #include <rtgui/image.h>
  20. //#include <rtgui/rtgui_theme.h>
  21. #include <rtgui/rtgui_system.h>
  22. #include <rtgui/rtgui_app.h>
  23. #include <rtgui/widgets/window.h>
  24. #include <rtgui/widgets/container.h>
  25. /*
  26. * windows tree in the server side.
  27. *
  28. * This list is divided into two parts. The first part is the shown list, in
  29. * which all the windows have the WINTITLE_SHOWN flag set. Second part is the
  30. * hidden items, in which all the windows don't have WINTITLE_SHOWN flag.
  31. *
  32. * The active window is the one that would receive kbd events. It should always
  33. * be in the first tree. The order of this list is the order of the windows.
  34. * Top window can always clip the window beneath it when the two
  35. * overlapping. Child window can always clip it's parent. Slibing windows can
  36. * clip each other with the same rule as this list. Each child list is the same
  37. * as _rtgui_topwin_list. This forms the hierarchy tree structure of all
  38. * windows.
  39. *
  40. * Thus, the left most leaf of the tree is the top most window and the right
  41. * most root node is the bottom window. The hidden part have no specific
  42. * order.
  43. */
  44. #define get_topwin_from_list(list_entry) (rt_list_entry((list_entry), struct rtgui_topwin, list))
  45. /* the direction can only be next or prev. If you want to iterate the list in
  46. * normal order, use next. If you want to iterate the list with reverse order,
  47. * use prev.*/
  48. #define rt_list_foreach(node, list, direction) \
  49. for ((node) = (list)->direction; (node) != list; (node) = (node)->direction)
  50. #define IS_ROOT_WIN(topwin) ((topwin)->parent == RT_NULL)
  51. static rt_list_t _rtgui_topwin_list = RT_LIST_OBJECT_INIT(_rtgui_topwin_list);
  52. static struct rt_semaphore _rtgui_topwin_lock;
  53. static void rtgui_topwin_update_clip(void);
  54. static void rtgui_topwin_redraw(struct rtgui_rect *rect);
  55. static void _rtgui_topwin_activate_next(enum rtgui_topwin_flag);
  56. void rtgui_topwin_init(void)
  57. {
  58. /* initialize semaphore */
  59. rt_sem_init(&_rtgui_topwin_lock, "wintree", 1, RT_IPC_FLAG_FIFO);
  60. }
  61. static struct rtgui_topwin *rtgui_topwin_search_in_list(struct rtgui_win *window,
  62. struct rt_list_node *list)
  63. {
  64. /* TODO: use a cache to speed up the search. */
  65. struct rt_list_node *node;
  66. struct rtgui_topwin *topwin;
  67. /* the action is tend to operate on the top most window. So we search in a
  68. * depth first order.
  69. */
  70. rt_list_foreach(node, list, next)
  71. {
  72. topwin = rt_list_entry(node, struct rtgui_topwin, list);
  73. /* is this node? */
  74. if (topwin->wid == window)
  75. {
  76. return topwin;
  77. }
  78. topwin = rtgui_topwin_search_in_list(window, &topwin->child_list);
  79. if (topwin != RT_NULL)
  80. return topwin;
  81. }
  82. return RT_NULL;
  83. }
  84. /* add a window to window list[hide] */
  85. rt_err_t rtgui_topwin_add(struct rtgui_event_win_create *event)
  86. {
  87. struct rtgui_topwin *topwin;
  88. topwin = rtgui_malloc(sizeof(struct rtgui_topwin));
  89. if (topwin == RT_NULL)
  90. return -RT_ERROR;
  91. topwin->wid = event->wid;
  92. if (event->wid->_title_wgt)
  93. topwin->extent = RTGUI_WIDGET(event->wid->_title_wgt)->extent;
  94. else
  95. topwin->extent = RTGUI_WIDGET(event->wid)->extent;
  96. topwin->app = event->parent.sender;
  97. if (event->parent_window == RT_NULL)
  98. {
  99. topwin->parent = RT_NULL;
  100. rt_list_insert_before(&_rtgui_topwin_list, &topwin->list);
  101. }
  102. else
  103. {
  104. topwin->parent = rtgui_topwin_search_in_list(event->parent_window, &_rtgui_topwin_list);
  105. if (topwin->parent == RT_NULL)
  106. {
  107. /* parent does not exist. Orphan window? */
  108. rtgui_free(topwin);
  109. return -RT_ERROR;
  110. }
  111. rt_list_insert_before(&topwin->parent->child_list, &topwin->list);
  112. }
  113. rt_list_init(&topwin->child_list);
  114. topwin->flag = WINTITLE_INIT;
  115. if (event->parent.user & RTGUI_WIN_STYLE_NO_FOCUS)
  116. topwin->flag |= WINTITLE_NOFOCUS;
  117. if (event->parent.user & RTGUI_WIN_STYLE_ONTOP)
  118. topwin->flag |= WINTITLE_ONTOP;
  119. if (event->parent.user & RTGUI_WIN_STYLE_ONBTM)
  120. topwin->flag |= WINTITLE_ONBTM;
  121. topwin->title = RT_NULL;
  122. rtgui_list_init(&topwin->monitor_list);
  123. return RT_EOK;
  124. }
  125. static struct rtgui_topwin *_rtgui_topwin_get_root_win(struct rtgui_topwin *topwin)
  126. {
  127. struct rtgui_topwin *topparent;
  128. RT_ASSERT(topwin != RT_NULL);
  129. topparent = topwin;
  130. while (topparent && !IS_ROOT_WIN(topparent))
  131. topparent = topparent->parent;
  132. return topparent;
  133. }
  134. static struct rtgui_topwin *_rtgui_topwin_get_topmost_child_shown(struct rtgui_topwin *topwin)
  135. {
  136. RT_ASSERT(topwin != RT_NULL);
  137. while (!(rt_list_isempty(&topwin->child_list)) &&
  138. get_topwin_from_list(topwin->child_list.next)->flag & WINTITLE_SHOWN)
  139. {
  140. topwin = get_topwin_from_list(topwin->child_list.next);
  141. }
  142. return topwin;
  143. }
  144. static rt_bool_t _rtgui_topwin_in_layer(struct rtgui_topwin *topwin, enum rtgui_topwin_flag flag)
  145. {
  146. return (topwin->flag & (WINTITLE_ONTOP | WINTITLE_ONBTM))
  147. == (flag & (WINTITLE_ONTOP | WINTITLE_ONBTM));
  148. }
  149. /* find the topmost window shown in the layer set by flag. The flag has many
  150. * other infomations but we only use the ONTOP/ONBTM */
  151. struct rtgui_topwin *rtgui_topwin_get_topmost_window_shown(enum rtgui_topwin_flag flag)
  152. {
  153. struct rt_list_node *node;
  154. rt_list_foreach(node, &_rtgui_topwin_list, next)
  155. {
  156. struct rtgui_topwin *topwin = get_topwin_from_list(node);
  157. /* reach the hidden region no window shown in current layer */
  158. if (!(topwin->flag & WINTITLE_SHOWN))
  159. return RT_NULL;
  160. if (_rtgui_topwin_in_layer(topwin, flag))
  161. return _rtgui_topwin_get_topmost_child_shown(topwin);
  162. }
  163. /* no window in current layer is shown */
  164. return RT_NULL;
  165. }
  166. struct rtgui_topwin *rtgui_topwin_get_topmost_window_shown_all(void)
  167. {
  168. struct rtgui_topwin *top;
  169. top = rtgui_topwin_get_topmost_window_shown(WINTITLE_ONTOP);
  170. /* 0 is normal layer */
  171. if (top == RT_NULL)
  172. top = rtgui_topwin_get_topmost_window_shown(WINTITLE_INIT);
  173. if (top == RT_NULL)
  174. top = rtgui_topwin_get_topmost_window_shown(WINTITLE_ONBTM);
  175. return top;
  176. }
  177. struct rtgui_win* rtgui_win_get_topmost_shown(void)
  178. {
  179. struct rtgui_topwin *top;
  180. top = rtgui_topwin_get_topmost_window_shown_all();
  181. if (!top)
  182. return RT_NULL;
  183. return top->wid;
  184. }
  185. static struct rtgui_topwin* _rtgui_topwin_get_next_shown(struct rtgui_topwin *top)
  186. {
  187. /* move to next sibling tree */
  188. if (top->parent == RT_NULL)
  189. {
  190. if (top->list.next != &_rtgui_topwin_list &&
  191. get_topwin_from_list(top->list.next)->flag & WINTITLE_SHOWN)
  192. top = _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(top->list.next));
  193. else
  194. return RT_NULL;
  195. }
  196. /* move to next slibing topwin */
  197. else if (top->list.next != &top->parent->child_list &&
  198. get_topwin_from_list(top->list.next)->flag & WINTITLE_SHOWN)
  199. {
  200. top = _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(top->list.next));
  201. }
  202. /* level up */
  203. else
  204. {
  205. top = top->parent;
  206. }
  207. return top;
  208. }
  209. struct rtgui_win* rtgui_win_get_next_shown(void)
  210. {
  211. struct rtgui_topwin *top;
  212. top = rtgui_topwin_get_topmost_window_shown_all();
  213. if (!top)
  214. return RT_NULL;
  215. top = _rtgui_topwin_get_next_shown(top);
  216. if (!top)
  217. return RT_NULL;
  218. return top->wid;
  219. }
  220. /* a hidden parent will hide it's children. Top level window can be shown at
  221. * any time. */
  222. static rt_bool_t _rtgui_topwin_could_show(struct rtgui_topwin *topwin)
  223. {
  224. struct rtgui_topwin *parent;
  225. RT_ASSERT(topwin != RT_NULL);
  226. for (parent = topwin->parent; parent != RT_NULL; parent = parent->parent)
  227. {
  228. if (!(parent->flag & WINTITLE_SHOWN))
  229. return RT_FALSE;
  230. }
  231. return RT_TRUE;
  232. }
  233. static void _rtgui_topwin_union_region_tree(struct rtgui_topwin *topwin,
  234. struct rtgui_region *region)
  235. {
  236. struct rt_list_node *node;
  237. RT_ASSERT(topwin != RT_NULL);
  238. rt_list_foreach(node, &topwin->child_list, next)
  239. _rtgui_topwin_union_region_tree(get_topwin_from_list(node), region);
  240. rtgui_region_union_rect(region, region, &topwin->extent);
  241. }
  242. /* The return value of this function is the next node in tree.
  243. *
  244. * As we freed the node in this function, it would be a null reference error of
  245. * the caller iterate the tree normally.
  246. */
  247. static struct rt_list_node *_rtgui_topwin_free_tree(struct rtgui_topwin *topwin)
  248. {
  249. struct rt_list_node *node, *next_node;
  250. RT_ASSERT(topwin != RT_NULL);
  251. node = topwin->child_list.next;
  252. while (node != &topwin->child_list)
  253. node = _rtgui_topwin_free_tree(get_topwin_from_list(node));
  254. next_node = topwin->list.next;
  255. rt_list_remove(&topwin->list);
  256. /* free the monitor rect list, topwin node and title */
  257. while (topwin->monitor_list.next != RT_NULL)
  258. {
  259. struct rtgui_mouse_monitor *monitor = rtgui_list_entry(topwin->monitor_list.next,
  260. struct rtgui_mouse_monitor, list);
  261. topwin->monitor_list.next = topwin->monitor_list.next->next;
  262. rtgui_free(monitor);
  263. }
  264. rtgui_free(topwin);
  265. return next_node;
  266. }
  267. rt_err_t rtgui_topwin_remove(struct rtgui_win *wid)
  268. {
  269. struct rtgui_topwin *topwin, *old_focus;
  270. struct rtgui_region region;
  271. /* find the topwin node */
  272. topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
  273. if (topwin == RT_NULL) return -RT_ERROR;
  274. rtgui_region_init(&region);
  275. old_focus = rtgui_topwin_get_focus();
  276. /* remove the root from _rtgui_topwin_list will remove the whole tree from
  277. * _rtgui_topwin_list. */
  278. rt_list_remove(&topwin->list);
  279. if (old_focus == topwin)
  280. {
  281. _rtgui_topwin_activate_next(topwin->flag);
  282. }
  283. if (topwin->flag & WINTITLE_SHOWN)
  284. {
  285. rtgui_topwin_update_clip();
  286. /* redraw the old rect */
  287. _rtgui_topwin_union_region_tree(topwin, &region);
  288. rtgui_topwin_redraw(rtgui_region_extents(&region));
  289. }
  290. rtgui_region_fini(&region);
  291. _rtgui_topwin_free_tree(topwin);
  292. return RT_EOK;
  293. }
  294. /* neither deactivate the old focus nor change _rtgui_topwin_list.
  295. * Suitable to be called when the first item is the window to be activated
  296. * already. */
  297. static void _rtgui_topwin_only_activate(struct rtgui_topwin *topwin)
  298. {
  299. struct rtgui_event_win event;
  300. RT_ASSERT(topwin != RT_NULL);
  301. if (topwin->flag & WINTITLE_NOFOCUS)
  302. return;
  303. /* activate the raised window */
  304. RTGUI_EVENT_WIN_ACTIVATE_INIT(&event);
  305. topwin->flag |= WINTITLE_ACTIVATE;
  306. event.wid = topwin->wid;
  307. rtgui_send(topwin->app, &(event.parent), sizeof(struct rtgui_event_win));
  308. }
  309. /* activate next window in the same layer as flag. The flag has many other
  310. * infomations but we only use the ONTOP/ONBTM */
  311. static void _rtgui_topwin_activate_next(enum rtgui_topwin_flag flag)
  312. {
  313. struct rtgui_topwin *topwin;
  314. topwin = rtgui_topwin_get_topmost_window_shown(flag);
  315. if (topwin == RT_NULL)
  316. return;
  317. _rtgui_topwin_only_activate(topwin);
  318. }
  319. /* this function does not update the clip(to avoid doubel clipping). So if the
  320. * tree has changed, make sure it has already updated outside. */
  321. static void _rtgui_topwin_deactivate(struct rtgui_topwin *topwin)
  322. {
  323. struct rtgui_event_win event;
  324. RT_ASSERT(topwin != RT_NULL);
  325. RT_ASSERT(topwin->app != RT_NULL);
  326. RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
  327. event.wid = topwin->wid;
  328. rtgui_send(topwin->app,
  329. &event.parent, sizeof(struct rtgui_event_win));
  330. topwin->flag &= ~WINTITLE_ACTIVATE;
  331. }
  332. /* Return 1 on the tree is truely moved. If the tree is already in position,
  333. * return 0. */
  334. static int _rtgui_topwin_move_whole_tree2top(struct rtgui_topwin *topwin)
  335. {
  336. struct rtgui_topwin *topparent;
  337. RT_ASSERT(topwin != RT_NULL);
  338. /* move the whole tree */
  339. topparent = _rtgui_topwin_get_root_win(topwin);
  340. RT_ASSERT(topparent != RT_NULL);
  341. /* add node to show list */
  342. if (topwin->flag & WINTITLE_ONTOP)
  343. {
  344. if (get_topwin_from_list(_rtgui_topwin_list.next) == topwin)
  345. return 0;
  346. rt_list_remove(&topparent->list);
  347. rt_list_insert_after(&_rtgui_topwin_list, &(topparent->list));
  348. }
  349. else if (topwin->flag & WINTITLE_ONBTM)
  350. {
  351. /* botton layer window, before the fisrt bottom window or hidden window. */
  352. struct rt_list_node *node;
  353. struct rtgui_topwin *ntopwin = RT_NULL;
  354. rt_list_foreach(node, &_rtgui_topwin_list, next)
  355. {
  356. ntopwin = get_topwin_from_list(node);
  357. if ((ntopwin->flag & WINTITLE_ONBTM)
  358. || !(ntopwin->flag & WINTITLE_SHOWN))
  359. break;
  360. }
  361. if (get_topwin_from_list(node) == topparent)
  362. return 0;
  363. rt_list_remove(&topparent->list);
  364. rt_list_insert_before(node, &(topparent->list));
  365. }
  366. else
  367. {
  368. /* normal layer window, before the fisrt shown normal layer window. */
  369. struct rtgui_topwin *ntopwin = RT_NULL;
  370. struct rt_list_node *node;
  371. rt_list_foreach(node, &_rtgui_topwin_list, next)
  372. {
  373. ntopwin = get_topwin_from_list(node);
  374. if (!((ntopwin->flag & WINTITLE_ONTOP)
  375. && (ntopwin->flag & WINTITLE_SHOWN)))
  376. break;
  377. }
  378. if (get_topwin_from_list(node) == topparent)
  379. return 0;
  380. rt_list_remove(&topparent->list);
  381. rt_list_insert_before(node, &(topparent->list));
  382. }
  383. return 1;
  384. }
  385. static void _rtgui_topwin_raise_in_sibling(struct rtgui_topwin *topwin)
  386. {
  387. struct rt_list_node *win_level;
  388. RT_ASSERT(topwin != RT_NULL);
  389. if (topwin->parent == RT_NULL)
  390. win_level = &_rtgui_topwin_list;
  391. else
  392. win_level = &topwin->parent->child_list;
  393. rt_list_remove(&topwin->list);
  394. rt_list_insert_after(win_level, &topwin->list);
  395. }
  396. /* it will do 2 things. One is moving the whole tree(the root of the tree) to
  397. * the front and the other is moving topwin to the front of it's siblings. */
  398. static int _rtgui_topwin_raise_tree_from_root(struct rtgui_topwin *topwin)
  399. {
  400. int moved;
  401. RT_ASSERT(topwin != RT_NULL);
  402. moved = _rtgui_topwin_move_whole_tree2top(topwin);
  403. /* root win is aleady moved by _rtgui_topwin_move_whole_tree2top */
  404. if (!IS_ROOT_WIN(topwin))
  405. _rtgui_topwin_raise_in_sibling(topwin);
  406. return moved;
  407. }
  408. /* activate a win means:
  409. * - deactivate the old focus win if any
  410. * - raise the window to the front of it's siblings
  411. * - activate a win
  412. */
  413. rt_err_t rtgui_topwin_activate(struct rtgui_event_win_activate *event)
  414. {
  415. struct rtgui_topwin *topwin;
  416. RT_ASSERT(event);
  417. topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_list);
  418. if (topwin == RT_NULL)
  419. return -RT_ERROR;
  420. return rtgui_topwin_activate_topwin(topwin);
  421. }
  422. static void _rtgui_topwin_draw_tree(struct rtgui_topwin *topwin, struct rtgui_event_paint *epaint)
  423. {
  424. struct rt_list_node *node;
  425. rt_list_foreach(node, &topwin->child_list, next)
  426. {
  427. if (!(get_topwin_from_list(node)->flag & WINTITLE_SHOWN))
  428. break;
  429. _rtgui_topwin_draw_tree(get_topwin_from_list(node), epaint);
  430. }
  431. epaint->wid = topwin->wid;
  432. rtgui_send(topwin->app, &(epaint->parent), sizeof(*epaint));
  433. }
  434. rt_err_t rtgui_topwin_activate_topwin(struct rtgui_topwin *topwin)
  435. {
  436. int tpmoved;
  437. struct rtgui_topwin *old_focus_topwin;
  438. struct rtgui_event_paint epaint;
  439. RT_ASSERT(topwin != RT_NULL);
  440. RTGUI_EVENT_PAINT_INIT(&epaint);
  441. if (!(topwin->flag & WINTITLE_SHOWN))
  442. return -RT_ERROR;
  443. if (topwin->flag & WINTITLE_NOFOCUS)
  444. {
  445. /* just raise and show, no other effects. Active window is the one
  446. * which will receive kbd events. So a no-focus window can only be
  447. * "raised" but not "activated".
  448. */
  449. tpmoved = _rtgui_topwin_raise_tree_from_root(topwin);
  450. rtgui_topwin_update_clip();
  451. if (tpmoved)
  452. _rtgui_topwin_draw_tree(_rtgui_topwin_get_root_win(topwin),
  453. &epaint);
  454. else
  455. _rtgui_topwin_draw_tree(topwin, &epaint);
  456. return RT_EOK;
  457. }
  458. if (topwin->flag & WINTITLE_ACTIVATE)
  459. return RT_EOK;
  460. old_focus_topwin = rtgui_topwin_get_focus();
  461. /* if topwin has the focus, it should have WINTITLE_ACTIVATE set and
  462. * returned above. */
  463. RT_ASSERT(old_focus_topwin != topwin);
  464. tpmoved = _rtgui_topwin_raise_tree_from_root(topwin);
  465. /* clip before active the window, so we could get right boarder region. */
  466. rtgui_topwin_update_clip();
  467. if (old_focus_topwin != RT_NULL)
  468. {
  469. /* deactivate the old focus window firstly, otherwise it will make the new
  470. * window invisible. */
  471. _rtgui_topwin_deactivate(old_focus_topwin);
  472. }
  473. _rtgui_topwin_only_activate(topwin);
  474. if (tpmoved)
  475. _rtgui_topwin_draw_tree(_rtgui_topwin_get_root_win(topwin),
  476. &epaint);
  477. else
  478. _rtgui_topwin_draw_tree(topwin, &epaint);
  479. return RT_EOK;
  480. }
  481. /* map func to the topwin tree in preorder.
  482. *
  483. * Remember that we are in a embedded system so write the @param func memory
  484. * efficiently.
  485. */
  486. rt_inline void _rtgui_topwin_preorder_map(struct rtgui_topwin *topwin, void (*func)(struct rtgui_topwin *))
  487. {
  488. struct rt_list_node *child;
  489. RT_ASSERT(topwin != RT_NULL);
  490. RT_ASSERT(func != RT_NULL);
  491. func(topwin);
  492. rt_list_foreach(child, &topwin->child_list, next)
  493. _rtgui_topwin_preorder_map(get_topwin_from_list(child), func);
  494. }
  495. rt_inline void _rtgui_topwin_mark_hidden(struct rtgui_topwin *topwin)
  496. {
  497. topwin->flag &= ~WINTITLE_SHOWN;
  498. RTGUI_WIDGET_HIDE(topwin->wid);
  499. }
  500. rt_inline void _rtgui_topwin_mark_shown(struct rtgui_topwin *topwin)
  501. {
  502. if (topwin->flag & WINTITLE_SHOWN)
  503. return;
  504. topwin->flag |= WINTITLE_SHOWN;
  505. if (RTGUI_WIDGET_IS_HIDE(topwin->wid))
  506. {
  507. rtgui_widget_show(RTGUI_WIDGET(topwin->wid));
  508. }
  509. }
  510. rt_err_t rtgui_topwin_show(struct rtgui_event_win *event)
  511. {
  512. struct rtgui_topwin *topwin;
  513. struct rtgui_win *wid = event->wid;
  514. topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
  515. /* no such a window recorded */
  516. if (topwin == RT_NULL)
  517. return -RT_ERROR;
  518. /* child windows could only be shown iif the parent is shown */
  519. if (!_rtgui_topwin_could_show(topwin))
  520. {
  521. return -RT_ERROR;
  522. }
  523. _rtgui_topwin_preorder_map(topwin, _rtgui_topwin_mark_shown);
  524. rtgui_topwin_activate_topwin(topwin);
  525. return RT_EOK;
  526. }
  527. static void _rtgui_topwin_clear_modal_tree(struct rtgui_topwin *topwin)
  528. {
  529. struct rt_list_node *node;
  530. RT_ASSERT(topwin != RT_NULL);
  531. RT_ASSERT(topwin->parent != RT_NULL);
  532. while (!IS_ROOT_WIN(topwin))
  533. {
  534. rt_list_foreach(node, &topwin->parent->child_list, next)
  535. {
  536. get_topwin_from_list(node)->flag &= ~WINTITLE_MODALED;
  537. get_topwin_from_list(node)->wid->flag &= ~RTGUI_WIN_FLAG_UNDER_MODAL;
  538. if (get_topwin_from_list(node)->flag & WINTITLE_MODALING)
  539. {
  540. goto _out;
  541. }
  542. }
  543. topwin = topwin->parent;
  544. }
  545. _out:
  546. /* clear the modal flag of the root window */
  547. topwin->flag &= ~WINTITLE_MODALED;
  548. topwin->wid->flag &= ~RTGUI_WIN_FLAG_UNDER_MODAL;
  549. }
  550. /* hide a window */
  551. rt_err_t rtgui_topwin_hide(struct rtgui_event_win *event)
  552. {
  553. struct rtgui_topwin *topwin;
  554. struct rtgui_topwin *old_focus_topwin;
  555. struct rtgui_win *wid;
  556. struct rt_list_node *containing_list;
  557. if (!event)
  558. return -RT_ERROR;
  559. wid = event->wid;
  560. /* find in show list */
  561. topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
  562. if (topwin == RT_NULL)
  563. {
  564. return -RT_ERROR;
  565. }
  566. if (!(topwin->flag & WINTITLE_SHOWN))
  567. {
  568. return RT_EOK;
  569. }
  570. old_focus_topwin = rtgui_topwin_get_focus();
  571. _rtgui_topwin_preorder_map(topwin, _rtgui_topwin_mark_hidden);
  572. if (topwin->parent == RT_NULL)
  573. containing_list = &_rtgui_topwin_list;
  574. else
  575. containing_list = &topwin->parent->child_list;
  576. rt_list_remove(&topwin->list);
  577. rt_list_insert_before(containing_list, &topwin->list);
  578. /* update clip info */
  579. rtgui_topwin_update_clip();
  580. if (topwin->flag & WINTITLE_MODALING)
  581. {
  582. topwin->flag &= ~WINTITLE_MODALING;
  583. _rtgui_topwin_clear_modal_tree(topwin);
  584. }
  585. if (old_focus_topwin == topwin)
  586. {
  587. _rtgui_topwin_activate_next(topwin->flag);
  588. }
  589. topwin->flag &= ~WINTITLE_ACTIVATE;
  590. /* redraw the old rect */
  591. rtgui_topwin_redraw(&(topwin->extent));
  592. return RT_EOK;
  593. }
  594. /* move top window */
  595. rt_err_t rtgui_topwin_move(struct rtgui_event_win_move *event)
  596. {
  597. struct rtgui_topwin *topwin;
  598. int dx, dy;
  599. rtgui_rect_t old_rect; /* the old topwin coverage area */
  600. struct rtgui_list_node *node;
  601. /* find in show list */
  602. topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_list);
  603. if (topwin == RT_NULL ||
  604. !(topwin->flag & WINTITLE_SHOWN))
  605. {
  606. return -RT_ERROR;
  607. }
  608. /* get the delta move x, y */
  609. dx = event->x - topwin->extent.x1;
  610. dy = event->y - topwin->extent.y1;
  611. old_rect = topwin->extent;
  612. /* move window rect */
  613. rtgui_rect_moveto(&(topwin->extent), dx, dy);
  614. /* move the monitor rect list */
  615. rtgui_list_foreach(node, &(topwin->monitor_list))
  616. {
  617. struct rtgui_mouse_monitor *monitor = rtgui_list_entry(node,
  618. struct rtgui_mouse_monitor,
  619. list);
  620. rtgui_rect_moveto(&(monitor->rect), dx, dy);
  621. }
  622. /* update windows clip info */
  623. rtgui_topwin_update_clip();
  624. /* update old window coverage area */
  625. rtgui_topwin_redraw(&old_rect);
  626. if (rtgui_rect_is_intersect(&old_rect, &(topwin->extent)) != RT_EOK)
  627. {
  628. /*
  629. * the old rect is not intersect with moved rect,
  630. * re-paint window
  631. */
  632. struct rtgui_event_paint epaint;
  633. RTGUI_EVENT_PAINT_INIT(&epaint);
  634. epaint.wid = topwin->wid;
  635. rtgui_send(topwin->app, &(epaint.parent), sizeof(epaint));
  636. }
  637. return RT_EOK;
  638. }
  639. /*
  640. * resize a top win
  641. * Note: currently, only support resize hidden window
  642. */
  643. void rtgui_topwin_resize(struct rtgui_win *wid, rtgui_rect_t *rect)
  644. {
  645. struct rtgui_topwin *topwin;
  646. struct rtgui_region region;
  647. /* find in show list */
  648. topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
  649. if (topwin == RT_NULL ||
  650. !(topwin->flag & WINTITLE_SHOWN))
  651. return;
  652. /* record the old rect */
  653. rtgui_region_init_with_extents(&region, &topwin->extent);
  654. /* union the new rect so this is the region we should redraw */
  655. rtgui_region_union_rect(&region, &region, rect);
  656. topwin->extent = *rect;
  657. /* update windows clip info */
  658. rtgui_topwin_update_clip();
  659. /* update old window coverage area */
  660. rtgui_topwin_redraw(rtgui_region_extents(&region));
  661. rtgui_region_fini(&region);
  662. }
  663. static struct rtgui_topwin *_rtgui_topwin_get_focus_from_list(struct rt_list_node *list)
  664. {
  665. struct rt_list_node *node;
  666. RT_ASSERT(list != RT_NULL);
  667. rt_list_foreach(node, list, next)
  668. {
  669. struct rtgui_topwin *child = get_topwin_from_list(node);
  670. if (child->flag & WINTITLE_ACTIVATE)
  671. return child;
  672. child = _rtgui_topwin_get_focus_from_list(&child->child_list);
  673. if (child != RT_NULL)
  674. return child;
  675. }
  676. return RT_NULL;
  677. }
  678. struct rtgui_topwin *rtgui_topwin_get_focus(void)
  679. {
  680. return _rtgui_topwin_get_focus_from_list(&_rtgui_topwin_list);
  681. }
  682. static struct rtgui_topwin *_rtgui_topwin_get_wnd_from_tree(struct rt_list_node *list,
  683. int x, int y,
  684. rt_bool_t exclude_modaled)
  685. {
  686. struct rt_list_node *node;
  687. struct rtgui_topwin *topwin, *target;
  688. RT_ASSERT(list != RT_NULL);
  689. rt_list_foreach(node, list, next)
  690. {
  691. topwin = get_topwin_from_list(node);
  692. if (!(topwin->flag & WINTITLE_SHOWN))
  693. break;
  694. /* if higher window have this point, return it */
  695. target = _rtgui_topwin_get_wnd_from_tree(&topwin->child_list, x, y, exclude_modaled);
  696. if (target != RT_NULL)
  697. return target;
  698. if (exclude_modaled && (topwin->flag & WINTITLE_MODALED))
  699. break;
  700. if (rtgui_rect_contains_point(&(topwin->extent), x, y) == RT_EOK)
  701. {
  702. return topwin;
  703. }
  704. }
  705. return RT_NULL;
  706. }
  707. struct rtgui_topwin *rtgui_topwin_get_wnd(int x, int y)
  708. {
  709. return _rtgui_topwin_get_wnd_from_tree(&_rtgui_topwin_list, x, y, RT_FALSE);
  710. }
  711. struct rtgui_topwin *rtgui_topwin_get_wnd_no_modaled(int x, int y)
  712. {
  713. return _rtgui_topwin_get_wnd_from_tree(&_rtgui_topwin_list, x, y, RT_TRUE);
  714. }
  715. /* clip region from topwin, and the windows beneath it. */
  716. rt_inline void _rtgui_topwin_clip_to_region(struct rtgui_topwin *topwin,
  717. struct rtgui_region *region)
  718. {
  719. RT_ASSERT(region != RT_NULL);
  720. RT_ASSERT(topwin != RT_NULL);
  721. rtgui_region_reset(&topwin->wid->outer_clip, &topwin->wid->outer_extent);
  722. rtgui_region_intersect(&topwin->wid->outer_clip, &topwin->wid->outer_clip, region);
  723. }
  724. static void rtgui_topwin_update_clip(void)
  725. {
  726. struct rtgui_topwin *top;
  727. struct rtgui_event_clip_info eclip;
  728. /* Note that the region is a "female die", that means it's the region you
  729. * can paint to, not the region covered by others.
  730. */
  731. struct rtgui_region region_available;
  732. if (rt_list_isempty(&_rtgui_topwin_list) ||
  733. !(get_topwin_from_list(_rtgui_topwin_list.next)->flag & WINTITLE_SHOWN))
  734. return;
  735. RTGUI_EVENT_CLIP_INFO_INIT(&eclip);
  736. rtgui_region_init_rect(&region_available, 0, 0,
  737. rtgui_graphic_driver_get_default()->width,
  738. rtgui_graphic_driver_get_default()->height);
  739. /* from top to bottom. */
  740. top = rtgui_topwin_get_topmost_window_shown(WINTITLE_ONTOP);
  741. /* 0 is normal layer */
  742. if (top == RT_NULL)
  743. top = rtgui_topwin_get_topmost_window_shown(WINTITLE_INIT);
  744. if (top == RT_NULL)
  745. top = rtgui_topwin_get_topmost_window_shown(WINTITLE_ONBTM);
  746. while (top != RT_NULL)
  747. {
  748. /* clip the topwin */
  749. _rtgui_topwin_clip_to_region(top, &region_available);
  750. /* update available region */
  751. rtgui_region_subtract_rect(&region_available, &region_available, &top->extent);
  752. /* send clip event to destination window */
  753. eclip.wid = top->wid;
  754. rtgui_send(top->app, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
  755. top = _rtgui_topwin_get_next_shown(top);
  756. }
  757. rtgui_region_fini(&region_available);
  758. }
  759. static void _rtgui_topwin_redraw_tree(struct rt_list_node *list,
  760. struct rtgui_rect *rect,
  761. struct rtgui_event_paint *epaint)
  762. {
  763. struct rt_list_node *node;
  764. RT_ASSERT(list != RT_NULL);
  765. RT_ASSERT(rect != RT_NULL);
  766. RT_ASSERT(epaint != RT_NULL);
  767. /* skip the hidden windows */
  768. rt_list_foreach(node, list, prev)
  769. {
  770. if (get_topwin_from_list(node)->flag & WINTITLE_SHOWN)
  771. break;
  772. }
  773. for (; node != list; node = node->prev)
  774. {
  775. struct rtgui_topwin *topwin;
  776. topwin = get_topwin_from_list(node);
  777. //FIXME: intersect with clip?
  778. if (rtgui_rect_is_intersect(rect, &(topwin->extent)) == RT_EOK)
  779. {
  780. epaint->wid = topwin->wid;
  781. rtgui_send(topwin->app, &(epaint->parent), sizeof(*epaint));
  782. }
  783. _rtgui_topwin_redraw_tree(&topwin->child_list, rect, epaint);
  784. }
  785. }
  786. static void rtgui_topwin_redraw(struct rtgui_rect *rect)
  787. {
  788. struct rtgui_event_paint epaint;
  789. RTGUI_EVENT_PAINT_INIT(&epaint);
  790. epaint.wid = RT_NULL;
  791. _rtgui_topwin_redraw_tree(&_rtgui_topwin_list, rect, &epaint);
  792. }
  793. /* a window enter modal mode will modal all the sibling window and parent
  794. * window all along to the root window. If a root window modals, there is
  795. * nothing to do here.*/
  796. rt_err_t rtgui_topwin_modal_enter(struct rtgui_event_win_modal_enter *event)
  797. {
  798. struct rtgui_topwin *topwin, *parent_top;
  799. struct rt_list_node *node;
  800. topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_list);
  801. if (topwin == RT_NULL)
  802. return -RT_ERROR;
  803. if (IS_ROOT_WIN(topwin))
  804. return RT_EOK;
  805. parent_top = topwin->parent;
  806. /* modal window should be on top already */
  807. RT_ASSERT(get_topwin_from_list(parent_top->child_list.next) == topwin);
  808. do {
  809. rt_list_foreach(node, &parent_top->child_list, next)
  810. {
  811. get_topwin_from_list(node)->flag |= WINTITLE_MODALED;
  812. get_topwin_from_list(node)->wid->flag |= RTGUI_WIN_FLAG_UNDER_MODAL;
  813. }
  814. parent_top->flag |= WINTITLE_MODALED;
  815. parent_top->wid->flag |= RTGUI_WIN_FLAG_UNDER_MODAL;
  816. parent_top = parent_top->parent;
  817. } while (parent_top);
  818. topwin->flag &= ~WINTITLE_MODALED;
  819. topwin->wid->flag &= ~RTGUI_WIN_FLAG_UNDER_MODAL;
  820. topwin->flag |= WINTITLE_MODALING;
  821. return RT_EOK;
  822. }
  823. void rtgui_topwin_append_monitor_rect(struct rtgui_win *wid, rtgui_rect_t *rect)
  824. {
  825. struct rtgui_topwin *win;
  826. /* parameters check */
  827. if (wid == RT_NULL || rect == RT_NULL) return;
  828. /* find topwin */
  829. win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
  830. if (win == RT_NULL)
  831. return;
  832. /* append rect to top window monitor rect list */
  833. rtgui_mouse_monitor_append(&(win->monitor_list), rect);
  834. }
  835. void rtgui_topwin_remove_monitor_rect(struct rtgui_win *wid, rtgui_rect_t *rect)
  836. {
  837. struct rtgui_topwin *win;
  838. /* parameters check */
  839. if (wid == RT_NULL || rect == RT_NULL)
  840. return;
  841. /* find topwin */
  842. win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
  843. if (win == RT_NULL)
  844. return;
  845. /* remove rect from top window monitor rect list */
  846. rtgui_mouse_monitor_remove(&(win->monitor_list), rect);
  847. }
  848. static struct rtgui_object* _get_obj_in_topwin(struct rtgui_topwin *topwin,
  849. struct rtgui_app *app,
  850. rt_uint32_t id)
  851. {
  852. struct rtgui_object *object;
  853. struct rt_list_node *node;
  854. object = RTGUI_OBJECT(topwin->wid);
  855. if (object->id == id)
  856. return object;
  857. object = rtgui_container_get_object(RTGUI_CONTAINER(object), id);
  858. if (object)
  859. return object;
  860. rt_list_foreach(node, &topwin->child_list, next)
  861. {
  862. struct rtgui_topwin *topwin;
  863. topwin = get_topwin_from_list(node);
  864. if (topwin->app != app)
  865. continue;
  866. object = _get_obj_in_topwin(topwin, app, id);
  867. if (object)
  868. return object;
  869. }
  870. return RT_NULL;
  871. }
  872. struct rtgui_object* rtgui_get_object(struct rtgui_app *app, rt_uint32_t id)
  873. {
  874. struct rtgui_object *object;
  875. struct rt_list_node *node;
  876. object = RTGUI_OBJECT(app);
  877. if (object->id == id)
  878. return object;
  879. rt_list_foreach(node, &_rtgui_topwin_list, next)
  880. {
  881. struct rtgui_topwin *topwin;
  882. topwin = get_topwin_from_list(node);
  883. if (topwin->app != app)
  884. continue;
  885. object = _get_obj_in_topwin(topwin, app, id);
  886. if (object)
  887. return object;
  888. }
  889. return RT_NULL;
  890. }
  891. RTM_EXPORT(rtgui_get_object);
  892. struct rtgui_object* rtgui_get_self_object(rt_uint32_t id)
  893. {
  894. return rtgui_get_object(rtgui_app_self(), id);
  895. }
  896. RTM_EXPORT(rtgui_get_self_object);
  897. static void _rtgui_topwin_dump(struct rtgui_topwin *topwin)
  898. {
  899. rt_kprintf("0x%p:%s,0x%x,%c%c",
  900. topwin, topwin->wid->title, topwin->flag,
  901. topwin->flag & WINTITLE_SHOWN ? 'S' : 'H',
  902. topwin->flag & WINTITLE_MODALED ? 'm' :
  903. topwin->flag & WINTITLE_MODALING ? 'M' : ' ');
  904. }
  905. static void _rtgui_topwin_dump_tree(struct rtgui_topwin *topwin)
  906. {
  907. struct rt_list_node *node;
  908. _rtgui_topwin_dump(topwin);
  909. rt_kprintf("(");
  910. rt_list_foreach(node, &topwin->child_list, next)
  911. {
  912. _rtgui_topwin_dump_tree(get_topwin_from_list(node));
  913. }
  914. rt_kprintf(")");
  915. }
  916. void rtgui_topwin_dump_tree(void)
  917. {
  918. struct rt_list_node *node;
  919. rt_list_foreach(node, &_rtgui_topwin_list, next)
  920. {
  921. _rtgui_topwin_dump_tree(get_topwin_from_list(node));
  922. rt_kprintf("\n");
  923. }
  924. }
  925. #ifdef RT_USING_FINSH
  926. #include <finsh.h>
  927. void dump_tree()
  928. {
  929. rtgui_topwin_dump_tree();
  930. }
  931. FINSH_FUNCTION_EXPORT(dump_tree, dump rtgui topwin tree)
  932. #endif