rt-thread/rtgui/server/topwin.c

1070 lines
27 KiB
C

/*
* File : topwin.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include "panel.h"
#include "topwin.h"
#include "mouse.h"
#include <rtgui/event.h>
#include <rtgui/image.h>
#include <rtgui/rtgui_theme.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/window.h>
struct rtgui_topwin* rtgui_server_focus_topwin = RT_NULL;
static struct rtgui_list_node _rtgui_topwin_show_list;
static struct rtgui_list_node _rtgui_topwin_hide_list;
static struct rt_semaphore _rtgui_topwin_lock;
static void rtgui_topwin_update_clip(void);
static void rtgui_topwin_redraw(struct rtgui_rect* rect);
void rtgui_topwin_init()
{
/* init window list */
rtgui_list_init(&_rtgui_topwin_show_list);
rtgui_list_init(&_rtgui_topwin_hide_list);
rt_sem_init(&_rtgui_topwin_lock,
"topwin", 1, RT_IPC_FLAG_FIFO);
}
static struct rtgui_topwin*
rtgui_topwin_search_in_list(struct rtgui_win* wid, struct rtgui_list_node* list)
{
struct rtgui_list_node* node;
struct rtgui_topwin* topwin;
/* search in list */
rtgui_list_foreach(node, list)
{
topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
/* is this node? */
if (topwin->wid == wid)
{
return topwin;
}
}
return RT_NULL;
}
/* add a window to window list[hide] */
rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event)
{
struct rtgui_topwin* topwin;
topwin = rtgui_malloc(sizeof(struct rtgui_topwin));
if (topwin == RT_NULL) return -RT_ERROR;
topwin->wid = event->wid;
#ifdef RTGUI_USING_SMALL_SIZE
topwin->extent = RTGUI_WIDGET(event->wid)->extent;
#else
topwin->extent = event->extent;
#endif
topwin->tid = event->parent.sender;
topwin->flag = 0;
if (event->parent.user & RTGUI_WIN_STYLE_NO_TITLE) topwin->flag |= WINTITLE_NO;
if (event->parent.user & RTGUI_WIN_STYLE_CLOSEBOX) topwin->flag |= WINTITLE_CLOSEBOX;
if (!(event->parent.user & RTGUI_WIN_STYLE_NO_BORDER)) topwin->flag |= WINTITLE_BORDER;
if (event->parent.user & RTGUI_WIN_STYLE_NO_FOCUS) topwin->flag |= WINTITLE_NOFOCUS;
if(!(topwin->flag & WINTITLE_NO) || (topwin->flag & WINTITLE_BORDER))
{
/* get win extent */
rtgui_rect_t rect = topwin->extent;
/* add border rect */
if (topwin->flag & WINTITLE_BORDER)
{
rtgui_rect_inflate(&rect, WINTITLE_BORDER_SIZE);
}
/* add title rect */
if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT;
#ifdef RTGUI_USING_SMALL_SIZE
topwin->title = rtgui_wintitle_create(event->wid->title);
#else
topwin->title = rtgui_wintitle_create(event->title);
#endif
rtgui_widget_set_rect(RTGUI_WIDGET(topwin->title), &rect);
/* update clip info */
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
&(RTGUI_WIDGET(topwin->title)->clip),
&(topwin->extent));
}
else topwin->title = RT_NULL;
rtgui_list_init(&topwin->list);
rtgui_list_init(&topwin->monitor_list);
/* add topwin node to the hidden window list */
rtgui_list_insert(&(_rtgui_topwin_hide_list), &(topwin->list));
return RT_EOK;
}
rt_err_t rtgui_topwin_remove(struct rtgui_win* wid)
{
struct rtgui_topwin* topwin;
/* find the topwin node */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (topwin)
{
/* remove node from list */
rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
rtgui_topwin_update_clip();
/* redraw the old rect */
rtgui_topwin_redraw(&(topwin->extent));
if (rtgui_server_focus_topwin == topwin)
{
/* activate the next window */
if (_rtgui_topwin_show_list.next != RT_NULL)
{
struct rtgui_event_win wevent;
struct rtgui_topwin* wnd;
/* get the topwin */
wnd = rtgui_list_entry(_rtgui_topwin_show_list.next,
struct rtgui_topwin, list);
/* activate the window */
RTGUI_EVENT_WIN_ACTIVATE_INIT(&wevent);
wevent.wid = wnd->wid;
rtgui_thread_send(wnd->tid, &(wevent.parent), sizeof(struct rtgui_event_win));
/* set new focus topwin */
rtgui_server_focus_topwin = wnd;
}
else
{
/* there is no shown window right now */
rtgui_server_focus_topwin = RT_NULL;
}
}
/* free the monitor rect list, topwin node and title */
while (topwin->monitor_list.next != RT_NULL)
{
struct rtgui_mouse_monitor* monitor = rtgui_list_entry(topwin->monitor_list.next,
struct rtgui_mouse_monitor, list);
topwin->monitor_list.next = topwin->monitor_list.next->next;
rtgui_free(monitor);
}
/* destroy win title */
rtgui_wintitle_destroy(topwin->title);
topwin->title = RT_NULL;
rtgui_free(topwin);
return RT_EOK;
}
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (topwin)
{
/* remove node from list */
rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list));
/* free the topwin node and title */
rtgui_wintitle_destroy(topwin->title);
topwin->title = RT_NULL;
rtgui_free(topwin);
return RT_EOK;
}
return -RT_ERROR;
}
/* activate a win
* - deactivate the old focus win
* - activate a win
* - set the focus win to activate win
* - draw win title
*/
void rtgui_topwin_activate_win(struct rtgui_topwin* win)
{
struct rtgui_event_win event;
/* activate the raised window */
RTGUI_EVENT_WIN_ACTIVATE_INIT(&event);
event.wid = win->wid;
rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
/* redraw title */
if (win->title != RT_NULL)
{
win->flag |= WINTITLE_ACTIVATE;
rtgui_theme_draw_win(win);
}
if ((rtgui_server_focus_topwin != RT_NULL) && (rtgui_server_focus_topwin != win))
{
/* deactivate the old focus win */
RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
event.wid = rtgui_server_focus_topwin->wid;
rtgui_thread_send(rtgui_server_focus_topwin->tid,
&event.parent, sizeof(struct rtgui_event_win));
/* redraw title */
if (rtgui_server_focus_topwin->title != RT_NULL)
{
rtgui_server_focus_topwin->flag &= ~WINTITLE_ACTIVATE;
rtgui_theme_draw_win(rtgui_server_focus_topwin);
}
}
rtgui_server_focus_topwin = win;
}
/*
* deactivate a win
* - deactivate the win
* - redraw win title
* - set rtgui_server_focus_topwin
*/
void rtgui_topwin_deactivate_win(struct rtgui_topwin* win)
{
/* deactivate win */
struct rtgui_event_win event;
RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
event.wid = win->wid;
rtgui_thread_send(win->tid,
&event.parent, sizeof(struct rtgui_event_win));
win->flag &= ~WINTITLE_ACTIVATE;
rtgui_theme_draw_win(win);
if (rtgui_server_focus_topwin == win)
{
rtgui_server_focus_topwin = RT_NULL;
}
}
/* raise window to front */
#ifdef RTGUI_USING_SMALL_SIZE
void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender)
{
struct rtgui_topwin* topwin;
/* find the topwin node */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (topwin)
{
rt_int32_t count;
struct rtgui_list_node* node;
struct rtgui_event_clip_info eclip;
RTGUI_EVENT_CLIP_INFO_INIT(&eclip);
/* the window is already placed in front */
if (&(topwin->list) == _rtgui_topwin_show_list.next)
{
rtgui_server_focus_topwin = RT_NULL;
rtgui_topwin_activate_win(topwin);
return ;
}
/* remove node from list */
rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
/* add to front */
rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list));
/* send clip info event */
count = 0;
for (node = _rtgui_topwin_show_list.next; node != RT_NULL; node = node->next)
{
struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
eclip.num_rect = count;
eclip.wid = wnd->wid;
count ++;
/* send to destination window */
rtgui_thread_send(wnd->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
/* reset clip info in title */
if (wnd->title != RT_NULL)
{
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), &eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
&(RTGUI_WIDGET(wnd->title)->clip),
&(wnd->extent));
}
}
rtgui_topwin_activate_win(topwin);
}
}
#else
void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender)
{
struct rtgui_topwin* topwin;
/* find the topwin node */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (topwin)
{
rt_int32_t count;
struct rtgui_list_node* node;
struct rtgui_event_clip_info* eclip;
struct rtgui_rect* rect;
/* the window is already placed in front */
if (&(topwin->list) == _rtgui_topwin_show_list.next)
{
rtgui_server_focus_topwin = RT_NULL;
rtgui_topwin_activate_win(topwin);
return ;
}
/* update clip info */
count = 0;
node = _rtgui_topwin_show_list.next;
while (node != &(topwin->list))
{
count ++;
node = node->next;
}
eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ (count + 1)* sizeof(struct rtgui_rect));
/* reset clip info to top window */
RTGUI_EVENT_CLIP_INFO_INIT(eclip);
eclip->num_rect = 0;
eclip->wid = topwin->wid;
/* send to destination window */
rtgui_thread_send(topwin->tid, &(eclip->parent), sizeof(struct rtgui_event_clip_info));
/* reset clip info in title */
if (topwin->title != RT_NULL)
{
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(topwin->title), eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
&(RTGUI_WIDGET(topwin->title)->clip),
&(topwin->extent));
}
rect = RTGUI_EVENT_GET_RECT(eclip, 0);
*rect = (topwin->title != RT_NULL)? RTGUI_WIDGET(topwin->title)->extent : topwin->extent;
count = 1;
for (node = _rtgui_topwin_show_list.next;
node != &(topwin->list);
node = node->next)
{
struct rtgui_topwin* wnd;
wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
eclip->num_rect = count;
eclip->wid = wnd->wid;
/* send to destination window */
rtgui_thread_send(wnd->tid, &(eclip->parent),
sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
/* reset clip info in title */
if (wnd->title != RT_NULL)
{
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
&(RTGUI_WIDGET(wnd->title)->clip),
&(wnd->extent));
}
rect = RTGUI_EVENT_GET_RECT(eclip, count++);
*rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
}
/* release clip info event */
rtgui_free(eclip);
/* remove node from list */
rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
/* add to front */
rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list));
rtgui_topwin_activate_win(topwin);
}
}
#endif
/* show a window */
void rtgui_topwin_show(struct rtgui_event_win* event)
{
struct rtgui_topwin* topwin;
struct rtgui_win* wid = event->wid;
rt_thread_t sender = RTGUI_EVENT(event)->sender;
/* find in hide list */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
/* find it */
if (topwin != RT_NULL)
{
/* remove node from hidden list */
rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list));
/* add node to show list */
rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list));
/* show window title */
if (topwin->title != RT_NULL)
{
RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->title));
}
/* update clip info */
rtgui_topwin_update_clip();
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
/* activate this window */
rtgui_topwin_activate_win(topwin);
}
else
{
/* the wnd is located in show list, raise wnd to front */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (topwin != RT_NULL)
{
if (_rtgui_topwin_show_list.next != &(topwin->list))
{
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
/* not the front window, raise it */
rtgui_topwin_raise(wid, sender);
}
else
{
/* just raise it */
rtgui_topwin_raise(wid, sender);
}
}
else
{
/* there is no wnd in wnd list */
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
}
}
}
/* send clip info to panel */
#ifdef RTGUI_USING_SMALL_SIZE
void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel)
{
rt_uint32_t count;
rt_thread_t tid;
struct rtgui_list_node* node;
struct rtgui_event_clip_info eclip;
/* get topwin count */
count = 0;
node = _rtgui_topwin_show_list.next;
while (node != RT_NULL)
{
count ++;
node = node->next;
}
/* send clip info event to panel */
RTGUI_EVENT_CLIP_INFO_INIT(&eclip);
eclip.num_rect = count; eclip.wid = RT_NULL;
/* send to the activated thread of panel */
tid = rtgui_panel_get_active_thread(panel);
rtgui_thread_send(tid, &eclip.parent, sizeof(struct rtgui_event_clip_info));
}
#else
void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel)
{
rt_uint32_t count;
rt_thread_t tid;
struct rtgui_list_node* node;
struct rtgui_event_clip_info* eclip;
/* get topwin count */
count = 0;
node = _rtgui_topwin_show_list.next;
while (node != RT_NULL)
{
count ++;
node = node->next;
}
eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ (count + 1)* sizeof(struct rtgui_rect));
if (eclip == RT_NULL)
{
/* no memory */
return ;
}
/* reset clip info to top window */
RTGUI_EVENT_CLIP_INFO_INIT(eclip);
eclip->num_rect = count; eclip->wid = RT_NULL;
count = 0;
for (node = _rtgui_topwin_show_list.next; node != RT_NULL; node = node->next)
{
struct rtgui_topwin* wnd;
struct rtgui_rect* rect;
wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
rect = RTGUI_EVENT_GET_RECT(eclip, count++);
*rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
}
/* send to the activated thread of panel */
tid = rtgui_panel_get_active_thread(panel);
rtgui_thread_send(tid, (struct rtgui_event*)eclip, sizeof(struct rtgui_event_clip_info)
+ count* sizeof(struct rtgui_rect));
/* release clip info event */
rtgui_free(eclip);
}
#endif
/* hide a window */
void rtgui_topwin_hide(struct rtgui_event_win* event)
{
struct rtgui_topwin* topwin;
struct rtgui_win* wid = event->wid;
/* find in show list */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
/* found it */
if (topwin)
{
/* remove node from show list */
rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
/* add node to hidden list */
rtgui_list_insert(&_rtgui_topwin_hide_list, &(topwin->list));
/* show window title */
if (topwin->title != RT_NULL)
{
RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->title));
}
/* update clip info */
rtgui_topwin_update_clip();
/* redraw the old rect */
rtgui_topwin_redraw(&(topwin->extent));
if (rtgui_server_focus_topwin == topwin)
{
/* activate the next window */
if (_rtgui_topwin_show_list.next != RT_NULL)
{
/* get the topwin */
topwin = rtgui_list_entry(_rtgui_topwin_show_list.next,
struct rtgui_topwin, list);
rtgui_server_focus_topwin = RT_NULL;
rtgui_topwin_activate_win(topwin);
}
else
{
/* there is no shown window right now */
rtgui_server_focus_topwin = RT_NULL;
}
}
}
else
{
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
return;
}
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
}
/* move top window */
void rtgui_topwin_move(struct rtgui_event_win_move* event)
{
struct rtgui_topwin* topwin;
/* find in show list */
topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_show_list);
if (topwin != RT_NULL)
{
int dx, dy;
rtgui_rect_t rect; /* the old topwin coverage area */
struct rtgui_list_node* node;
/* send status ok */
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
/* get the delta move x, y */
dx = event->x - topwin->extent.x1;
dy = event->y - topwin->extent.y1;
rect = topwin->extent;
/* move window rect */
rtgui_rect_moveto(&(topwin->extent), dx, dy);
/* move window title */
if (topwin->title != RT_NULL)
{
rect = RTGUI_WIDGET(topwin->title)->extent;
rtgui_widget_move_to_logic(RTGUI_WIDGET(topwin->title), dx, dy);
}
/* move the monitor rect list */
rtgui_list_foreach(node, &(topwin->monitor_list))
{
struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node,
struct rtgui_mouse_monitor,
list);
rtgui_rect_moveto(&(monitor->rect), dx, dy);
}
/* update windows clip info */
rtgui_topwin_update_clip();
/* update top window title */
if (topwin->title != RT_NULL) rtgui_theme_draw_win(topwin);
if (rtgui_rect_is_intersect(&rect, &(topwin->extent)) != RT_EOK)
{
/*
* the old rect is not intersect with moved rect,
* re-paint window
*/
struct rtgui_event_paint epaint;
RTGUI_EVENT_PAINT_INIT(&epaint);
epaint.wid = topwin->wid;
rtgui_thread_send(topwin->tid, &(epaint.parent), sizeof(epaint));
}
/* update old window coverage area */
rtgui_topwin_redraw(&rect);
}
else
{
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
}
}
/*
* resize a top win
* Note: currently, only support resize hidden window
*/
void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r)
{
struct rtgui_topwin* topwin;
/* find in show list */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (topwin)
{
topwin->extent = *r;
if (topwin->title != RT_NULL)
{
/* get win extent */
rtgui_rect_t rect = topwin->extent;
/* add border rect */
if (topwin->flag & WINTITLE_BORDER)
{
rtgui_rect_inflate(&rect, WINTITLE_BORDER_SIZE);
}
/* add title rect */
if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT;
RTGUI_WIDGET(topwin->title)->extent = rect;
/* update title & border clip info */
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
&(RTGUI_WIDGET(topwin->title)->clip),
&(topwin->extent));
}
}
}
struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y)
{
struct rtgui_list_node* node;
struct rtgui_topwin* topwin;
/* search in list */
rtgui_list_foreach(node, &(_rtgui_topwin_show_list))
{
topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
/* is this window? */
if ((topwin->title != RT_NULL) &&
rtgui_rect_contains_point(&(RTGUI_WIDGET(topwin->title)->extent), x, y) == RT_EOK)
{
return topwin;
}
else if (rtgui_rect_contains_point(&(topwin->extent), x, y) == RT_EOK)
{
return topwin;
}
}
return RT_NULL;
}
extern struct rtgui_list_node _rtgui_panel_list;
#ifdef RTGUI_USING_SMALL_SIZE
static void rtgui_topwin_update_clip()
{
rt_int32_t count = 0;
struct rtgui_event_clip_info eclip;
struct rtgui_list_node* node = _rtgui_topwin_show_list.next;
RTGUI_EVENT_CLIP_INFO_INIT(&eclip);
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
struct rtgui_topwin* wnd;
wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
eclip.num_rect = count;
eclip.wid = wnd->wid;
count ++;
/* send to destination window */
rtgui_thread_send(wnd->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
/* update clip in win title */
if (wnd->title != RT_NULL)
{
/* reset clip info */
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), &eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
&(RTGUI_WIDGET(wnd->title)->clip),
&(wnd->extent));
}
}
/* send clip info to each panel */
eclip.wid = RT_NULL;
eclip.num_rect = count;
rtgui_list_foreach(node, &(_rtgui_panel_list))
{
struct rtgui_panel* panel;
struct rtgui_list_node* panel_node;
panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
rtgui_list_foreach(panel_node, &(panel->thread_list))
{
struct rtgui_panel_thread* thread;
thread = rtgui_list_entry(panel_node, struct rtgui_panel_thread, list);
/* send clip info to panel */
rtgui_thread_send(thread->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
}
}
}
#else
static void rtgui_topwin_update_clip()
{
rt_int32_t count = 0;
struct rtgui_event_clip_info* eclip;
struct rtgui_list_node* node = _rtgui_topwin_show_list.next;
/* calculate count */
while (node != RT_NULL)
{
count ++;
node = node->next;
}
eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ count * sizeof(struct rtgui_rect));
RTGUI_EVENT_CLIP_INFO_INIT(eclip);
count = 0;
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
struct rtgui_rect* rect;
struct rtgui_topwin* wnd;
wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
eclip->num_rect = count;
eclip->wid = wnd->wid;
/* send to destination window */
rtgui_thread_send(wnd->tid, &(eclip->parent),
sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
/* update clip in win title */
if (wnd->title != RT_NULL)
{
/* reset clip info */
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
&(RTGUI_WIDGET(wnd->title)->clip),
&(wnd->extent));
}
rect = RTGUI_EVENT_GET_RECT(eclip, count++);
*rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
}
/* send clip info to each panel */
eclip->wid = RT_NULL;
eclip->num_rect = count;
rtgui_list_foreach(node, &(_rtgui_panel_list))
{
struct rtgui_panel* panel;
struct rtgui_list_node* panel_node;
panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
rtgui_list_foreach(panel_node, &(panel->thread_list))
{
struct rtgui_panel_thread* thread;
thread = rtgui_list_entry(panel_node, struct rtgui_panel_thread, list);
/* send clip info to panel */
rtgui_thread_send(thread->tid, &(eclip->parent),
sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
}
}
/* release clip info event */
rtgui_free(eclip);
}
#endif
static void rtgui_topwin_redraw(struct rtgui_rect* rect)
{
struct rtgui_list_node* node;
struct rtgui_event_paint epaint;
RTGUI_EVENT_PAINT_INIT(&epaint);
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
if (rtgui_rect_is_intersect(rect, &(wnd->extent)) == RT_EOK)
{
/* draw window */
epaint.wid = wnd->wid;
rtgui_thread_send(wnd->tid, &(epaint.parent), sizeof(epaint));
/* draw title */
if (wnd->title != RT_NULL)
{
rtgui_theme_draw_win(wnd);
}
}
}
/* redraw the panel */
rtgui_list_foreach(node, &(_rtgui_panel_list))
{
struct rtgui_panel* panel;
panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
if (rtgui_rect_is_intersect(rect, &(panel->extent)) == RT_EOK)
{
rt_thread_t tid;
tid = rtgui_panel_get_active_thread(panel);
if (tid != RT_NULL)
{
/* draw panel */
epaint.wid = RT_NULL;
rtgui_thread_send(tid, &(epaint.parent), sizeof(epaint));
}
}
}
}
void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event)
{
rtgui_rect_t rect;
/* let window to process this mouse event */
if (rtgui_rect_contains_point(&win->extent, event->x, event->y) == RT_EOK)
{
/* send mouse event to thread */
rtgui_thread_send(win->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
return;
}
/* get close button rect (device value) */
rect.x1 = RTGUI_WIDGET(win->title)->extent.x2 - WINTITLE_BORDER_SIZE - WINTITLE_CB_WIDTH - 3;
rect.y1 = RTGUI_WIDGET(win->title)->extent.y1 + WINTITLE_BORDER_SIZE + 3;
rect.x2 = rect.x1 + WINTITLE_CB_WIDTH;
rect.y2 = rect.y1 + WINTITLE_CB_HEIGHT;
if (event->button & RTGUI_MOUSE_BUTTON_LEFT)
{
if (event->button & RTGUI_MOUSE_BUTTON_DOWN)
{
if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
{
win->flag |= WINTITLE_CB_PRESSED;
rtgui_theme_draw_win(win);
}
else
{
/* maybe move window */
rtgui_winrect_set(win);
}
}
else if (event->button & RTGUI_MOUSE_BUTTON_UP)
{
if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
{
struct rtgui_event_win event;
win->flag &= ~WINTITLE_CB_PRESSED;
rtgui_theme_draw_win(win);
/* send close event to window */
RTGUI_EVENT_WIN_CLOSE_INIT(&event);
event.wid = win->wid;
rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
}
}
}
}
void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect)
{
struct rtgui_topwin* win;
/* parameters check */
if (wid == RT_NULL || rect == RT_NULL) return;
/* find topwin */
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (win == RT_NULL)
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (win == RT_NULL) return;
/* append rect to top window monitor rect list */
rtgui_mouse_monitor_append(&(win->monitor_list), rect);
}
void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect)
{
struct rtgui_topwin* win;
/* parameters check */
if (wid == RT_NULL || rect == RT_NULL) return;
/* find topwin */
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (win == RT_NULL)
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (win == RT_NULL) return;
/* remove rect from top window monitor rect list */
rtgui_mouse_monitor_remove(&(win->monitor_list), rect);
}
#ifdef RTGUI_USING_SMALL_SIZE
/**
* get clip information for topwin
* wid, the self window id. If wid = NULL, get whole topwin clip information.
*
* @return the clip rect information
*/
void rtgui_topwin_get_clipinfo(struct rtgui_rect* rect_list, rt_int32_t count)
{
struct rtgui_rect* rect;
struct rtgui_topwin* topwin;
struct rtgui_list_node* node;
if ((rect_list == RT_NULL) || (count == 0)) return ;
/* set to the header of list */
rect = rect_list;
rt_sem_take(&_rtgui_topwin_lock, RT_WAITING_FOREVER);
/* get all of topwin rect list */
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
if (topwin->title != RT_NULL)
*rect = RTGUI_WIDGET(topwin->title)->extent;
else
*rect = topwin->extent;
rect ++;
count --;
if (count <= 0) break;
}
rt_sem_release(&_rtgui_topwin_lock);
}
#endif
#ifdef RT_USING_FINSH
#include <finsh.h>
void rtgui_topwin_dump()
{
struct rtgui_list_node* node;
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
rt_kprintf("wnd at (%d, %d) - (%d, %d)\n",
wnd->extent.x1, wnd->extent.y1, wnd->extent.x2, wnd->extent.y2);
if (wnd->title != RT_NULL)
{
rt_kprintf("title[%s] border (%d, %d) - (%d, %d)\n", wnd->title->title,
RTGUI_WIDGET(wnd->title)->extent.x1, RTGUI_WIDGET(wnd->title)->extent.y1,
RTGUI_WIDGET(wnd->title)->extent.x2, RTGUI_WIDGET(wnd->title)->extent.y2);
}
}
}
FINSH_FUNCTION_EXPORT(rtgui_topwin_dump, dump topwindow list);
#endif