summaryrefslogtreecommitdiff
path: root/components/rtgui/server
diff options
context:
space:
mode:
Diffstat (limited to 'components/rtgui/server')
-rw-r--r--components/rtgui/server/mouse.c2
-rw-r--r--components/rtgui/server/panel.c315
-rw-r--r--components/rtgui/server/panel.h72
-rw-r--r--components/rtgui/server/rtgui_application.c673
-rw-r--r--components/rtgui/server/server.c601
-rw-r--r--components/rtgui/server/topwin.c1255
-rw-r--r--components/rtgui/server/topwin.h22
7 files changed, 1596 insertions, 1344 deletions
diff --git a/components/rtgui/server/mouse.c b/components/rtgui/server/mouse.c
index 8d851f0f85..c7a05aac4b 100644
--- a/components/rtgui/server/mouse.c
+++ b/components/rtgui/server/mouse.c
@@ -432,7 +432,7 @@ static void rtgui_winrect_show()
rt_uint16_t x, y;
rtgui_color_t c;
rtgui_rect_t screen_rect, win_rect, win_rect_inner;
- void (*set_pixel) (rtgui_color_t *c, rt_base_t x, rt_base_t y);
+ void (*set_pixel) (rtgui_color_t *c, int x, int y);
c = black;
set_pixel = rtgui_graphic_driver_get_default()->ops->set_pixel;
diff --git a/components/rtgui/server/panel.c b/components/rtgui/server/panel.c
deleted file mode 100644
index f9cd93a578..0000000000
--- a/components/rtgui/server/panel.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * File : panel.c
- * This file is part of RTGUI in 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-04 Bernard first version
- */
-
-#include "panel.h"
-#include "mouse.h"
-
-#include <rtgui/rtgui_system.h>
-
-/* the global parameter */
-struct rtgui_list_node _rtgui_panel_list = {RT_NULL};
-
-void rtgui_panel_register(char* name, rtgui_rect_t* extent)
-{
- register rt_base_t temp;
- struct rtgui_panel* panel;
-
- panel = rtgui_panel_find(name);
- if (panel != RT_NULL )
- {
- /* there are already a same named panel exist. */
- return;
- }
-
- panel = rtgui_malloc(sizeof(struct rtgui_panel));
- if (panel == RT_NULL)
- {
- /* can't alloc memory */
- return;
- }
-
- /* copy name */
- for (temp = 0; temp < RTGUI_NAME_MAX; temp ++)
- {
- panel->name[temp] = name[temp];
- }
-
- /* copy extent */
- panel->extent = *extent;
-
- panel->wm_thread = RT_NULL;
- panel->is_focusable = RT_TRUE;
-
- /* init list */
- rtgui_list_init(&(panel->sibling));
- rtgui_list_init(&(panel->thread_list));
-
- /* add panel to panel list */
- rtgui_list_insert(&_rtgui_panel_list, &(panel->sibling));
-}
-
-void rtgui_panel_deregister(char* name)
-{
- struct rtgui_panel* panel;
-
- panel = rtgui_panel_find(name);
- if (panel != RT_NULL)
- {
- rtgui_list_remove(&_rtgui_panel_list, &(panel->sibling));
-
- /* free pane node */
- rtgui_free(panel);
- }
-}
-
-/* set default focused panel, please use it after registered panel */
-void rtgui_panel_set_default_focused(char* name)
-{
- extern struct rtgui_panel* rtgui_server_focus_panel;
- struct rtgui_panel* panel;
-
- panel = rtgui_panel_find(name);
- if (panel != RT_NULL)
- {
- rtgui_server_focus_panel = panel;
- }
-}
-
-void rtgui_panel_set_nofocused(char* name)
-{
- extern struct rtgui_panel* rtgui_server_focus_panel;
- struct rtgui_panel* panel;
-
- panel = rtgui_panel_find(name);
- if (panel != RT_NULL)
- {
- panel->is_focusable = RT_FALSE;
- }
-}
-
-struct rtgui_panel* rtgui_panel_find(char* name)
-{
- struct rtgui_list_node* node;
- struct rtgui_panel* panel;
-
- rtgui_list_foreach(node, &_rtgui_panel_list)
- {
- panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
-
- if (rt_strncmp(panel->name, name, RTGUI_NAME_MAX) == 0)
- {
- return panel;
- }
- }
-
- return RT_NULL;
-}
-
-struct rtgui_panel* rtgui_panel_thread_add(char* name, rt_thread_t tid)
-{
- struct rtgui_panel* panel;
-
- panel = rtgui_panel_find(name);
- if (panel != RT_NULL )
- {
- struct rtgui_panel_thread* thread;
-
- /* allocate panel thread node */
- thread = rtgui_malloc(sizeof(struct rtgui_panel_thread));
- if (thread == RT_NULL)
- {
- return RT_NULL;
- }
-
- /* construct panel thread node */
- thread->tid = tid;
-
- /* init list */
- rtgui_list_init(&(thread->list));
- rtgui_list_init(&(thread->monitor_list));
-
- /* append thread to the list */
- rtgui_list_append(&(panel->thread_list), &(thread->list));
- }
-
- return panel;
-}
-
-void rtgui_panel_thread_remove(rtgui_panel_t* panel, rt_thread_t tid)
-{
- if (panel != RT_NULL )
- {
- struct rtgui_list_node* node;
- struct rtgui_panel_thread* thread;
-
- rtgui_list_foreach(node, &(panel->thread_list))
- {
- thread = rtgui_list_entry(node, struct rtgui_panel_thread, list);
- if (thread->tid == tid)
- {
- /* remove node from list */
- rtgui_list_remove(&(panel->thread_list), &(thread->list));
-
- /* free the panel thread node */
- rtgui_free(thread);
- return;
- }
- }
- }
-}
-
-rt_thread_t rtgui_panel_get_active_thread(rtgui_panel_t* panel)
-{
- if (panel != RT_NULL)
- {
- if (panel->thread_list.next != RT_NULL)
- {
- struct rtgui_panel_thread* thread;
- thread = rtgui_list_entry(panel->thread_list.next, struct rtgui_panel_thread, list);
-
- return thread->tid;
- }
- }
-
- return RT_NULL;
-}
-
-void rtgui_panel_set_active_thread(rtgui_panel_t* panel, rt_thread_t tid)
-{
- /* get old active thread */
- rt_thread_t prev_actived = rtgui_panel_get_active_thread(panel);
- if (prev_actived != tid)
- {
- /* de-active old active workbench */
- struct rtgui_event_panel_hide ehide;
- RTGUI_EVENT_PANEL_HIDE_INIT(&ehide);
-
- ehide.panel = panel;
- ehide.workbench = RT_NULL;
- rtgui_thread_send_urgent(prev_actived, &(ehide.parent), sizeof (ehide));
- }
-
- if (panel != RT_NULL )
- {
- struct rtgui_list_node* node;
- struct rtgui_panel_thread* thread;
-
- rtgui_list_foreach(node, &(panel->thread_list))
- {
- thread = rtgui_list_entry(node, struct rtgui_panel_thread, list);
- if (thread->tid == tid)
- {
- /* remove node from list */
- rtgui_list_remove(&(panel->thread_list), &(thread->list));
-
- /* insert node to the header */
- rtgui_list_insert(&(panel->thread_list), &(thread->list));
- return;
- }
- }
- }
-}
-
-/* deactivate current activated thread -- move it to the end of list */
-void rtgui_panel_deactive_thread(rtgui_panel_t* panel)
-{
- RT_ASSERT(panel == RT_NULL);
-
- if (panel->thread_list.next != RT_NULL)
- {
- struct rtgui_panel_thread* thread;
- thread = rtgui_list_entry(panel->thread_list.next, struct rtgui_panel_thread, list);
-
- /* remove it */
- panel->thread_list.next = thread->list.next;
-
- /* append to the tail of thread list */
- rtgui_list_append(&(panel->thread_list), &(thread->list));
- }
-}
-
-/**
- * get the panel which contains a point(x, y)
- */
-rtgui_panel_t* rtgui_panel_get_contain(int x, int y)
-{
- struct rtgui_list_node* node;
- struct rtgui_panel* panel;
-
- rtgui_list_foreach(node, &(_rtgui_panel_list))
- {
- panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
- if (rtgui_rect_contains_point(&(panel->extent), x, y) == RT_EOK)
- {
- return panel;
- }
- }
-
- return RT_NULL;
-}
-
-/**
- * append a rect to panel mouse monitor rect list
- */
-void rtgui_panel_append_monitor_rect(rtgui_panel_t* panel, rt_thread_t tid, rtgui_rect_t* rect)
-{
- if (panel != RT_NULL )
- {
- struct rtgui_list_node* node;
- struct rtgui_panel_thread* thread;
-
- rtgui_list_foreach(node, &(panel->thread_list))
- {
- thread = rtgui_list_entry(node, struct rtgui_panel_thread, list);
- if (thread->tid == tid)
- {
- /* add the monitor rect to list */
- rtgui_mouse_monitor_append(&(thread->monitor_list), rect);
- return;
- }
- }
- }
-}
-
-/**
- * remove a rect from panel mouse monitor rect list
- */
-void rtgui_panel_remove_monitor_rect(rtgui_panel_t* panel, rt_thread_t tid, rtgui_rect_t* rect)
-{
- if (panel != RT_NULL )
- {
- struct rtgui_list_node* node;
- struct rtgui_panel_thread* thread;
-
- rtgui_list_foreach(node, &(panel->thread_list))
- {
- thread = rtgui_list_entry(node, struct rtgui_panel_thread, list);
- if (thread->tid == tid)
- {
- /* remove the monitor rect from list */
- rtgui_mouse_monitor_remove(&(thread->monitor_list), rect);
- return;
- }
- }
- }
-}
-
-void rtgui_panel_set_wm(rtgui_panel_t* panel, rt_thread_t wm)
-{
- RT_ASSERT(wm != RT_NULL);
- RT_ASSERT(panel != RT_NULL);
-
- panel->wm_thread = wm;
-}
-
diff --git a/components/rtgui/server/panel.h b/components/rtgui/server/panel.h
deleted file mode 100644
index 559ddc4307..0000000000
--- a/components/rtgui/server/panel.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * File : panel.h
- * This file is part of RTGUI in 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-04 Bernard first version
- */
-
-#ifndef __RT_PANEL_H__
-#define __RT_PANEL_H__
-
-#include <rtgui/rtgui.h>
-#include <rtgui/list.h>
-#include <rtgui/region.h>
-
-struct rtgui_panel_thread
-{
- /* thread id */
- rt_thread_t tid;
-
- /* the list of thread */
- rtgui_list_t list;
-
- /* monitor rect list */
- rtgui_list_t monitor_list;
-};
-typedef struct rtgui_panel_thread rtgui_panel_thread_list_t;
-
-struct rtgui_panel
-{
- char name[RTGUI_NAME_MAX];
-
- /* the extent of panel */
- rtgui_rect_t extent;
-
- /* the list of panel */
- rtgui_list_t sibling;
-
- /* the thread list in this panel */
- rtgui_list_t thread_list;
-
- /* the workbench manager thread */
- rt_thread_t wm_thread;
-
- /* is focusable */
- rt_bool_t is_focusable;
-};
-
-/* find panel by name */
-struct rtgui_panel* rtgui_panel_find(char* name);
-
-/* add or remove application thread from specified panel */
-rtgui_panel_t* rtgui_panel_thread_add(char* name, rt_thread_t tid);
-void rtgui_panel_thread_remove(rtgui_panel_t* panel, rt_thread_t tid);
-
-rt_thread_t rtgui_panel_get_active_thread(rtgui_panel_t* panel);
-void rtgui_panel_set_active_thread(rtgui_panel_t* panel, rt_thread_t tid);
-
-rtgui_panel_t* rtgui_panel_get_contain(int x, int y);
-void rtgui_panel_set_wm(rtgui_panel_t* panel, rt_thread_t wm);
-
-void rtgui_panel_append_monitor_rect(rtgui_panel_t* panel, rt_thread_t tid, rtgui_rect_t* rect);
-void rtgui_panel_remove_monitor_rect(rtgui_panel_t* panel, rt_thread_t tid, rtgui_rect_t* rect);
-
-#endif
-
diff --git a/components/rtgui/server/rtgui_application.c b/components/rtgui/server/rtgui_application.c
new file mode 100644
index 0000000000..97de7bd17a
--- /dev/null
+++ b/components/rtgui/server/rtgui_application.c
@@ -0,0 +1,673 @@
+/*
+ * File : rtgui_application.c
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 2012, 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
+ * 2012-01-13 Grissiom first version(just a prototype of application API)
+ */
+
+#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_application.h>
+#include <rtgui/widgets/window.h>
+
+#ifdef _WIN32
+#define RTGUI_EVENT_DEBUG
+#endif
+
+#ifdef RTGUI_EVENT_DEBUG
+const char *event_string[] =
+{
+ /* window event */
+ "WIN_CREATE", /* create a window */
+ "WIN_DESTROY", /* destroy a window */
+ "WIN_SHOW", /* show a window */
+ "WIN_HIDE", /* hide a window */
+ "WIN_ACTIVATE", /* activate a window */
+ "WIN_DEACTIVATE", /* deactivate a window */
+ "WIN_CLOSE", /* close a window */
+ "WIN_MOVE", /* move a window */
+ "WIN_RESIZE", /* resize a window */
+ "WIN_MODAL_ENTER", /* a window modals */
+
+ "SET_WM", /* set window manager */
+
+ "UPDATE_BEGIN", /* begin of update rect */
+ "UPDATE_END", /* end of update rect */
+ "MONITOR_ADD", /* add a monitor rect */
+ "MONITOR_REMOVE", /* remove a monitor rect*/
+ "PAINT", /* paint on screen */
+ "TIMER", /* timer */
+
+ /* clip rect information */
+ "CLIP_INFO", /* clip rect info */
+
+ /* mouse and keyboard event */
+ "MOUSE_MOTION", /* mouse motion */
+ "MOUSE_BUTTON", /* mouse button info */
+ "KBD", /* keyboard info */
+
+ /* user command event */
+ "COMMAND", /* user command */
+
+ /* request's status event */
+ "STATUS", /* request result */
+ "SCROLLED", /* scroll bar scrolled */
+ "RESIZE", /* widget resize */
+};
+
+#define DBG_MSG(x) rt_kprintf x
+
+static void rtgui_event_dump(rt_thread_t tid, rtgui_event_t* event)
+{
+ char* sender = "(unknown)";
+
+ if ((event->type == RTGUI_EVENT_TIMER) ||
+ (event->type == RTGUI_EVENT_UPDATE_BEGIN) ||
+ (event->type == RTGUI_EVENT_MOUSE_MOTION) ||
+ (event->type == RTGUI_EVENT_UPDATE_END))
+ {
+ /* don't dump timer event */
+ return ;
+ }
+
+ if (event->sender != RT_NULL)
+ sender = event->sender->name;
+
+ rt_kprintf("%s -- %s --> %s ", sender, event_string[event->type], tid->name);
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ {
+ struct rtgui_event_paint *paint = (struct rtgui_event_paint *)event;
+
+ if(paint->wid != RT_NULL)
+ rt_kprintf("win: %s", paint->wid->title);
+ }
+ break;
+
+ case RTGUI_EVENT_KBD:
+ {
+ struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd*) event;
+ if (ekbd->wid != RT_NULL)
+ rt_kprintf("win: %s", ekbd->wid->title);
+ if (RTGUI_KBD_IS_UP(ekbd)) rt_kprintf(", up");
+ else rt_kprintf(", down");
+ }
+ break;
+
+ case RTGUI_EVENT_CLIP_INFO:
+ {
+ struct rtgui_event_clip_info *info = (struct rtgui_event_clip_info *)event;
+
+ if(info->wid != RT_NULL)
+ rt_kprintf("win: %s", info->wid->title);
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_CREATE:
+ {
+ struct rtgui_event_win_create *create = (struct rtgui_event_win_create*)event;
+
+ rt_kprintf(" win: %s at (x1:%d, y1:%d, x2:%d, y2:%d), addr: %p",
+#ifdef RTGUI_USING_SMALL_SIZE
+ create->wid->title,
+ RTGUI_WIDGET(create->wid)->extent.x1,
+ RTGUI_WIDGET(create->wid)->extent.y1,
+ RTGUI_WIDGET(create->wid)->extent.x2,
+ RTGUI_WIDGET(create->wid)->extent.y2,
+#else
+ create->title,
+ create->extent.x1,
+ create->extent.y1,
+ create->extent.x2,
+ create->extent.y2,
+#endif
+ create->wid
+ );
+ }
+ break;
+
+ case RTGUI_EVENT_UPDATE_END:
+ {
+ struct rtgui_event_update_end* update_end = (struct rtgui_event_update_end*)event;
+ rt_kprintf("(x:%d, y1:%d, x2:%d, y2:%d)", update_end->rect.x1,
+ update_end->rect.y1,
+ update_end->rect.x2,
+ update_end->rect.y2);
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_ACTIVATE:
+ case RTGUI_EVENT_WIN_DEACTIVATE:
+ case RTGUI_EVENT_WIN_SHOW:
+ case RTGUI_EVENT_WIN_MODAL_ENTER:
+ {
+ struct rtgui_event_win *win = (struct rtgui_event_win *)event;
+
+ if(win->wid != RT_NULL)
+ rt_kprintf("win: %s", win->wid->title);
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_MOVE:
+ {
+ struct rtgui_event_win_move *win = (struct rtgui_event_win_move *)event;
+
+ if(win->wid != RT_NULL)
+ {
+ rt_kprintf("win: %s", win->wid->title);
+ rt_kprintf(" to (x:%d, y:%d)", win->x, win->y);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_RESIZE:
+ {
+ struct rtgui_event_win_resize* win = (struct rtgui_event_win_resize *)event;
+
+ if (win->wid != RT_NULL)
+ {
+ rt_kprintf("win: %s, rect(x1:%d, y1:%d, x2:%d, y2:%d)", win->wid->title,
+ RTGUI_WIDGET(win->wid)->extent.x1,
+ RTGUI_WIDGET(win->wid)->extent.y1,
+ RTGUI_WIDGET(win->wid)->extent.x2,
+ RTGUI_WIDGET(win->wid)->extent.y2);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ case RTGUI_EVENT_MOUSE_MOTION:
+ {
+ struct rtgui_event_mouse *mouse = (struct rtgui_event_mouse*)event;
+
+ if (mouse->button & RTGUI_MOUSE_BUTTON_LEFT) rt_kprintf("left ");
+ else rt_kprintf("right ");
+
+ if (mouse->button & RTGUI_MOUSE_BUTTON_DOWN) rt_kprintf("down ");
+ else rt_kprintf("up ");
+
+ if (mouse->wid != RT_NULL)
+ rt_kprintf("win: %s at (%d, %d)", mouse->wid->title,
+ mouse->x, mouse->y);
+ else
+ rt_kprintf("(%d, %d)", mouse->x, mouse->y);
+ }
+ break;
+
+ case RTGUI_EVENT_MONITOR_ADD:
+ {
+ struct rtgui_event_monitor *monitor = (struct rtgui_event_monitor*)event;
+ if (monitor->wid != RT_NULL)
+ {
+ rt_kprintf("win: %s, the rect is:(%d, %d) - (%d, %d)", monitor->wid->title,
+ monitor->rect.x1, monitor->rect.y1,
+ monitor->rect.x2, monitor->rect.y2);
+ }
+ }
+ break;
+ }
+
+ rt_kprintf("\n");
+}
+#else
+#define DBG_MSG(x)
+#define rtgui_event_dump(tid, event)
+#endif
+
+rt_bool_t rtgui_application_event_handler(struct rtgui_object* obj, rtgui_event_t* event);
+
+static void _rtgui_application_constructor(struct rtgui_application *app)
+{
+ /* set event handler */
+ rtgui_object_set_event_handler(RTGUI_OBJECT(app),
+ rtgui_application_event_handler);
+
+ app->name = RT_NULL;
+ /* set EXITED so we can destroy an application that just created */
+ app->state_flag = RTGUI_APPLICATION_FLAG_EXITED;
+ app->ref_count = 0;
+ app->exit_code = 0;
+ app->tid = RT_NULL;
+ app->server = RT_NULL;
+ app->mq = RT_NULL;
+ app->modal_object = RT_NULL;
+ app->on_idle = RT_NULL;
+}
+
+static void _rtgui_application_destructor(struct rtgui_application *app)
+{
+ RT_ASSERT(app != RT_NULL);
+
+ rt_free(app->name);
+ app->name = RT_NULL;
+}
+
+DEFINE_CLASS_TYPE(application, "application",
+ RTGUI_OBJECT_TYPE,
+ _rtgui_application_constructor,
+ _rtgui_application_destructor,
+ sizeof(struct rtgui_application));
+
+struct rtgui_application* rtgui_application_create(
+ rt_thread_t tid,
+ const char *myname)
+{
+ struct rtgui_application *app;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(myname != RT_NULL);
+
+ /* create application */
+ app = RTGUI_APPLICATION(rtgui_object_create(RTGUI_APPLICATION_TYPE));
+ if (app == RT_NULL)
+ return RT_NULL;
+
+ DBG_MSG(("register a rtgui application(%s) on thread %s\n", myname, tid->name));
+
+ app->tid = tid;
+ /* set user thread */
+ tid->user_data = (rt_uint32_t)app;
+
+ app->mq = rt_mq_create("rtgui", sizeof(union rtgui_event_generic), 32, RT_IPC_FLAG_FIFO);
+ if (app->mq == RT_NULL)
+ {
+ rt_kprintf("mq err\n");
+ goto __mq_err;
+ }
+
+ /* set application title */
+ app->name = (unsigned char*)rt_strdup((char*)myname);
+ if (app->name != RT_NULL)
+ return app;
+
+__mq_err:
+ rtgui_object_destroy(RTGUI_OBJECT(app));
+ tid->user_data = 0;
+ return RT_NULL;
+}
+
+#define _rtgui_application_check(app) \
+do { \
+ RT_ASSERT(app != RT_NULL); \
+ RT_ASSERT(app->tid != RT_NULL); \
+ RT_ASSERT(app->tid->user_data != 0); \
+ RT_ASSERT(app->mq != RT_NULL); \
+} while (0)
+
+void rtgui_application_destroy(struct rtgui_application *app)
+{
+ _rtgui_application_check(app);
+
+ if (!(app->state_flag & RTGUI_APPLICATION_FLAG_EXITED))
+ {
+ rt_kprintf("cannot destroy a running application: %s.\n",
+ app->name);
+ return;
+ }
+
+ app->tid->user_data = 0;
+ rt_mq_delete(app->mq);
+ rtgui_object_destroy(RTGUI_OBJECT(app));
+}
+
+struct rtgui_application* rtgui_application_self(void)
+{
+ struct rtgui_application *app;
+ rt_thread_t self;
+
+ /* get current thread */
+ self = rt_thread_self();
+ app = (struct rtgui_application*)(self->user_data);
+
+ return app;
+}
+
+void rtgui_application_set_onidle(rtgui_idle_func onidle)
+{
+ struct rtgui_application *app;
+
+ app = rtgui_application_self();
+ if (app != RT_NULL)
+ app->on_idle = onidle;
+}
+
+rtgui_idle_func rtgui_application_get_onidle(void)
+{
+ struct rtgui_application *app;
+
+ app = rtgui_application_self();
+ if (app != RT_NULL)
+ return app->on_idle;
+ else
+ return RT_NULL;
+}
+
+extern rt_thread_t rt_thread_find(char* name);
+rt_thread_t rtgui_application_get_server(void)
+{
+ return rt_thread_find("rtgui");
+}
+
+rt_err_t rtgui_application_send(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+ rt_err_t result;
+ struct rtgui_application *app;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ rtgui_event_dump(tid, event);
+
+ /* find struct rtgui_application */
+ app = (struct rtgui_application*) (tid->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ result = rt_mq_send(app->mq, event, event_size);
+ if (result != RT_EOK)
+ {
+ if (event->type != RTGUI_EVENT_TIMER)
+ rt_kprintf("send event to %s failed\n", app->tid->name);
+ }
+
+ return result;
+}
+
+rt_err_t rtgui_application_send_urgent(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+ rt_err_t result;
+ struct rtgui_application *app;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ rtgui_event_dump(tid, event);
+
+ /* find rtgui_application */
+ app = (struct rtgui_application*) (tid->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ result = rt_mq_urgent(app->mq, event, event_size);
+ if (result != RT_EOK)
+ rt_kprintf("send ergent event failed\n");
+
+ return result;
+}
+
+rt_err_t rtgui_application_send_sync(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+ rt_err_t r;
+ struct rtgui_application *app;
+ rt_int32_t ack_buffer, ack_status;
+ struct rt_mailbox ack_mb;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ rtgui_event_dump(tid, event);
+
+ /* init ack mailbox */
+ r = rt_mb_init(&ack_mb, "ack", &ack_buffer, 1, 0);
+ if (r!= RT_EOK)
+ goto __return;
+
+ app = (struct rtgui_application*) (tid->user_data);
+ if (app == RT_NULL)
+ {
+ r = -RT_ERROR;
+ goto __return;
+ }
+
+ event->ack = &ack_mb;
+ r = rt_mq_send(app->mq, event, event_size);
+ if (r != RT_EOK)
+ {
+ rt_kprintf("send sync event failed\n");
+ goto __return;
+ }
+
+ r = rt_mb_recv(&ack_mb, (rt_uint32_t*)&ack_status, RT_WAITING_FOREVER);
+ if (r!= RT_EOK)
+ goto __return;
+
+ if (ack_status != RTGUI_STATUS_OK)
+ r = -RT_ERROR;
+ else
+ r = RT_EOK;
+
+__return:
+ /* fini ack mailbox */
+ rt_mb_detach(&ack_mb);
+ return r;
+}
+
+rt_err_t rtgui_application_ack(rtgui_event_t* event, rt_int32_t status)
+{
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event->ack != RT_NULL);
+
+ rt_mb_send(event->ack, status);
+
+ return RT_EOK;
+}
+
+rt_err_t rtgui_application_recv(rtgui_event_t* event, rt_size_t event_size)
+{
+ struct rtgui_application* app;
+ rt_err_t r;
+
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ app = (struct rtgui_application*) (rt_thread_self()->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ r = rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER);
+
+ return r;
+}
+
+rt_err_t rtgui_application_recv_nosuspend(rtgui_event_t* event, rt_size_t event_size)
+{
+ struct rtgui_application *app;
+ rt_err_t r;
+
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event != 0);
+
+ app = (struct rtgui_application*) (rt_thread_self()->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ r = rt_mq_recv(app->mq, event, event_size, 0);
+
+ return r;
+}
+
+rt_err_t rtgui_application_recv_filter(rt_uint32_t type, rtgui_event_t* event, rt_size_t event_size)
+{
+ struct rtgui_application *app;
+
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ app = (struct rtgui_application*) (rt_thread_self()->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ while (rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER) == RT_EOK)
+ {
+ if (event->type == type)
+ {
+ return RT_EOK;
+ }
+ else
+ {
+ if (RTGUI_OBJECT(app)->event_handler != RT_NULL)
+ {
+ RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+ }
+ }
+ }
+
+ return -RT_ERROR;
+}
+
+rt_inline rt_bool_t _rtgui_application_dest_handle(
+ struct rtgui_application *app,
+ struct rtgui_event *event)
+{
+ struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
+
+ struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
+
+ if (dest_object != RT_NULL)
+ {
+ if (dest_object->event_handler != RT_NULL)
+ return dest_object->event_handler(RTGUI_OBJECT(dest_object), event);
+ else
+ return RT_FALSE;
+ }
+ else
+ {
+ rt_kprintf("RTGUI ERROR:server sent a event(%d) without wid\n", event->type);
+ return RT_FALSE;
+ }
+}
+
+rt_bool_t rtgui_application_event_handler(struct rtgui_object* object, rtgui_event_t* event)
+{
+ struct rtgui_application* app;
+
+ RT_ASSERT(object != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+
+ app = RTGUI_APPLICATION(object);
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ case RTGUI_EVENT_CLIP_INFO:
+ case RTGUI_EVENT_WIN_ACTIVATE:
+ case RTGUI_EVENT_WIN_DEACTIVATE:
+ case RTGUI_EVENT_WIN_CLOSE:
+ case RTGUI_EVENT_WIN_MOVE:
+ case RTGUI_EVENT_KBD:
+ _rtgui_application_dest_handle(app, event);
+ break;
+
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ case RTGUI_EVENT_MOUSE_MOTION:
+ {
+ struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
+ struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
+
+ // FIXME: let application determine the dest_wiget but not in sever
+ // so we can combine this handler with above one
+ if (app->modal_object != RT_NULL &&
+ dest_object != app->modal_object)
+ {
+// rt_kprintf("discard event %s that is not sent to modal object\n",
+// event_string[event->type]);
+ }
+ else
+ {
+ _rtgui_application_dest_handle(app, event);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_TIMER:
+ {
+ struct rtgui_timer* timer;
+ struct rtgui_event_timer* etimer = (struct rtgui_event_timer*) event;
+
+ timer = etimer->timer;
+ if (timer->timeout != RT_NULL)
+ {
+ /* call timeout function */
+ timer->timeout(timer, timer->user_data);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_COMMAND:
+ {
+ struct rtgui_event_command *ecmd = (struct rtgui_event_command*)event;
+
+ if (ecmd->wid != RT_NULL)
+ return _rtgui_application_dest_handle(app, event);
+ }
+
+ default:
+ return rtgui_object_event_handler(object, event);
+ }
+
+ return RT_TRUE;
+}
+
+rt_inline void _rtgui_application_event_loop(struct rtgui_application *app)
+{
+ rt_err_t result;
+ rt_uint16_t current_ref;
+ struct rtgui_event *event;
+
+ _rtgui_application_check(app);
+
+ /* point to event buffer */
+ event = (struct rtgui_event*)app->event_buffer;
+
+ current_ref = ++app->ref_count;
+
+ while (current_ref <= app->ref_count)
+ {
+ RT_ASSERT(current_ref == app->ref_count);
+
+ if (app->on_idle != RT_NULL)
+ {
+ result = rtgui_application_recv_nosuspend(event, sizeof(union rtgui_event_generic));
+ if (result == RT_EOK)
+ RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+ else if (result == -RT_ETIMEOUT)
+ app->on_idle(RTGUI_OBJECT(app), RT_NULL);
+ }
+ else
+ {
+ result = rtgui_application_recv(event, sizeof(union rtgui_event_generic));
+ if (result == RT_EOK)
+ RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+ }
+ }
+}
+
+rt_base_t rtgui_application_run(struct rtgui_application *app)
+{
+ _rtgui_application_check(app);
+
+ app->state_flag &= ~RTGUI_APPLICATION_FLAG_EXITED;
+
+ _rtgui_application_event_loop(app);
+
+ if (app->ref_count == 0)
+ app->state_flag |= RTGUI_APPLICATION_FLAG_EXITED;
+
+ return app->exit_code;
+}
+
+void rtgui_application_exit(struct rtgui_application* app, rt_uint16_t code)
+{
+ --app->ref_count;
+ app->exit_code = code;
+}
diff --git a/components/rtgui/server/server.c b/components/rtgui/server/server.c
index 5b90b64b1b..10ddfbf77a 100644
--- a/components/rtgui/server/server.c
+++ b/components/rtgui/server/server.c
@@ -15,176 +15,15 @@
#include <rtgui/rtgui.h>
#include <rtgui/event.h>
#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_object.h>
+#include <rtgui/rtgui_application.h>
#include <rtgui/driver.h>
#include "mouse.h"
-#include "panel.h"
#include "topwin.h"
static struct rt_thread *rtgui_server_tid;
-static struct rt_messagequeue *rtgui_server_mq;
-
-extern struct rtgui_topwin* rtgui_server_focus_topwin;
-struct rtgui_panel* rtgui_server_focus_panel = RT_NULL;
-
-void rtgui_server_create_application(struct rtgui_event_panel_attach* event)
-{
- struct rtgui_panel* panel = rtgui_panel_find(event->panel_name);
-
- if (panel != RT_NULL)
- {
- struct rtgui_event_panel_info ep;
- RTGUI_EVENT_PANEL_INFO_INIT(&ep);
-
- if (panel->wm_thread != RT_NULL)
- {
- /* notify to workbench */
- rtgui_thread_send(panel->wm_thread, &(event->parent), sizeof(struct rtgui_event_panel_attach));
- }
-
- /* send the responses - ok */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
-
- /* send the panel info */
- ep.panel = panel;
- ep.extent = panel->extent;
- rtgui_thread_send(event->parent.sender, (struct rtgui_event*)&ep, sizeof(ep));
-
- rtgui_panel_thread_add(event->panel_name, event->parent.sender);
- }
- else
- {
- /* send the responses - failure */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_NRC);
- }
-}
-
-void rtgui_server_destroy_application(struct rtgui_event_panel_detach* event)
-{
- struct rtgui_panel* panel = event->panel;
-
- if (panel != RT_NULL)
- {
- if (panel->wm_thread != RT_NULL)
- {
- /* notify to workbench */
- rtgui_thread_send(panel->wm_thread, &(event->parent), sizeof(struct rtgui_event_panel_detach));
- }
-
- /* send the responses */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
-
- rtgui_panel_thread_remove(panel, event->parent.sender);
-
- {
- /* get next thread and active it */
- rt_thread_t tid = rtgui_panel_get_active_thread(panel);
- if (tid != RT_NULL)
- {
- /* let this thread repaint */
- struct rtgui_event_paint epaint;
- RTGUI_EVENT_PAINT_INIT(&epaint);
- epaint.wid = RT_NULL;
- rtgui_thread_send(tid, (struct rtgui_event*)&epaint, sizeof(epaint));
- }
- }
- }
- else
- {
- /* send the responses - failure */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_NRC);
- }
-}
-
-void rtgui_server_thread_panel_show(struct rtgui_event_panel_show* event)
-{
- struct rtgui_panel* panel = event->panel;
-
- if (panel != RT_NULL)
- {
- struct rtgui_event_paint epaint;
-
- /* send the responses */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
-
- if (panel->wm_thread != RT_NULL)
- {
- /* notify to workbench */
- rtgui_thread_send(panel->wm_thread, &(event->parent), sizeof(struct rtgui_event_panel_show));
- }
-
- rtgui_panel_set_active_thread(panel, event->parent.sender);
-
- /* send all topwin clip info */
- rtgui_topwin_update_clip_to_panel(panel);
-
- /* send paint event */
- RTGUI_EVENT_PAINT_INIT(&epaint);
- epaint.wid = RT_NULL;
- rtgui_thread_send(event->parent.sender, (struct rtgui_event*)&epaint,
- sizeof(epaint));
- }
- else
- {
- /* send failed */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
- }
-}
-
-void rtgui_server_thread_panel_hide(struct rtgui_event_panel_hide* event)
-{
- struct rtgui_panel* panel = event->panel;
-
- if (panel != RT_NULL)
- {
- rt_thread_t tid;
-
- /* send the responses */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
-
- if (panel->thread_list.next != RT_NULL)
- {
- struct rtgui_panel_thread* thread;
- thread = rtgui_list_entry(panel->thread_list.next, struct rtgui_panel_thread, list);
-
- /* remove it */
- panel->thread_list.next = thread->list.next;
-
- /* append to the tail of thread list */
- rtgui_list_append(&(panel->thread_list), &(thread->list));
- }
-
- /* send all topwin clip info */
- rtgui_topwin_update_clip_to_panel(panel);
-
- /* get new active thread */
- tid = rtgui_panel_get_active_thread(panel);
- if (tid != RT_NULL)
- {
- struct rtgui_event_paint epaint;
-
- /* send paint event */
- RTGUI_EVENT_PAINT_INIT(&epaint);
- epaint.wid = RT_NULL;
- rtgui_thread_send(tid, (struct rtgui_event*)&epaint, sizeof(epaint));
- }
- }
- else
- {
- /* send failed */
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
- }
-}
-
-void rtgui_server_handle_set_wm(struct rtgui_event_set_wm *event)
-{
- struct rtgui_panel* panel = rtgui_panel_find(event->panel_name);
-
- if (panel != RT_NULL)
- {
- rtgui_panel_set_wm(panel, event->parent.sender);
- }
-}
+static struct rtgui_application *rtgui_server_application;
void rtgui_server_handle_update(struct rtgui_event_update_end* event)
{
@@ -199,36 +38,19 @@ void rtgui_server_handle_update(struct rtgui_event_update_end* event)
void rtgui_server_handle_monitor_add(struct rtgui_event_monitor* event)
{
- if (event->panel != RT_NULL)
- {
- /* append monitor rect to panel list */
- rtgui_panel_append_monitor_rect(event->panel, event->parent.sender, &(event->rect));
- }
- else
- {
- /* add monitor rect to top window list */
- rtgui_topwin_append_monitor_rect(event->wid, &(event->rect));
- }
+ /* add monitor rect to top window list */
+ rtgui_topwin_append_monitor_rect(event->wid, &(event->rect));
}
void rtgui_server_handle_monitor_remove(struct rtgui_event_monitor* event)
{
- if (event->panel != RT_NULL)
- {
- /* add monitor rect to panel list */
- rtgui_panel_remove_monitor_rect(event->panel, event->parent.sender, &(event->rect));
- }
- else
- {
- /* add monitor rect to top window list */
- rtgui_topwin_remove_monitor_rect(event->wid, &(event->rect));
- }
+ /* add monitor rect to top window list */
+ rtgui_topwin_remove_monitor_rect(event->wid, &(event->rect));
}
void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse* event)
{
struct rtgui_topwin* wnd;
- struct rtgui_panel* panel;
/* re-init to server thread */
RTGUI_EVENT_MOUSE_BUTTON_INIT(event);
@@ -263,7 +85,7 @@ void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse* event)
}
/* send to client thread */
- rtgui_thread_send(topwin->tid, &(ewin.parent), sizeof(ewin));
+ rtgui_application_send(topwin->tid, &(ewin.parent), sizeof(ewin));
return;
}
@@ -271,16 +93,15 @@ void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse* event)
#endif
/* get the wnd which contains the mouse */
- wnd = rtgui_topwin_get_wnd(event->x, event->y);
+ wnd = rtgui_topwin_get_wnd_no_modaled(event->x, event->y);
if (wnd != RT_NULL)
{
event->wid = wnd->wid;
- if (rtgui_server_focus_topwin != wnd)
+ if (rtgui_topwin_get_focus() != wnd)
{
/* raise this window */
rtgui_topwin_activate_win(wnd);
- rtgui_server_focus_panel = RT_NULL;
}
if (wnd->title != RT_NULL &&
@@ -291,137 +112,39 @@ void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse* event)
else
{
/* send mouse event to thread */
- rtgui_thread_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_mouse));
+ rtgui_application_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_mouse));
}
return ;
}
-
- /* get the panel which contains the mouse */
- panel = rtgui_panel_get_contain(event->x, event->y);
- if ((panel != RT_NULL) && (panel->is_focusable == RT_TRUE))
- {
- /* deactivate old window */
- if (rtgui_server_focus_topwin != RT_NULL)
- {
- rtgui_topwin_deactivate_win(rtgui_server_focus_topwin);
- }
-
- rtgui_server_focus_panel = panel;
- rtgui_server_focus_topwin = RT_NULL;
-
- /* set destination window to null */
- event->wid = RT_NULL;
-
- /* send mouse event to thread */
- if (rtgui_panel_get_active_thread(panel) != RT_NULL)
- {
- rtgui_thread_send(rtgui_panel_get_active_thread(panel),
- (struct rtgui_event*)event,
- sizeof(struct rtgui_event_mouse));
- }
- }
}
-static struct rtgui_panel* last_monitor_panel = RT_NULL;
static struct rtgui_topwin* last_monitor_topwin = RT_NULL;
void rtgui_server_handle_mouse_motion(struct rtgui_event_mouse* event)
{
/* the topwin contains current mouse */
struct rtgui_topwin* win = RT_NULL;
- struct rtgui_panel* panel = RT_NULL;
/* re-init mouse event */
RTGUI_EVENT_MOUSE_MOTION_INIT(event);
- /* find the panel or topwin which monitor the mouse motion */
- win = rtgui_topwin_get_wnd(event->x, event->y);
- if (win == RT_NULL)
- {
- /* try to find monitor on the panel */
- panel = rtgui_panel_get_contain(event->x, event->y);
-
- if (panel != RT_NULL)
- {
- struct rtgui_panel_thread* thread;
-
- /* get active panel thread */
- if (panel->thread_list.next != RT_NULL)
- {
- thread = rtgui_list_entry(panel->thread_list.next, struct rtgui_panel_thread, list);
- if (!rtgui_mouse_monitor_contains_point(&(thread->monitor_list),
- event->x, event->y) == RT_TRUE)
- {
- /* no monitor in this panel */
- panel = RT_NULL;
- }
- }
- }
- }
- else if (win->monitor_list.next != RT_NULL)
+ win = rtgui_topwin_get_wnd_no_modaled(event->x, event->y);
+ if (win != RT_NULL && win->monitor_list.next != RT_NULL)
{
+ // FIXME:
/* check whether the monitor exist */
- if (rtgui_mouse_monitor_contains_point(&(win->monitor_list), event->x, event->y) != RT_TRUE)
+ if (rtgui_mouse_monitor_contains_point(&(win->monitor_list),
+ event->x, event->y) != RT_TRUE)
{
win = RT_NULL;
-
- /* try to find monitor on the panel */
- panel = rtgui_panel_get_contain(event->x, event->y);
- if (panel != RT_NULL)
- {
- struct rtgui_panel_thread* thread;
-
- /* get active panel thread */
- if (panel->thread_list.next != RT_NULL)
- {
- thread = rtgui_list_entry(panel->thread_list.next, struct rtgui_panel_thread, list);
- if (!rtgui_mouse_monitor_contains_point(&(thread->monitor_list),
- event->x, event->y) == RT_TRUE)
- {
- /* no monitor in this panel */
- panel = RT_NULL;
- }
- }
- }
}
}
- else
- {
- win = RT_NULL;
- }
-
- /* check old panel or window */
- if (last_monitor_panel != RT_NULL)
- {
- rt_thread_t tid = rtgui_panel_get_active_thread(last_monitor_panel);
- /* send mouse motion event */
- if (tid != RT_NULL)
- {
- event->wid = RT_NULL;
- rtgui_thread_send(tid, &(event->parent), sizeof(struct rtgui_event_mouse));
- }
- }
- else if (last_monitor_topwin != RT_NULL)
+ if (last_monitor_topwin != RT_NULL)
{
event->wid = last_monitor_topwin->wid;
-
/* send mouse motion event */
- rtgui_thread_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
- }
-
- if (last_monitor_panel != panel)
- {
- last_monitor_panel = panel;
- if (last_monitor_panel != RT_NULL)
- {
- rt_thread_t tid = rtgui_panel_get_active_thread(last_monitor_panel);
- event->wid = RT_NULL;
-
- /* send mouse motion event */
- if (tid != RT_NULL)
- rtgui_thread_send(tid, &(event->parent), sizeof(struct rtgui_event_mouse));
- }
+ rtgui_application_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
}
if (last_monitor_topwin != win)
@@ -432,7 +155,7 @@ void rtgui_server_handle_mouse_motion(struct rtgui_event_mouse* event)
event->wid = last_monitor_topwin->wid;
/* send mouse motion event */
- rtgui_thread_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
+ rtgui_application_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
}
}
@@ -443,203 +166,191 @@ void rtgui_server_handle_mouse_motion(struct rtgui_event_mouse* event)
void rtgui_server_handle_kbd(struct rtgui_event_kbd* event)
{
struct rtgui_topwin* wnd;
- struct rtgui_panel* panel;
/* re-init to server thread */
RTGUI_EVENT_KBD_INIT(event);
/* todo: handle input method and global shortcut */
- /* send to focus window or focus panel */
- wnd = rtgui_server_focus_topwin;
- if (wnd != RT_NULL && wnd->flag & WINTITLE_ACTIVATE)
+ wnd = rtgui_topwin_get_focus();
+ if (wnd != RT_NULL)
{
+ RT_ASSERT(wnd->flag & WINTITLE_ACTIVATE)
+
/* send to focus window */
event->wid = wnd->wid;
/* send keyboard event to thread */
- rtgui_thread_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_kbd));
+ rtgui_application_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_kbd));
return;
}
-
- panel = rtgui_server_focus_panel;
- if (panel != RT_NULL)
- {
- rt_thread_t tid;
-
- /* get active thread in this panel */
- tid = rtgui_panel_get_active_thread(panel);
- if (tid != RT_NULL)
- {
- /* send to focus panel */
- event->wid = RT_NULL;
-
- /* send keyboard event to thread */
- rtgui_thread_send(tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_kbd));
- }
- }
}
-#ifdef __WIN32__
+#ifdef _WIN32
#include <windows.h>
#endif
-/**
- * rtgui server thread's entry
- */
-static void rtgui_server_entry(void* parameter)
+static rt_bool_t rtgui_server_event_handler(struct rtgui_object *object,
+ struct rtgui_event *event)
{
-#ifdef __WIN32__
- /* set the server thread to highest */
- HANDLE hCurrentThread = GetCurrentThread();
- SetThreadPriority(hCurrentThread, THREAD_PRIORITY_HIGHEST);
-#endif
+ RT_ASSERT(object != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
-#ifdef RTGUI_USING_SMALL_SIZE
- /* create rtgui server msgq */
- rtgui_server_mq = rt_mq_create("rtgui",
- 32, 16, RT_IPC_FLAG_FIFO);
-#else
- /* create rtgui server msgq */
- rtgui_server_mq = rt_mq_create("rtgui",
- 256, 8, RT_IPC_FLAG_FIFO);
-#endif
- /* register rtgui server thread */
- rtgui_thread_register(rtgui_server_tid, rtgui_server_mq);
+ /* dispatch event */
+ switch (event->type)
+ {
+ /* window event */
+ case RTGUI_EVENT_WIN_CREATE:
+ if (rtgui_topwin_add((struct rtgui_event_win_create*)event) == RT_EOK)
+ rtgui_application_ack(event, RTGUI_STATUS_OK);
+ else
+ rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+ break;
- /* init mouse and show */
- rtgui_mouse_init();
-#ifdef RTGUI_USING_MOUSE_CURSOR
- rtgui_mouse_show_cursor();
-#endif
+ case RTGUI_EVENT_WIN_DESTROY:
+ if (last_monitor_topwin != RT_NULL &&
+ last_monitor_topwin->wid == ((struct rtgui_event_win*)event)->wid)
+ last_monitor_topwin = RT_NULL;
+ if (rtgui_topwin_remove(((struct rtgui_event_win*)event)->wid) == RT_EOK)
+ rtgui_application_ack(event, RTGUI_STATUS_OK);
+ else
+ rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+ break;
- while (1)
- {
- /* the buffer uses to receive event */
-#ifdef RTGUI_USING_SMALL_SIZE
- char event_buf[64];
-#else
- char event_buf[256];
-#endif
- struct rtgui_event* event = (struct rtgui_event*)&(event_buf[0]);
+ case RTGUI_EVENT_WIN_SHOW:
+ if (rtgui_topwin_show((struct rtgui_event_win*)event) == RT_EOK)
+ rtgui_application_ack(event, RTGUI_STATUS_OK);
+ else
+ rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+ break;
- if (rtgui_thread_recv(event, sizeof(event_buf)) == RT_EOK)
- {
- /* dispatch event */
- switch (event->type)
- {
- /* panel event */
- case RTGUI_EVENT_PANEL_ATTACH:
- /* register an application in panel */
- rtgui_server_create_application((struct rtgui_event_panel_attach*)event);
- break;
+ case RTGUI_EVENT_WIN_HIDE:
+ if (rtgui_topwin_hide((struct rtgui_event_win*)event) == RT_EOK)
+ rtgui_application_ack(event, RTGUI_STATUS_OK);
+ else
+ rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+ break;
- case RTGUI_EVENT_PANEL_DETACH:
- /* unregister an application */
- rtgui_server_destroy_application((struct rtgui_event_panel_detach*)event);
- break;
+ case RTGUI_EVENT_WIN_MOVE:
+ if (rtgui_topwin_move((struct rtgui_event_win_move*)event) == RT_EOK)
+ rtgui_application_ack(event, RTGUI_STATUS_OK);
+ else
+ rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+ break;
- case RTGUI_EVENT_PANEL_SHOW:
- /* handle raise an application */
- rtgui_server_thread_panel_show((struct rtgui_event_panel_show*)event);
- break;
+ case RTGUI_EVENT_WIN_MODAL_ENTER:
+ if (rtgui_topwin_modal_enter((struct rtgui_event_win_modal_enter*)event) == RT_EOK)
+ rtgui_application_ack(event, RTGUI_STATUS_OK);
+ else
+ rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+ break;
- case RTGUI_EVENT_PANEL_HIDE:
- /* handle hide an application */
- rtgui_server_thread_panel_hide((struct rtgui_event_panel_hide*)event);
- break;
+ case RTGUI_EVENT_WIN_RESIZE:
+ rtgui_topwin_resize(((struct rtgui_event_win_resize*)event)->wid,
+ &(((struct rtgui_event_win_resize*)event)->rect));
+ break;
- case RTGUI_EVENT_SET_WM:
- /* handle set workbench manager event */
- rtgui_server_handle_set_wm((struct rtgui_event_set_wm*)event);
- break;
+ /* other event */
+ case RTGUI_EVENT_UPDATE_BEGIN:
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ /* hide cursor */
+ rtgui_mouse_hide_cursor();
+#endif
+ break;
- /* window event */
- case RTGUI_EVENT_WIN_CREATE:
- rtgui_thread_ack(event, RTGUI_STATUS_OK);
- rtgui_topwin_add((struct rtgui_event_win_create*)event);
- break;
+ case RTGUI_EVENT_UPDATE_END:
+ /* handle screen update */
+ rtgui_server_handle_update((struct rtgui_event_update_end*)event);
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ /* show cursor */
+ rtgui_mouse_show_cursor();
+#endif
+ break;
- case RTGUI_EVENT_WIN_DESTROY:
- if (rtgui_topwin_remove(((struct rtgui_event_win*)event)->wid) == RT_EOK)
- rtgui_thread_ack(event, RTGUI_STATUS_OK);
- else
- rtgui_thread_ack(event, RTGUI_STATUS_ERROR);
- break;
+ case RTGUI_EVENT_MONITOR_ADD:
+ /* handle mouse monitor */
+ rtgui_server_handle_monitor_add((struct rtgui_event_monitor*)event);
+ break;
- case RTGUI_EVENT_WIN_SHOW:
- rtgui_topwin_show((struct rtgui_event_win*)event);
- break;
+ /* mouse and keyboard event */
+ case RTGUI_EVENT_MOUSE_MOTION:
+ /* handle mouse motion event */
+ rtgui_server_handle_mouse_motion((struct rtgui_event_mouse*)event);
+ break;
- case RTGUI_EVENT_WIN_HIDE:
- rtgui_topwin_hide((struct rtgui_event_win*)event);
- break;
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ /* handle mouse button */
+ rtgui_server_handle_mouse_btn((struct rtgui_event_mouse*)event);
+ break;
- case RTGUI_EVENT_WIN_MOVE:
- rtgui_topwin_move((struct rtgui_event_win_move*)event);
- break;
+ case RTGUI_EVENT_KBD:
+ /* handle keyboard event */
+ rtgui_server_handle_kbd((struct rtgui_event_kbd*)event);
+ break;
- case RTGUI_EVENT_WIN_RESIZE:
- rtgui_topwin_resize(((struct rtgui_event_win_resize*)event)->wid,
- &(((struct rtgui_event_win_resize*)event)->rect));
- break;
+ case RTGUI_EVENT_COMMAND:
+ break;
+ }
- /* other event */
- case RTGUI_EVENT_UPDATE_BEGIN:
-#ifdef RTGUI_USING_MOUSE_CURSOR
- /* hide cursor */
- rtgui_mouse_hide_cursor();
-#endif
- break;
+ return RT_TRUE;
+}
- case RTGUI_EVENT_UPDATE_END:
- /* handle screen update */
- rtgui_server_handle_update((struct rtgui_event_update_end*)event);
-#ifdef RTGUI_USING_MOUSE_CURSOR
- /* show cursor */
- rtgui_mouse_show_cursor();
+/**
+ * rtgui server thread's entry
+ */
+static void rtgui_server_entry(void* parameter)
+{
+#ifdef _WIN32
+ /* set the server thread to highest */
+ HANDLE hCurrentThread = GetCurrentThread();
+ SetThreadPriority(hCurrentThread, THREAD_PRIORITY_HIGHEST);
#endif
- break;
- case RTGUI_EVENT_MONITOR_ADD:
- /* handle mouse monitor */
- rtgui_server_handle_monitor_add((struct rtgui_event_monitor*)event);
- break;
-
- /* mouse and keyboard event */
- case RTGUI_EVENT_MOUSE_MOTION:
- /* handle mouse motion event */
- rtgui_server_handle_mouse_motion((struct rtgui_event_mouse*)event);
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- /* handle mouse button */
- rtgui_server_handle_mouse_btn((struct rtgui_event_mouse*)event);
- break;
+ /* register rtgui server thread */
+ rtgui_server_application = rtgui_application_create(rtgui_server_tid,
+ "rtgui");
+ if (rtgui_server_application == RT_NULL)
+ return;
- case RTGUI_EVENT_KBD:
- /* handle keyboard event */
- rtgui_server_handle_kbd((struct rtgui_event_kbd*)event);
- break;
+ rtgui_object_set_event_handler(RTGUI_OBJECT(rtgui_server_application),
+ rtgui_server_event_handler);
+ /* init mouse and show */
+ rtgui_mouse_init();
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rtgui_mouse_show_cursor();
+#endif
- case RTGUI_EVENT_COMMAND:
- break;
- }
- }
- }
+ rtgui_application_run(rtgui_server_application);
- /* unregister in rtgui thread */
- // rtgui_thread_deregister(rt_thread_self());
+ rtgui_application_destroy(rtgui_server_application);
+ rtgui_server_application = RT_NULL;
}
void rtgui_server_post_event(struct rtgui_event* event, rt_size_t size)
{
- rt_mq_send(rtgui_server_mq, event, size);
+ if (rtgui_server_tid != RT_NULL)
+ rtgui_application_send(rtgui_server_tid, event, size);
+ else
+ rt_kprintf("post when server is not running\n");
+}
+
+rt_err_t rtgui_server_post_event_sync(struct rtgui_event* event, rt_size_t size)
+{
+ if (rtgui_server_tid != RT_NULL)
+ return rtgui_application_send_sync(rtgui_server_tid, event, size);
+ else
+ {
+ rt_kprintf("post when server is not running\n");
+ return -RT_ENOSYS;
+ }
}
-void rtgui_server_init()
+void rtgui_server_init(void)
{
+ if (rtgui_server_tid != RT_NULL)
+ return;
+
rtgui_server_tid = rt_thread_create("rtgui",
rtgui_server_entry, RT_NULL,
RTGUI_SVR_THREAD_STACK_SIZE,
diff --git a/components/rtgui/server/topwin.c b/components/rtgui/server/topwin.c
index 498f8987a8..14c9432b18 100644
--- a/components/rtgui/server/topwin.c
+++ b/components/rtgui/server/topwin.c
@@ -11,51 +11,82 @@
* Date Author Notes
* 2009-10-16 Bernard first version
*/
-#include "panel.h"
#include "topwin.h"
#include "mouse.h"
+#include <rtgui/dlist.h>
#include <rtgui/event.h>
#include <rtgui/image.h>
#include <rtgui/rtgui_theme.h>
#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_application.h>
#include <rtgui/widgets/window.h>
-struct rtgui_topwin* rtgui_server_focus_topwin = RT_NULL;
+/* This list is divided into two parts. The first part is the shown list, in
+ * which all the windows have the WINTITLE_SHOWN flag set. Second part is the
+ * hidden list, in which all the windows don't have WINTITLE_SHOWN flag.
+ *
+ * The active window is the one that would receive kbd events. It should always
+ * in the first tree. The order of this list is the order of the windows.
+ * Thus, the first item is the top most window and the last item is the bottom
+ * window. Top window can always clip the window beneath it when the two
+ * overlapping. Child window can always clip it's parent. Slibing windows can
+ * clip each other with the same rule as this list. Thus, each child list is
+ * the same as _rtgui_topwin_list. This forms the hierarchy tree structure of
+ * all windows.
+ *
+ * The hidden list have no specific order.
+ */
+static struct rtgui_dlist_node _rtgui_topwin_list;
+#define get_topwin_from_list(list_entry) \
+ (rtgui_dlist_entry((list_entry), struct rtgui_topwin, list))
+
+#ifdef RTGUI_USING_DESKTOP_WINDOW
+static struct rtgui_topwin *the_desktop_topwin;
+
+#define IS_ROOT_WIN(topwin) ((topwin)->parent == the_desktop_topwin)
+#else
+#define IS_ROOT_WIN(topwin) ((topwin)->parent == RT_NULL)
+#endif
-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);
+static void _rtgui_topwin_activate_next(void);
-void rtgui_topwin_init()
+void rtgui_topwin_init(void)
{
/* init window list */
- rtgui_list_init(&_rtgui_topwin_show_list);
- rtgui_list_init(&_rtgui_topwin_hide_list);
+ rtgui_dlist_init(&_rtgui_topwin_list);
- rt_sem_init(&_rtgui_topwin_lock,
+ 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)
+static struct rtgui_topwin* rtgui_topwin_search_in_list(struct rtgui_win* window,
+ struct rtgui_dlist_node* list)
{
- struct rtgui_list_node* node;
+ /* TODO: use a cache to speed up the search. */
+ struct rtgui_dlist_node* node;
struct rtgui_topwin* topwin;
- /* search in list */
- rtgui_list_foreach(node, list)
+ /* the action is tend to operate on the top most window. So we search in a
+ * depth first order.
+ */
+ rtgui_dlist_foreach(node, list, next)
{
- topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
+ topwin = rtgui_dlist_entry(node, struct rtgui_topwin, list);
/* is this node? */
- if (topwin->wid == wid)
+ if (topwin->wid == window)
{
return topwin;
}
+
+ topwin = rtgui_topwin_search_in_list(window, &topwin->child_list);
+ if (topwin != RT_NULL)
+ return topwin;
}
return RT_NULL;
@@ -67,17 +98,42 @@ 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;
+ if (topwin == RT_NULL)
+ return -RT_ERROR;
- topwin->wid = event->wid;
+ topwin->wid = event->wid;
#ifdef RTGUI_USING_SMALL_SIZE
- topwin->extent = RTGUI_WIDGET(event->wid)->extent;
+ topwin->extent = RTGUI_WIDGET(event->wid)->extent;
#else
- topwin->extent = event->extent;
+ topwin->extent = event->extent;
#endif
- topwin->tid = event->parent.sender;
+ topwin->tid = event->parent.sender;
- topwin->flag = 0;
+ if (event->parent_window == RT_NULL)
+ {
+ topwin->parent = RT_NULL;
+ rtgui_dlist_insert_before(&_rtgui_topwin_list, &topwin->list);
+#ifdef RTGUI_USING_DESKTOP_WINDOW
+ RT_ASSERT(the_desktop_topwin == RT_NULL);
+ RT_ASSERT(event->parent.user & RTGUI_WIN_STYLE_DESKTOP);
+ the_desktop_topwin = topwin;
+#endif
+ }
+ else
+ {
+ topwin->parent = rtgui_topwin_search_in_list(event->parent_window, &_rtgui_topwin_list);
+ if (topwin->parent == RT_NULL)
+ {
+ /* parent does not exist. Orphan window? */
+ rtgui_free(topwin);
+ return -RT_ERROR;
+ }
+ rtgui_dlist_insert_before(&topwin->parent->child_list, &topwin->list);
+ }
+
+ rtgui_dlist_init(&topwin->child_list);
+
+ 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;
@@ -105,541 +161,660 @@ rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event)
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;
+ 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)
+static struct rtgui_topwin* _rtgui_topwin_get_root_win(struct rtgui_topwin *topwin)
{
- struct rtgui_topwin* topwin;
+ struct rtgui_topwin *topparent;
- /* find the topwin node */
- topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ RT_ASSERT(topwin != RT_NULL);
+
+ topparent = topwin;
+ while (topparent && !IS_ROOT_WIN(topparent))
+ topparent = topparent->parent;
+ return topparent;
+}
- if (topwin)
+static struct rtgui_topwin* _rtgui_topwin_get_topmost_child_shown(struct rtgui_topwin *topwin)
+{
+ RT_ASSERT(topwin != RT_NULL);
+
+ while (!(rtgui_dlist_isempty(&topwin->child_list)) &&
+ get_topwin_from_list(topwin->child_list.next)->flag & WINTITLE_SHOWN)
+ topwin = get_topwin_from_list(topwin->child_list.next);
+ return topwin;
+}
+
+static struct rtgui_topwin* _rtgui_topwin_get_topmost_window_shown(void)
+{
+ if (!(get_topwin_from_list(_rtgui_topwin_list.next)->flag & WINTITLE_SHOWN))
+ return RT_NULL;
+ else
+ return _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(_rtgui_topwin_list.next));
+}
+
+/* a hidden parent will hide it's children. Top level window can be shown at
+ * any time. */
+static rt_bool_t _rtgui_topwin_could_show(struct rtgui_topwin *topwin)
+{
+ struct rtgui_topwin *parent;
+
+ RT_ASSERT(topwin != RT_NULL);
+
+ for (parent = topwin->parent; parent != RT_NULL; parent = parent->parent)
{
- /* remove node from list */
- rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
+ if (!(parent->flag & WINTITLE_SHOWN))
+ return RT_FALSE;
+ }
+ return RT_TRUE;
+}
- rtgui_topwin_update_clip();
+static void _rtgui_topwin_union_region_tree(struct rtgui_topwin *topwin,
+ struct rtgui_region *region)
+{
+ struct rtgui_dlist_node *node;
- /* redraw the old rect */
- rtgui_topwin_redraw(&(topwin->extent));
+ RT_ASSERT(topwin != RT_NULL);
- 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;
+ rtgui_dlist_foreach(node, &topwin->child_list, next)
+ _rtgui_topwin_union_region_tree(get_topwin_from_list(node), region);
- /* get the topwin */
- wnd = rtgui_list_entry(_rtgui_topwin_show_list.next,
- struct rtgui_topwin, list);
+ if (topwin->title != RT_NULL)
+ rtgui_region_union_rect(region, region, &RTGUI_WIDGET(topwin->title)->extent);
+ else
+ rtgui_region_union_rect(region, region, &topwin->extent);
+}
- /* 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));
+/* The return value of this function is the next node in tree.
+ *
+ * As we freed the node in this function, it would be a null reference error of
+ * the caller iterate the tree normally.
+ */
+static struct rtgui_dlist_node* _rtgui_topwin_free_tree(struct rtgui_topwin *topwin)
+{
+ struct rtgui_dlist_node *node, *next_node;
- /* set new focus topwin */
- rtgui_server_focus_topwin = wnd;
- }
- else
- {
- /* there is no shown window right now */
- rtgui_server_focus_topwin = RT_NULL;
- }
- }
+ RT_ASSERT(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,
+ node = topwin->child_list.next;
+ while (node != &topwin->child_list)
+ node = _rtgui_topwin_free_tree(get_topwin_from_list(node));
+
+ next_node = topwin->list.next;
+ rtgui_dlist_remove(&topwin->list);
+
+ /* 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);
- }
+ topwin->monitor_list.next = topwin->monitor_list.next->next;
+ rtgui_free(monitor);
+ }
- /* destroy win title */
- rtgui_wintitle_destroy(topwin->title);
- topwin->title = RT_NULL;
+ /* destroy win title */
+ rtgui_wintitle_destroy(topwin->title);
+ topwin->title = RT_NULL;
- rtgui_free(topwin);
+ rtgui_free(topwin);
+ return next_node;
+}
- return RT_EOK;
- }
+rt_err_t rtgui_topwin_remove(struct rtgui_win* wid)
+{
+ struct rtgui_topwin *topwin, *old_focus;
+ struct rtgui_region region;
- 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));
+ /* find the topwin node */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
- /* free the topwin node and title */
- rtgui_wintitle_destroy(topwin->title);
- topwin->title = RT_NULL;
+ if (topwin == RT_NULL)
+ return -RT_ERROR;
- rtgui_free(topwin);
+ rtgui_region_init(&region);
- return RT_EOK;
+ old_focus = rtgui_topwin_get_focus();
+
+ // TODO: if the window is hidden, there is no need to update the window
+ // region
+ _rtgui_topwin_union_region_tree(topwin, &region);
+ if (topwin->flag & WINTITLE_SHOWN)
+ rtgui_topwin_update_clip();
+
+ if (old_focus == topwin)
+ {
+ _rtgui_topwin_activate_next();
}
- return -RT_ERROR;
+ /* redraw the old rect */
+ rtgui_topwin_redraw(rtgui_region_extents(&region));
+
+ /* remove the root from _rtgui_topwin_list will remove the whole tree from
+ * _rtgui_topwin_list. */
+ rtgui_dlist_remove(&topwin->list);
+
+ _rtgui_topwin_free_tree(topwin);
+
+ return RT_EOK;
}
-/* 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)
+/* neither deactivate the old focus nor change _rtgui_topwin_list.
+ * Suitable to be called when the first item is the window to be activated
+ * already. */
+static void _rtgui_topwin_only_activate(struct rtgui_topwin *topwin)
{
struct rtgui_event_win event;
+ RT_ASSERT(topwin != RT_NULL);
+
+ if (topwin->flag & WINTITLE_NOFOCUS)
+ return;
+
/* 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));
+
+ topwin->flag |= WINTITLE_ACTIVATE;
+
+ event.wid = topwin->wid;
+ rtgui_application_send(topwin->tid, &(event.parent), sizeof(struct rtgui_event_win));
/* redraw title */
- if (win->title != RT_NULL)
+ if (topwin->title != RT_NULL)
{
- win->flag |= WINTITLE_ACTIVATE;
- rtgui_theme_draw_win(win);
+ rtgui_theme_draw_win(topwin);
}
+}
- 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));
+static void _rtgui_topwin_activate_next(void)
+{
+ struct rtgui_topwin *topwin;
- /* 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);
- }
- }
+ topwin = _rtgui_topwin_get_topmost_window_shown();
+ if (topwin == RT_NULL)
+ return;
- rtgui_server_focus_topwin = win;
+ _rtgui_topwin_only_activate(topwin);
}
-/*
- * deactivate a win
- * - deactivate the win
- * - redraw win title
- * - set rtgui_server_focus_topwin
- */
-void rtgui_topwin_deactivate_win(struct rtgui_topwin* win)
+/* this function does not update the clip(to avoid doubel clipping). So if the
+ * tree has changed, make sure it has already updated outside. */
+static void _rtgui_topwin_deactivate(struct rtgui_topwin *topwin)
{
- /* deactivate win */
struct rtgui_event_win event;
+
+ RT_ASSERT(topwin != RT_NULL);
+ RT_ASSERT(topwin->tid != RT_NULL);
+
RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
- event.wid = win->wid;
- rtgui_thread_send(win->tid,
- &event.parent, sizeof(struct rtgui_event_win));
+ event.wid = topwin->wid;
+ rtgui_application_send(topwin->tid,
+ &event.parent, sizeof(struct rtgui_event_win));
- win->flag &= ~WINTITLE_ACTIVATE;
- rtgui_theme_draw_win(win);
+ topwin->flag &= ~WINTITLE_ACTIVATE;
- if (rtgui_server_focus_topwin == win)
+ /* redraw title */
+ if (topwin->title != RT_NULL)
{
- rtgui_server_focus_topwin = RT_NULL;
+ rtgui_theme_draw_win(topwin);
}
}
-/* raise window to front */
-void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender)
+static void _rtgui_topwin_move_whole_tree2top(struct rtgui_topwin *topwin)
{
- struct rtgui_topwin* topwin;
- struct rtgui_list_node* node;
- struct rtgui_event_clip_info eclip;
+ struct rtgui_topwin *topparent;
- RTGUI_EVENT_CLIP_INFO_INIT(&eclip);
- eclip.wid = RT_NULL;
+ RT_ASSERT(topwin != RT_NULL);
- /* the window is already placed in front */
- if (&(topwin->list) == _rtgui_topwin_show_list.next)
+#ifdef RTGUI_USING_DESKTOP_WINDOW
+ /* handle desktop window separately, avoid calling
+ * _rtgui_topwin_get_root_win */
+ if (topwin == the_desktop_topwin)
{
- rtgui_server_focus_topwin = RT_NULL;
- rtgui_topwin_activate_win(topwin);
- return ;
+ rtgui_dlist_remove(&the_desktop_topwin->list);
+ rtgui_dlist_insert_after(&_rtgui_topwin_list, &the_desktop_topwin->list);
+ return;
}
+#endif
- // rt_sem_take(&_rtgui_topwin_lock, RT_WAITING_FOREVER);
- /* find the topwin node */
- for (node = _rtgui_topwin_show_list.next; node->next != RT_NULL; node = node->next)
- {
- topwin = rtgui_list_entry(node->next, struct rtgui_topwin, list);
- if (topwin->wid == wid)
- {
- /* found target */
-
- struct rtgui_list_node* n;
- n = node->next;
- /* remove node */
- node->next = node->next->next;
- /* insert node to the header */
- n->next = _rtgui_topwin_show_list.next;
- _rtgui_topwin_show_list.next = n;
+ /* move the whole tree */
+ topparent = _rtgui_topwin_get_root_win(topwin);
+ RT_ASSERT(topparent != RT_NULL);
- /* send clip update to each upper window */
- for (n = _rtgui_topwin_show_list.next; n != node->next; n = n->next)
- {
- struct rtgui_topwin* wnd = rtgui_list_entry(n, struct rtgui_topwin, list);
- eclip.wid = wnd->wid;
+ /* remove node from hidden list */
+ rtgui_dlist_remove(&topparent->list);
+ /* add node to show list */
+#ifdef RTGUI_USING_DESKTOP_WINDOW
+ rtgui_dlist_insert_after(&the_desktop_topwin->child_list, &(topparent->list));
+#else
+ rtgui_dlist_insert_after(&_rtgui_topwin_list, &(topparent->list));
+#endif
+}
- /* send to destination window */
- rtgui_thread_send(wnd->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
+static void _rtgui_topwin_raise_topwin_in_tree(struct rtgui_topwin *topwin)
+{
+ struct rtgui_dlist_node *win_level;
- /* reset clip info in title */
- if (wnd->title != RT_NULL)
- {
- rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
- rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
- &(RTGUI_WIDGET(wnd->title)->clip),
- &(wnd->extent));
- }
- }
+ RT_ASSERT(topwin != RT_NULL);
- /* active window */
- rtgui_topwin_activate_win(topwin);
- break;
- }
- }
- // rt_sem_release(&_rtgui_topwin_lock);
+ _rtgui_topwin_move_whole_tree2top(topwin);
+ if (topwin->parent == RT_NULL)
+ win_level = &_rtgui_topwin_list;
+ else
+ win_level = &topwin->parent->child_list;
+ rtgui_dlist_remove(&topwin->list);
+ rtgui_dlist_insert_after(win_level, &topwin->list);
}
-/* show a window */
-void rtgui_topwin_show(struct rtgui_event_win* event)
+/* activate a win means:
+ * - deactivate the old focus win if any
+ * - raise the window to the front of it's siblings
+ * - activate a win
+ */
+void rtgui_topwin_activate_win(struct rtgui_topwin* topwin)
{
- struct rtgui_topwin* topwin;
- struct rtgui_win* wid = event->wid;
- rt_thread_t sender = RTGUI_EVENT(event)->sender;
+ struct rtgui_topwin *old_focus_topwin;
- /* find in hide list */
- topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
+ RT_ASSERT(topwin != RT_NULL);
- /* find it */
- if (topwin != RT_NULL)
+ if (topwin->flag & WINTITLE_NOFOCUS)
{
- /* 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));
- }
+ /* just raise it, not affect others. */
+ _rtgui_topwin_raise_topwin_in_tree(topwin);
/* update clip info */
rtgui_topwin_update_clip();
+ return;
+ }
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
+ old_focus_topwin = rtgui_topwin_get_focus();
- /* 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);
+ if (old_focus_topwin == topwin)
+ return;
- /* 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);
- }
+ _rtgui_topwin_raise_topwin_in_tree(topwin);
+ /* update clip info */
+ rtgui_topwin_update_clip();
+
+ if (old_focus_topwin != RT_NULL)
+ {
+ /* deactivate the old focus window firstly, otherwise it will make the new
+ * window invisible. */
+ _rtgui_topwin_deactivate(old_focus_topwin);
}
+
+ _rtgui_topwin_only_activate(topwin);
}
-/* send clip info to panel */
-#ifdef RTGUI_USING_SMALL_SIZE
-void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel)
+/* map func to the topwin tree in preorder.
+ *
+ * Remember that we are in a embedded system so write the @param func memory
+ * efficiently.
+ */
+rt_inline void _rtgui_topwin_preorder_map(struct rtgui_topwin *topwin, void (*func)(struct rtgui_topwin*))
{
- rt_uint32_t count;
- rt_thread_t tid;
- struct rtgui_list_node* node;
- struct rtgui_event_clip_info eclip;
+ struct rtgui_dlist_node *child;
- /* get topwin count */
- count = 0;
- node = _rtgui_topwin_show_list.next;
- while (node != RT_NULL)
- {
- count ++;
- node = node->next;
- }
+ RT_ASSERT(topwin != RT_NULL);
+ RT_ASSERT(func != RT_NULL);
- /* send clip info event to panel */
- RTGUI_EVENT_CLIP_INFO_INIT(&eclip);
- eclip.num_rect = count; eclip.wid = RT_NULL;
+ func(topwin);
- /* 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));
+ rtgui_dlist_foreach(child, &topwin->child_list, next)
+ _rtgui_topwin_preorder_map(get_topwin_from_list(child), func);
}
-#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)
+rt_inline void _rtgui_topwin_mark_hidden(struct rtgui_topwin *topwin)
+{
+ topwin->flag &= ~WINTITLE_SHOWN;
+ if (topwin->title != RT_NULL)
{
- count ++;
- node = node->next;
+ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->title));
}
+ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->wid));
+}
- eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
- + (count + 1)* sizeof(struct rtgui_rect));
- if (eclip == RT_NULL)
+rt_inline void _rtgui_topwin_mark_shown(struct rtgui_topwin *topwin)
+{
+ topwin->flag |= WINTITLE_SHOWN;
+ if (topwin->title != RT_NULL)
{
- /* no memory */
- return ;
+ RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->title));
}
+ RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->wid));
+}
- /* reset clip info to top window */
- RTGUI_EVENT_CLIP_INFO_INIT(eclip);
- eclip->num_rect = count; eclip->wid = RT_NULL;
+static void _rtgui_topwin_draw_tree(struct rtgui_topwin *topwin, struct rtgui_event_paint *epaint)
+{
+ struct rtgui_dlist_node *node;
- count = 0;
- for (node = _rtgui_topwin_show_list.next; node != RT_NULL; node = node->next)
+ if (topwin->title != RT_NULL)
{
- struct rtgui_topwin* wnd;
- struct rtgui_rect* rect;
+ rtgui_theme_draw_win(topwin);
+ }
- wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
+ epaint->wid = topwin->wid;
+ rtgui_application_send(topwin->tid, &(epaint->parent), sizeof(struct rtgui_event_paint));
- rect = RTGUI_EVENT_GET_RECT(eclip, count++);
- *rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
+ rtgui_dlist_foreach(node, &topwin->child_list, prev)
+ {
+ _rtgui_topwin_draw_tree(get_topwin_from_list(node), epaint);
}
+}
+
+/* show the window tree. @param epaint can be initialized outside and reduce stack
+ * usage. */
+static void _rtgui_topwin_show_tree(struct rtgui_topwin *topwin, struct rtgui_event_paint *epaint)
+{
+ RT_ASSERT(topwin != RT_NULL);
+ RT_ASSERT(epaint != RT_NULL);
- /* 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));
+ _rtgui_topwin_raise_topwin_in_tree(topwin);
+ /* we have to mark the _all_ tree before update_clip because update_clip
+ * will stop as hidden windows */
+ _rtgui_topwin_preorder_map(topwin, _rtgui_topwin_mark_shown);
- /* release clip info event */
- rtgui_free(eclip);
+ // TODO: if all the window is shown already, there is no need to
+ // update_clip. But since we use peorder_map, it seems it's a bit difficult
+ // to tell whether @param topwin and it's children are all shown.
+ rtgui_topwin_update_clip();
+
+ _rtgui_topwin_draw_tree(topwin, epaint);
}
-#endif
-/* hide a window */
-void rtgui_topwin_hide(struct rtgui_event_win* event)
+/** show a window
+ *
+ * If any parent window in the hierarchy tree is hidden, this window won't be
+ * shown. If this window could be shown, all the child windows will be shown as
+ * well. The topmost child will be active.
+ *
+ * Top level window(parent == RT_NULL) can always be shown.
+ */
+rt_err_t rtgui_topwin_show(struct rtgui_event_win* event)
{
- struct rtgui_topwin* topwin;
+ struct rtgui_topwin *topwin, *old_focus;
struct rtgui_win* wid = event->wid;
+ struct rtgui_event_paint epaint;
- /* find in show list */
- topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ RTGUI_EVENT_PAINT_INIT(&epaint);
+
+ /* find in hide list */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
+ if (topwin == RT_NULL ||
+ !_rtgui_topwin_could_show(topwin))
+ return -RT_ERROR;
+
+ old_focus = rtgui_topwin_get_focus();
+
+ _rtgui_topwin_show_tree(topwin, &epaint);
- /* found it */
- if (topwin)
+ /* we don't want double clipping(bare rtgui_topwin_activate_win will clip),
+ * so we have to do deactivate/activate manually. */
+ if (old_focus == RT_NULL)
+ _rtgui_topwin_only_activate(topwin);
+ else if (old_focus != topwin)
{
- /* remove node from show list */
- rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
+ _rtgui_topwin_deactivate(old_focus);
+ _rtgui_topwin_only_activate(topwin);
+ }
- /* add node to hidden list */
- rtgui_list_insert(&_rtgui_topwin_hide_list, &(topwin->list));
+ return RT_EOK;
+}
- /* show window title */
- if (topwin->title != RT_NULL)
- {
- RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->title));
- }
+static void _rtgui_topwin_clear_modal_tree(struct rtgui_topwin *topwin)
+{
+ struct rtgui_dlist_node *node;
- /* update clip info */
- rtgui_topwin_update_clip();
+ RT_ASSERT(topwin != RT_NULL);
+ RT_ASSERT(topwin->parent != RT_NULL);
- /* redraw the old rect */
- rtgui_topwin_redraw(&(topwin->extent));
+ while (!IS_ROOT_WIN(topwin))
+ {
+ rtgui_dlist_foreach(node, &topwin->parent->child_list, next)
+ get_topwin_from_list(node)->flag &= ~WINTITLE_MODALED;
+ topwin = topwin->parent;
+ }
+ /* clear the modal flag of the root window */
+ topwin->flag &= ~WINTITLE_MODALED;
+}
- 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);
+/* hide a window */
+rt_err_t rtgui_topwin_hide(struct rtgui_event_win* event)
+{
+ struct rtgui_topwin *topwin;
+ struct rtgui_topwin *old_focus_topwin = rtgui_topwin_get_focus();
+ struct rtgui_win *wid = event->wid;
+ struct rtgui_dlist_node *containing_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;
- }
- }
+ /* find in show list */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
+ if (topwin == RT_NULL)
+ {
+ return -RT_ERROR;
+ }
+ if (!(topwin->flag & WINTITLE_SHOWN))
+ {
+ return RT_EOK;
}
+
+ old_focus_topwin = rtgui_topwin_get_focus();
+
+ _rtgui_topwin_preorder_map(topwin, _rtgui_topwin_mark_hidden);
+
+ if (topwin->parent == RT_NULL)
+ containing_list = &_rtgui_topwin_list;
else
+ containing_list = &topwin->parent->child_list;
+
+ rtgui_dlist_remove(&topwin->list);
+ rtgui_dlist_insert_before(containing_list, &topwin->list);
+
+ /* update clip info */
+ rtgui_topwin_update_clip();
+
+ /* redraw the old rect */
+ rtgui_topwin_redraw(&(topwin->extent));
+
+ if (topwin->flag & WINTITLE_MODALING)
{
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
- return;
+ _rtgui_topwin_clear_modal_tree(topwin);
+ topwin->flag &= ~WINTITLE_MODALING;
+ }
+
+ if (old_focus_topwin == topwin)
+ {
+ _rtgui_topwin_activate_next();
}
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
+ return RT_EOK;
}
/* move top window */
-void rtgui_topwin_move(struct rtgui_event_win_move* event)
+rt_err_t rtgui_topwin_move(struct rtgui_event_win_move* event)
{
struct rtgui_topwin* topwin;
+ int dx, dy;
+ rtgui_rect_t old_rect; /* the old topwin coverage area */
+ struct rtgui_list_node* node;
/* find in show list */
- topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_show_list);
- if (topwin != RT_NULL)
+ topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_list);
+ if (topwin == RT_NULL ||
+ !(topwin->flag & WINTITLE_SHOWN))
{
- 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);
+ return -RT_ERROR;
+ }
- /* get the delta move x, y */
- dx = event->x - topwin->extent.x1;
- dy = event->y - topwin->extent.y1;
+ /* 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);
+ old_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 window title */
+ if (topwin->title != RT_NULL)
+ {
+ old_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,
+ /* 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);
- }
+ rtgui_rect_moveto(&(monitor->rect), dx, dy);
+ }
- /* update windows clip info */
- rtgui_topwin_update_clip();
+ /* 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(&old_rect);
- /* update old window coverage area */
- rtgui_topwin_redraw(&rect);
- }
- else
+ /* update top window title */
+ if (topwin->title != RT_NULL)
+ rtgui_theme_draw_win(topwin);
+ if (rtgui_rect_is_intersect(&old_rect, &(topwin->extent)) != RT_EOK)
{
- rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
+ /*
+ * 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_application_send(topwin->tid, &(epaint.parent), sizeof(epaint));
}
+
+ return RT_EOK;
}
/*
* resize a top win
* Note: currently, only support resize hidden window
*/
-void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r)
+void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* rect)
{
struct rtgui_topwin* topwin;
+ struct rtgui_region region;
/* find in show list */
- topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
- if (topwin)
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
+ if (topwin == RT_NULL ||
+ !(topwin->flag & WINTITLE_SHOWN))
+ return;
+
+ /* record the old rect */
+ rtgui_region_init_with_extents(&region, &topwin->extent);
+ /* union the new rect so this is the region we should redraw */
+ rtgui_region_union_rect(&region, &region, rect);
+
+ topwin->extent = *rect;
+
+ if (topwin->title != RT_NULL)
{
- topwin->extent = *r;
+ /* get win extent */
+ rtgui_rect_t rect = topwin->extent;
- if (topwin->title != RT_NULL)
+ /* add border rect */
+ if (topwin->flag & WINTITLE_BORDER)
{
- /* get win extent */
- rtgui_rect_t rect = topwin->extent;
+ rtgui_rect_inflate(&rect, WINTITLE_BORDER_SIZE);
+ }
- /* 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;
- /* add title rect */
- if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT;
+ RTGUI_WIDGET(topwin->title)->extent = rect;
+ }
- RTGUI_WIDGET(topwin->title)->extent = rect;
+ /* update windows clip info */
+ rtgui_topwin_update_clip();
- /* 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));
- }
+ /* update old window coverage area */
+ rtgui_topwin_redraw(rtgui_region_extents(&region));
+}
+
+static struct rtgui_topwin* _rtgui_topwin_get_focus_from_list(struct rtgui_dlist_node *list)
+{
+ struct rtgui_dlist_node *node;
+
+ RT_ASSERT(list != RT_NULL);
+
+ rtgui_dlist_foreach(node, list, next)
+ {
+ struct rtgui_topwin *child = get_topwin_from_list(node);
+ if (child->flag & WINTITLE_ACTIVATE)
+ return child;
+
+ child = _rtgui_topwin_get_focus_from_list(&child->child_list);
+ if (child != RT_NULL)
+ return child;
}
+
+ return RT_NULL;
}
-struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y)
+struct rtgui_topwin* rtgui_topwin_get_focus(void)
{
- struct rtgui_list_node* node;
- struct rtgui_topwin* topwin;
+#if 1
+ // debug code
+ struct rtgui_topwin *topwin = _rtgui_topwin_get_focus_from_list(&_rtgui_topwin_list);
- /* search in list */
- rtgui_list_foreach(node, &(_rtgui_topwin_show_list))
+ if (topwin != RT_NULL)
+#ifdef RTGUI_USING_DESKTOP_WINDOW
+ RT_ASSERT(topwin == the_desktop_topwin ||\
+ get_topwin_from_list(the_desktop_topwin->child_list.next) ==
+ _rtgui_topwin_get_root_win(topwin));
+#else
+ RT_ASSERT(get_topwin_from_list(_rtgui_topwin_list.next) ==
+ _rtgui_topwin_get_root_win(topwin));
+#endif
+
+ return topwin;
+#else
+ return _rtgui_topwin_get_focus_from_list(&_rtgui_topwin_list);
+#endif
+}
+
+static struct rtgui_topwin* _rtgui_topwin_get_wnd_from_tree(struct rtgui_dlist_node *list,
+ int x, int y,
+ rt_bool_t exclude_modaled)
+{
+ struct rtgui_dlist_node *node;
+ struct rtgui_topwin *topwin, *target;
+
+ RT_ASSERT(list != RT_NULL);
+
+ rtgui_dlist_foreach(node, list, next)
{
- topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
+ topwin = get_topwin_from_list(node);
+ if (!(topwin->flag & WINTITLE_SHOWN))
+ break;
+
+ /* if higher window have this point, return it */
+ target = _rtgui_topwin_get_wnd_from_tree(&topwin->child_list, x, y, exclude_modaled);
+ if (target != RT_NULL)
+ return target;
+
+ if (exclude_modaled && (topwin->flag & WINTITLE_MODALED))
+ break;
- /* is this window? */
if ((topwin->title != RT_NULL) &&
rtgui_rect_contains_point(&(RTGUI_WIDGET(topwin->title)->extent), x, y) == RT_EOK)
{
@@ -654,105 +829,186 @@ struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y)
return RT_NULL;
}
-extern struct rtgui_list_node _rtgui_panel_list;
-static void rtgui_topwin_update_clip()
+struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y)
+{
+ return _rtgui_topwin_get_wnd_from_tree(&_rtgui_topwin_list, x, y, RT_FALSE);
+}
+
+struct rtgui_topwin* rtgui_topwin_get_wnd_no_modaled(int x, int y)
+{
+ return _rtgui_topwin_get_wnd_from_tree(&_rtgui_topwin_list, x, y, RT_TRUE);
+}
+
+/* clip region from topwin, and the windows beneath it. */
+rt_inline void _rtgui_topwin_clip_to_region(struct rtgui_region *region,
+ struct rtgui_topwin *topwin)
+{
+ RT_ASSERT(region != RT_NULL);
+ RT_ASSERT(topwin != RT_NULL);
+
+ if (topwin->title != RT_NULL)
+ {
+ rtgui_region_reset(&(RTGUI_WIDGET(topwin->title)->clip),
+ &(RTGUI_WIDGET(topwin->title)->extent));
+ rtgui_region_intersect(&(RTGUI_WIDGET(topwin->title)->clip),
+ &(RTGUI_WIDGET(topwin->title)->clip),
+ region);
+ rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
+ &(RTGUI_WIDGET(topwin->title)->clip),
+ &topwin->extent);
+ }
+
+ rtgui_region_reset(&RTGUI_WIDGET(topwin->wid)->clip,
+ &RTGUI_WIDGET(topwin->wid)->extent);
+ rtgui_region_intersect(&RTGUI_WIDGET(topwin->wid)->clip,
+ &RTGUI_WIDGET(topwin->wid)->clip,
+ region);
+}
+
+static void rtgui_topwin_update_clip(void)
{
- rt_int32_t count = 0;
+ struct rtgui_topwin *top;
struct rtgui_event_clip_info eclip;
- struct rtgui_list_node* node = _rtgui_topwin_show_list.next;
+ /* Note that the region is a "female die", that means it's the region you
+ * can paint to, not the region covered by others.
+ */
+ struct rtgui_region region_available;
+
+ if (rtgui_dlist_isempty(&_rtgui_topwin_list) ||
+ !(get_topwin_from_list(_rtgui_topwin_list.next)->flag & WINTITLE_SHOWN))
+ return;
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);
+ rtgui_region_init_rect(&region_available, 0, 0,
+ rtgui_graphic_driver_get_default()->width,
+ rtgui_graphic_driver_get_default()->height);
+
+ /* from top to bottom. */
+ top = _rtgui_topwin_get_topmost_window_shown();
- eclip.num_rect = count;
- eclip.wid = wnd->wid;
+ while (top != RT_NULL)
+ {
+ /* clip the topwin */
+ _rtgui_topwin_clip_to_region(&region_available, top);
+#if 0
+ /* debug window clipping */
+ rt_kprintf("clip %s ", top->wid->title);
+ rtgui_region_dump(&region_available);
+ rt_kprintf("\n");
+#endif
- count ++;
+ /* update available region */
+ if (top->title != RT_NULL)
+ rtgui_region_subtract_rect(&region_available, &region_available, &RTGUI_WIDGET(top->title)->extent);
+ else
+ rtgui_region_subtract_rect(&region_available, &region_available, &top->extent);
- /* send to destination window */
- rtgui_thread_send(wnd->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
+ /* send clip event to destination window */
+ eclip.wid = top->wid;
+ rtgui_application_send(top->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
- /* update clip in win title */
- if (wnd->title != RT_NULL)
- {
- /* reset clip info */
- rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
- rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
- &(RTGUI_WIDGET(wnd->title)->clip),
- &(wnd->extent));
- }
+ /* move to next sibling tree */
+ if (top->parent == RT_NULL)
+ if (top->list.next != &_rtgui_topwin_list &&
+ get_topwin_from_list(top->list.next)->flag & WINTITLE_SHOWN)
+ top = _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(top->list.next));
+ else
+ break;
+ else if (top->list.next != &top->parent->child_list &&
+ get_topwin_from_list(top->list.next)->flag & WINTITLE_SHOWN)
+ top = _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(top->list.next));
+ /* level up */
+ else
+ top = top->parent;
}
+}
+
+static void _rtgui_topwin_redraw_tree(struct rtgui_dlist_node *list,
+ struct rtgui_rect* rect,
+ struct rtgui_event_paint *epaint)
+{
+ struct rtgui_dlist_node *node;
- /* send clip info to each panel */
- eclip.wid = RT_NULL;
- eclip.num_rect = count;
+ RT_ASSERT(list != RT_NULL);
+ RT_ASSERT(rect != RT_NULL);
+ RT_ASSERT(epaint != RT_NULL);
- rtgui_list_foreach(node, &(_rtgui_panel_list))
+ /* skip the hidden windows */
+ rtgui_dlist_foreach(node, list, prev)
{
- struct rtgui_panel* panel;
- struct rtgui_list_node* panel_node;
+ if (get_topwin_from_list(node)->flag & WINTITLE_SHOWN)
+ break;
+ }
- panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
+ for (; node != list; node = node->prev)
+ {
+ struct rtgui_topwin *topwin;
- rtgui_list_foreach(panel_node, &(panel->thread_list))
+ topwin = get_topwin_from_list(node);
+
+ //FIXME: intersect with clip?
+ if (rtgui_rect_is_intersect(rect, &(topwin->extent)) == RT_EOK)
{
- struct rtgui_panel_thread* thread;
- thread = rtgui_list_entry(panel_node, struct rtgui_panel_thread, list);
+ epaint->wid = topwin->wid;
+ rtgui_application_send(topwin->tid, &(epaint->parent), sizeof(*epaint));
- /* send clip info to panel */
- rtgui_thread_send(thread->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
+ /* draw title */
+ if (topwin->title != RT_NULL)
+ {
+ rtgui_theme_draw_win(topwin);
+ }
}
+
+ _rtgui_topwin_redraw_tree(&topwin->child_list, rect, epaint);
}
}
static void rtgui_topwin_redraw(struct rtgui_rect* rect)
{
- struct rtgui_list_node* node;
struct rtgui_event_paint epaint;
RTGUI_EVENT_PAINT_INIT(&epaint);
epaint.wid = RT_NULL;
- rtgui_list_foreach(node, &_rtgui_topwin_show_list)
- {
- struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
+ _rtgui_topwin_redraw_tree(&_rtgui_topwin_list, rect, &epaint);
+}
- 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));
+/* a window enter modal mode will modal all the sibling window and parent
+ * window all along to the root window(which parent is RT_NULL or the desktop
+ * window if there is). If a root window modals, there is nothing to do here.*/
+rt_err_t rtgui_topwin_modal_enter(struct rtgui_event_win_modal_enter* event)
+{
+ struct rtgui_topwin *topwin, *parent_top;
+ struct rtgui_dlist_node *node;
- /* draw title */
- if (wnd->title != RT_NULL)
- {
- rtgui_theme_draw_win(wnd);
- }
- }
- }
+ topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_list);
- /* redraw the panel */
- rtgui_list_foreach(node, &(_rtgui_panel_list))
- {
- struct rtgui_panel* panel;
- panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
+ if (topwin == RT_NULL)
+ return -RT_ERROR;
- if (rtgui_rect_is_intersect(rect, &(panel->extent)) == RT_EOK)
- {
- rt_thread_t tid;
+ if (IS_ROOT_WIN(topwin))
+ return RT_EOK;
- 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));
- }
- }
+ parent_top = topwin->parent;
+
+ /* modal window should be on top already */
+ RT_ASSERT(get_topwin_from_list(parent_top->child_list.next) == topwin);
+
+ while (!IS_ROOT_WIN(parent_top))
+ {
+ rtgui_dlist_foreach(node, &parent_top->child_list, next)
+ get_topwin_from_list(node)->flag |= WINTITLE_MODALED;
+ parent_top->flag |= WINTITLE_MODALED;
+
+ parent_top = parent_top->parent;
}
+ /* mark root window as modaled */
+ parent_top->flag |= WINTITLE_MODALED;
+
+ topwin->flag &= ~WINTITLE_MODALED;
+ topwin->flag |= WINTITLE_MODALING;
+
+ return RT_EOK;
}
void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event)
@@ -763,7 +1019,7 @@ void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mou
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));
+ rtgui_application_send(win->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
return;
}
@@ -790,7 +1046,7 @@ void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mou
}
#endif
}
- else if (event->button & RTGUI_MOUSE_BUTTON_UP)
+ else if (win->flag & WINTITLE_CB_PRESSED && event->button & RTGUI_MOUSE_BUTTON_UP)
{
if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
{
@@ -802,7 +1058,7 @@ void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mou
/* 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));
+ rtgui_application_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
}
}
}
@@ -816,11 +1072,9 @@ void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect)
if (wid == RT_NULL || rect == RT_NULL) return;
/* find topwin */
- win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
if (win == RT_NULL)
- win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
-
- if (win == RT_NULL) return;
+ return;
/* append rect to top window monitor rect list */
rtgui_mouse_monitor_append(&(win->monitor_list), rect);
@@ -831,51 +1085,54 @@ 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;
+ if (wid == RT_NULL || rect == RT_NULL)
+ return;
/* find topwin */
- win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
if (win == RT_NULL)
- win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
-
- if (win == RT_NULL) return;
+ return;
/* remove rect from top window monitor rect list */
rtgui_mouse_monitor_remove(&(win->monitor_list), rect);
}
-/**
- * do clip for topwin list
- * widget, the clip widget to be done clip
- */
-void rtgui_topwin_do_clip(rtgui_widget_t* widget)
+static void _rtgui_topwin_dump(struct rtgui_topwin *topwin)
{
- rtgui_widget_t* wid;
- struct rtgui_rect* rect;
- struct rtgui_topwin* topwin;
- struct rtgui_list_node* node;
+ rt_kprintf("0x%p:%s,0x%x", topwin, topwin->wid->title, topwin->flag);
+}
+
+static void _rtgui_topwin_dump_tree(struct rtgui_topwin *topwin)
+{
+ struct rtgui_dlist_node *node;
- /* get toplevel wid */
- wid = widget->toplevel;
+ _rtgui_topwin_dump(topwin);
- rt_sem_take(&_rtgui_topwin_lock, RT_WAITING_FOREVER);
- /* get all of topwin rect list */
- rtgui_list_foreach(node, &_rtgui_topwin_show_list)
+ rt_kprintf("(");
+ rtgui_dlist_foreach(node, &topwin->child_list, next)
{
- topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
-
- if (topwin->wid == (rtgui_win_t*)(wid) ||
- RTGUI_WIDGET(topwin->title) == widget) break; /* it's self window, break */
+ _rtgui_topwin_dump_tree(get_topwin_from_list(node));
+ }
+ rt_kprintf(")");
+}
- /* get extent */
- if (topwin->title != RT_NULL)
- rect = &(RTGUI_WIDGET(topwin->title)->extent);
- else
- rect = &(topwin->extent);
+void rtgui_topwin_dump_tree(void)
+{
+ struct rtgui_dlist_node *node;
- /* subtract the topwin rect */
- rtgui_region_subtract_rect(&(widget->clip), &(widget->clip), rect);
+#ifdef RTGUI_USING_DESKTOP_WINDOW
+ _rtgui_topwin_dump(the_desktop_topwin);
+ rt_kprintf("\n");
+ rtgui_dlist_foreach(node, &the_desktop_topwin->child_list, next)
+ {
+ _rtgui_topwin_dump_tree(get_topwin_from_list(node));
+ rt_kprintf("\n");
}
- rt_sem_release(&_rtgui_topwin_lock);
+#else
+ rtgui_dlist_foreach(node, &_rtgui_topwin_list, next)
+ {
+ _rtgui_topwin_dump_tree(get_topwin_from_list(node));
+ rt_kprintf("\n");
+ }
+#endif
}
-
diff --git a/components/rtgui/server/topwin.h b/components/rtgui/server/topwin.h
index 8ec5a5c6cc..bc9db9d284 100644
--- a/components/rtgui/server/topwin.h
+++ b/components/rtgui/server/topwin.h
@@ -15,7 +15,6 @@
#define __RTGUI_TOPWIN_H__
#include <rtgui/rtgui.h>
-#include <rtgui/list.h>
#include <rtgui/region.h>
#include <rtgui/event.h>
#include <rtgui/widgets/title.h>
@@ -25,25 +24,24 @@
rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event);
rt_err_t rtgui_topwin_remove(struct rtgui_win* wid);
-/* raise window to front */
-void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender);
-/* update clip info to a panel */
-void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel);
+void rtgui_topwin_activate_win(struct rtgui_topwin* win);
/* show a window */
-void rtgui_topwin_show(struct rtgui_event_win* event);
+rt_err_t rtgui_topwin_show(struct rtgui_event_win* event);
/* hide a window */
-void rtgui_topwin_hide(struct rtgui_event_win* event);
+rt_err_t rtgui_topwin_hide(struct rtgui_event_win* event);
/* move a window */
-void rtgui_topwin_move(struct rtgui_event_win_move* event);
+rt_err_t rtgui_topwin_move(struct rtgui_event_win_move* event);
/* resize a window */
void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r);
+/* a window is entering modal mode */
+rt_err_t rtgui_topwin_modal_enter(struct rtgui_event_win_modal_enter* event);
/* get window at (x, y) */
struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y);
+struct rtgui_topwin* rtgui_topwin_get_wnd_no_modaled(int x, int y);
-void rtgui_topwin_activate_win(struct rtgui_topwin* win);
-void rtgui_topwin_deactivate_win(struct rtgui_topwin* win);
+//void rtgui_topwin_deactivate_win(struct rtgui_topwin* win);
/* window title */
void rtgui_topwin_title_ondraw(struct rtgui_topwin* win);
@@ -53,7 +51,7 @@ void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mou
void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect);
void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect);
-void rtgui_topwin_do_clip(rtgui_widget_t* widget);
-
+/* get the topwin that is currently focused */
+struct rtgui_topwin* rtgui_topwin_get_focus(void);
#endif