diff options
Diffstat (limited to 'components/rtgui/widgets/window.c')
| -rw-r--r-- | components/rtgui/widgets/window.c | 554 |
1 files changed, 256 insertions, 298 deletions
diff --git a/components/rtgui/widgets/window.c b/components/rtgui/widgets/window.c index c1df9379ff..f8d5db3d24 100644 --- a/components/rtgui/widgets/window.c +++ b/components/rtgui/widgets/window.c @@ -15,27 +15,37 @@ #include <rtgui/color.h> #include <rtgui/image.h> #include <rtgui/rtgui_system.h> +#include <rtgui/rtgui_server.h> +#include <rtgui/rtgui_application.h> #include <rtgui/widgets/window.h> #include <rtgui/widgets/button.h> -#include <rtgui/widgets/workbench.h> static void _rtgui_win_constructor(rtgui_win_t *win) { + RTGUI_WIDGET(win)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + win->parent_window = RT_NULL; /* init window attribute */ - win->on_activate = RT_NULL; - win->on_deactivate = RT_NULL; - win->on_close = RT_NULL; - win->title = RT_NULL; - win->modal_code = RTGUI_MODAL_OK; - win->modal_widget = RT_NULL; + win->on_activate = RT_NULL; + win->on_deactivate = RT_NULL; + win->on_close = RT_NULL; + win->on_key = RT_NULL; + win->title = RT_NULL; + win->modal_code = RTGUI_MODAL_OK; + + /* initialize last mouse event handled widget */ + win->last_mevent_widget = RT_NULL; + win->focused_widget = RT_NULL; /* set window hide */ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win)); /* set window style */ win->style = RTGUI_WIN_STYLE_DEFAULT; - rtgui_widget_set_event_handler(RTGUI_WIDGET(win), rtgui_win_event_handler); + + win->flag = RTGUI_WIN_FLAG_INIT; + + rtgui_object_set_event_handler(RTGUI_OBJECT(win), rtgui_win_event_handler); /* init user data */ win->user_data = 0; @@ -45,12 +55,12 @@ static void _rtgui_win_destructor(rtgui_win_t* win) { struct rtgui_event_win_destroy edestroy; - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* destroy in server */ RTGUI_EVENT_WIN_DESTROY_INIT(&edestroy); edestroy.wid = win; - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&edestroy), + if (rtgui_server_post_event_sync(RTGUI_EVENT(&edestroy), sizeof(struct rtgui_event_win_destroy)) != RT_EOK) { /* destroy in server failed */ @@ -62,225 +72,238 @@ static void _rtgui_win_destructor(rtgui_win_t* win) rt_free(win->title); } -static rt_bool_t _rtgui_win_create_in_server(rtgui_win_t* win) +static rt_bool_t _rtgui_win_create_in_server(struct rtgui_win *win) { - if (RTGUI_TOPLEVEL(win)->server == RT_NULL) + if (!(win->flag & RTGUI_WIN_FLAG_CONNECTED)) { - rt_thread_t server; struct rtgui_event_win_create ecreate; RTGUI_EVENT_WIN_CREATE_INIT(&ecreate); - /* get server thread id */ - server = rtgui_thread_get_server(); - if (server == RT_NULL) - { - rt_kprintf("RTGUI server is not running...\n"); - return RT_FALSE; - } - /* send win create event to server */ - ecreate.wid = win; - ecreate.parent.user = win->style; + ecreate.parent_window = win->parent_window; + ecreate.wid = win; + ecreate.parent.user = win->style; #ifndef RTGUI_USING_SMALL_SIZE - ecreate.extent = RTGUI_WIDGET(win)->extent; + ecreate.extent = RTGUI_WIDGET(win)->extent; rt_strncpy((char*)ecreate.title, (char*)win->title, RTGUI_NAME_MAX); #endif - if (rtgui_thread_send_sync(server, RTGUI_EVENT(&ecreate), - sizeof(struct rtgui_event_win_create)) != RT_EOK) + if (rtgui_server_post_event_sync(RTGUI_EVENT(&ecreate), + sizeof(struct rtgui_event_win_create) + ) != RT_EOK) { rt_kprintf("create win: %s failed\n", win->title); return RT_FALSE; } - /* set server */ - RTGUI_TOPLEVEL(win)->server = server; + win->flag |= RTGUI_WIN_FLAG_CONNECTED; } return RT_TRUE; } -DEFINE_CLASS_TYPE(win, "win", +DEFINE_CLASS_TYPE(win, "win", RTGUI_TOPLEVEL_TYPE, _rtgui_win_constructor, _rtgui_win_destructor, sizeof(struct rtgui_win)); -rtgui_win_t* rtgui_win_create(rtgui_toplevel_t* parent_toplevel, const char* title, rtgui_rect_t *rect, rt_uint8_t style) +#ifdef RTGUI_USING_DESKTOP_WINDOW +static struct rtgui_win *the_desktop_window; +#endif + +rtgui_win_t* rtgui_win_create(struct rtgui_win* parent_window, + const char* title, + rtgui_rect_t *rect, + rt_uint16_t style) { struct rtgui_win* win; /* allocate win memory */ - win = (struct rtgui_win*) rtgui_widget_create (RTGUI_WIN_TYPE); - if (win != RT_NULL) + win = RTGUI_WIN(rtgui_widget_create(RTGUI_WIN_TYPE)); + if (win == RT_NULL) + return RT_NULL; + + /* set parent toplevel */ +#ifdef RTGUI_USING_DESKTOP_WINDOW + if (style & RTGUI_WIN_STYLE_DESKTOP) { - /* set parent toplevel */ - win->parent_toplevel = parent_toplevel; + RT_ASSERT(the_desktop_window == RT_NULL); + win->parent_window = RT_NULL; + the_desktop_window = win; + } + else if (parent_window == RT_NULL) + { + RT_ASSERT(the_desktop_window != RT_NULL); + win->parent_window = the_desktop_window; + } + else + win->parent_window = parent_window; +#else + win->parent_window = parent_window; +#endif - /* set title, rect and style */ - if (title != RT_NULL) win->title = rt_strdup(title); - else win->title = RT_NULL; + /* set title, rect and style */ + if (title != RT_NULL) + win->title = rt_strdup(title); + else + win->title = RT_NULL; - rtgui_widget_set_rect(RTGUI_WIDGET(win), rect); - win->style = style; + rtgui_widget_set_rect(RTGUI_WIDGET(win), rect); + win->style = style; - if (_rtgui_win_create_in_server(win) == RT_FALSE) - { - rtgui_widget_destroy(RTGUI_WIDGET(win)); - return RT_NULL; - } + if (_rtgui_win_create_in_server(win) == RT_FALSE) + { + goto __on_err; } - return win; + +__on_err: + rtgui_widget_destroy(RTGUI_WIDGET(win)); + return RT_NULL; } void rtgui_win_destroy(struct rtgui_win* win) { - if (win->style & RTGUI_WIN_STYLE_MODAL) + if (win->flag & RTGUI_WIN_FLAG_MODAL) { - /* end modal */ + /* set the RTGUI_WIN_STYLE_DESTROY_ON_CLOSE flag so the window will be + * destroyed after the event_loop */ + win->style |= RTGUI_WIN_STYLE_DESTROY_ON_CLOSE; rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL); } else - { rtgui_widget_destroy(RTGUI_WIDGET(win)); +} + +static rt_bool_t _rtgui_win_deal_close(struct rtgui_win *win, + struct rtgui_event *event) +{ + if (win->on_close != RT_NULL) + { + if (win->on_close(RTGUI_OBJECT(win), event) == RT_FALSE) + return RT_FALSE; + } + + rtgui_win_hiden(win); + + win->flag |= RTGUI_WIN_FLAG_CLOSED; + + if (win->flag & RTGUI_WIN_FLAG_MODAL) + { + rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL); } + else if (win->style & RTGUI_WIN_STYLE_DESTROY_ON_CLOSE) + { + rtgui_win_destroy(win); + } + + return RT_TRUE; } -void rtgui_win_close(struct rtgui_win* win) +/* send a close event to myself to get a consistent behavior */ +rt_bool_t rtgui_win_close(struct rtgui_win* win) { - win->style |= RTGUI_WIN_STYLE_CLOSED; + struct rtgui_event_win_close eclose; + + RTGUI_EVENT_WIN_CLOSE_INIT(&eclose); + eclose.wid = win; + return _rtgui_win_deal_close(win, + (struct rtgui_event*)&eclose); } -rtgui_modal_code_t rtgui_win_show(struct rtgui_win* win, rt_bool_t is_modal) +rt_base_t rtgui_win_show(struct rtgui_win* win, rt_bool_t is_modal) { - rtgui_modal_code_t result; + struct rtgui_event_win_show eshow; + rt_base_t exit_code = -1; - RT_ASSERT(win != RT_NULL); - result = RTGUI_MODAL_CANCEL; + RTGUI_EVENT_WIN_SHOW_INIT(&eshow); + eshow.wid = win; + + if (win == RT_NULL) + return exit_code; /* if it does not register into server, create it in server */ - if (RTGUI_TOPLEVEL(win)->server == RT_NULL) + if (!(win->flag & RTGUI_WIN_FLAG_CONNECTED)) { if (_rtgui_win_create_in_server(win) == RT_FALSE) - return result; + return exit_code; } - if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(win))) + if (rtgui_server_post_event_sync(RTGUI_EVENT(&eshow), + sizeof(struct rtgui_event_win_show) + ) != RT_EOK) { - /* send show message to server */ - struct rtgui_event_win_show eshow; - RTGUI_EVENT_WIN_SHOW_INIT(&eshow); - eshow.wid = win; + rt_kprintf("show win failed\n"); + return exit_code; + } - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&eshow), - sizeof(struct rtgui_event_win_show)) != RT_EOK) - { - /* hide window failed */ - return result; - } + /* set window unhidden */ + RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win)); - /* set window unhidden */ - RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win)); - } - else rtgui_widget_update(RTGUI_WIDGET(win)); + if (win->focused_widget == RT_NULL) + rtgui_widget_focus(RTGUI_WIDGET(win)); - if (is_modal == RT_TRUE) - { - if (win->parent_toplevel != RT_NULL) - { - rtgui_widget_t *parent_widget; + if (is_modal == RT_TRUE) + { + struct rtgui_application *app; + struct rtgui_event_win_modal_enter emodal; - /* set style */ - win->style |= RTGUI_WIN_STYLE_MODAL; + RTGUI_EVENT_WIN_MODAL_ENTER_INIT(&emodal); + emodal.wid = win; - /* get root toplevel */ - parent_widget = RTGUI_WIDGET(win->parent_toplevel); - if (RTGUI_IS_WORKBENCH(parent_widget)) - { - rtgui_workbench_t* workbench; - workbench = RTGUI_WORKBENCH(win->parent_toplevel); - workbench->flag |= RTGUI_WORKBENCH_FLAG_MODAL_MODE; - workbench->modal_widget = RTGUI_WIDGET(win); + app = rtgui_application_self(); + RT_ASSERT(app != RT_NULL); - rtgui_workbench_event_loop(workbench); - result = workbench->modal_code; - workbench->flag &= ~RTGUI_WORKBENCH_FLAG_MODAL_MODE; - workbench->modal_widget = RT_NULL; - } - else if (RTGUI_IS_WIN(parent_widget)) - { - rtgui_win_t* parent_win; - parent_win = RTGUI_WIN(win->parent_toplevel); - parent_win->style |= RTGUI_WIN_STYLE_UNDER_MODAL; - parent_win->modal_widget = RTGUI_WIDGET(win); + win->flag |= RTGUI_WIN_FLAG_MODAL; - rtgui_win_event_loop(parent_win); - result = parent_win->modal_code; - parent_win->style &= ~RTGUI_WIN_STYLE_UNDER_MODAL; - parent_win->modal_widget = RT_NULL; - } - } - else - { - /* which is a root window */ - win->style |= RTGUI_WIN_STYLE_MODAL; - rtgui_win_event_loop(win); + if (rtgui_server_post_event_sync((struct rtgui_event*)&emodal, + sizeof(emodal)) != RT_EOK) + return exit_code; - result = win->modal_code; - win->style &= ~RTGUI_WIN_STYLE_MODAL; + app->modal_object = RTGUI_OBJECT(win); + + exit_code = rtgui_application_run(app); + + app->modal_object = RT_NULL; + win->flag &= ~RTGUI_WIN_FLAG_MODAL; + + if (win->style & RTGUI_WIN_STYLE_DESTROY_ON_CLOSE) + { + rtgui_win_destroy(win); } - } + } - return result; + return exit_code; } void rtgui_win_end_modal(struct rtgui_win* win, rtgui_modal_code_t modal_code) { - if (win->parent_toplevel != RT_NULL) - { - if (RTGUI_IS_WORKBENCH(win->parent_toplevel)) - { - rtgui_workbench_t* workbench; + if (win == RT_NULL || !(win->flag & RTGUI_WIN_FLAG_MODAL)) + return; - /* which is shown under workbench */ - workbench = RTGUI_WORKBENCH(win->parent_toplevel); - workbench->modal_code = modal_code; - workbench->flag &= ~RTGUI_WORKBENCH_FLAG_MODAL_MODE; - } - else if (RTGUI_IS_WIN(win->parent_toplevel)) - { - rtgui_win_t* parent_win; - - /* which is shown under win */ - parent_win = RTGUI_WIN(win->parent_toplevel); - parent_win->modal_code = modal_code; - parent_win->style &= ~RTGUI_WIN_STYLE_UNDER_MODAL; - } - } - else - { - /* which is a stand alone window */ - win->modal_code = modal_code; - } + rtgui_application_exit(rtgui_application_self(), modal_code); /* remove modal mode */ - win->style &= ~RTGUI_WIN_STYLE_MODAL; + win->flag &= ~RTGUI_WIN_FLAG_MODAL; } void rtgui_win_hiden(struct rtgui_win* win) { RT_ASSERT(win != RT_NULL); +#ifdef RTGUI_USING_DESKTOP_WINDOW + RT_ASSERT(win != the_desktop_window); +#endif if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(win)) && - RTGUI_TOPLEVEL(win)->server != RT_NULL) + win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* send hidden message to server */ struct rtgui_event_win_hide ehide; RTGUI_EVENT_WIN_HIDE_INIT(&ehide); ehide.wid = win; - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&ehide), + if (rtgui_server_post_event_sync(RTGUI_EVENT(&ehide), sizeof(struct rtgui_event_win_hide)) != RT_EOK) { rt_kprintf("hide win: %s failed\n", win->title); @@ -289,7 +312,7 @@ void rtgui_win_hiden(struct rtgui_win* win) /* set window hide and deactivated */ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win)); - win->style &= ~RTGUI_WIN_STYLE_ACTIVATE; + win->flag &= ~RTGUI_WIN_FLAG_ACTIVATE; } } @@ -297,7 +320,7 @@ rt_bool_t rtgui_win_is_activated(struct rtgui_win* win) { RT_ASSERT(win != RT_NULL); - if (win->style & RTGUI_WIN_STYLE_ACTIVATE) return RT_TRUE; + if (win->flag & RTGUI_WIN_FLAG_ACTIVATE) return RT_TRUE; return RT_FALSE; } @@ -307,28 +330,29 @@ void rtgui_win_move(struct rtgui_win* win, int x, int y) struct rtgui_event_win_move emove; RTGUI_EVENT_WIN_MOVE_INIT(&emove); - if (win == RT_NULL) return; + if (win == RT_NULL) + return; + + /* move window to logic position */ + rtgui_widget_move_to_logic(RTGUI_WIDGET(win), + x - RTGUI_WIDGET(win)->extent.x1, + y - RTGUI_WIDGET(win)->extent.y1); - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* set win hide firstly */ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win)); - emove.wid = win; + emove.wid = win; emove.x = x; emove.y = y; - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&emove), + if (rtgui_server_post_event_sync(RTGUI_EVENT(&emove), sizeof(struct rtgui_event_win_move)) != RT_EOK) { return; } } - /* move window to logic position */ - rtgui_widget_move_to_logic(RTGUI_WIDGET(win), - x - RTGUI_WIDGET(win)->extent.x1, - y - RTGUI_WIDGET(win)->extent.y1); - /* set window visible */ RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win)); return; @@ -342,7 +366,8 @@ static rt_bool_t rtgui_win_ondraw(struct rtgui_win* win) /* begin drawing */ dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(win)); - if (dc == RT_NULL) return RT_FALSE; + if (dc == RT_NULL) + return RT_FALSE; /* get window rect */ rtgui_widget_get_rect(RTGUI_WIDGET(win), &rect); @@ -352,18 +377,22 @@ static rt_bool_t rtgui_win_ondraw(struct rtgui_win* win) /* paint each widget */ RTGUI_EVENT_PAINT_INIT(&event); event.wid = RT_NULL; - rtgui_container_dispatch_event(RTGUI_CONTAINER(win), (rtgui_event_t*)&event); + rtgui_container_dispatch_event(RTGUI_CONTAINER(win), + (rtgui_event_t*)&event); rtgui_dc_end_drawing(dc); return RT_FALSE; } -rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +rt_bool_t rtgui_win_event_handler(struct rtgui_object* object, struct rtgui_event* event) { - struct rtgui_win* win = (struct rtgui_win*)widget; + struct rtgui_win* win; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); - RT_ASSERT((win != RT_NULL) && (event != RT_NULL)); + win = RTGUI_WIN(object); switch (event->type) { @@ -376,22 +405,8 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even break; case RTGUI_EVENT_WIN_CLOSE: - if (win->on_close != RT_NULL) - { - if (win->on_close(widget, event) == RT_FALSE) return RT_TRUE; - } - - if (win->style & RTGUI_WIN_STYLE_MODAL) - { - rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL); - } - else - { - /* destroy window */ - rtgui_win_destroy(win); - } - - /* exit event loop */ + _rtgui_win_deal_close(win, event); + /* don't broadcast WIN_CLOSE event to others */ return RT_TRUE; case RTGUI_EVENT_WIN_MOVE: @@ -410,49 +425,54 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even return RT_TRUE; } - win->style |= RTGUI_WIN_STYLE_ACTIVATE; + win->flag |= RTGUI_WIN_FLAG_ACTIVATE; #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); - else + if (RTGUI_WIDGET(object)->on_draw != RT_NULL) + RTGUI_WIDGET(object)->on_draw(object, event); + else #endif rtgui_widget_update(RTGUI_WIDGET(win)); if (win->on_activate != RT_NULL) { - win->on_activate(widget, event); + win->on_activate(RTGUI_OBJECT(object), event); } break; case RTGUI_EVENT_WIN_DEACTIVATE: - if (win->style & RTGUI_WIN_STYLE_MODAL) + if (win->flag & RTGUI_WIN_FLAG_MODAL) { - /* do not deactivate a modal win, re-send win-show event */ - struct rtgui_event_win_show eshow; - RTGUI_EVENT_WIN_SHOW_INIT(&eshow); - eshow.wid = win; - - rtgui_thread_send(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&eshow), - sizeof(struct rtgui_event_win_show)); + /* FIXME: make modal concept clear and easy. See the comment of + * rtgui_topwin_modal_enter. */ + /* There are various reason that a modal window got deactivated: + * 1, it has child windows and the user activate one of them. + * 2, the application has more than one root window and the + * user switched to one of the others. + * + * In any of the cases, we have nothing to do here. + */ } else { - win->style &= ~RTGUI_WIN_STYLE_ACTIVATE; + win->flag &= ~RTGUI_WIN_FLAG_ACTIVATE; #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); - else + if (RTGUI_WIDGET(object)->on_draw != RT_NULL) + RTGUI_WIDGET(object)->on_draw(object, event); + else #endif - rtgui_win_ondraw(win); + rtgui_widget_update(RTGUI_WIDGET(win)); if (win->on_deactivate != RT_NULL) { - win->on_deactivate(widget, event); + win->on_deactivate(RTGUI_OBJECT(object), event); } } break; case RTGUI_EVENT_PAINT: #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + if (RTGUI_WIDGET(object)->on_draw != RT_NULL) + RTGUI_WIDGET(object)->on_draw(object, event); else #endif rtgui_win_ondraw(win); @@ -460,36 +480,22 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even case RTGUI_EVENT_MOUSE_BUTTON: /* check whether has widget which handled mouse event before */ - if (RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win) != RT_NULL) + if (win->last_mevent_widget != RT_NULL) { - struct rtgui_event_mouse* emouse; - - emouse = (struct rtgui_event_mouse*)event; - - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win)->event_handler(RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win), event); - if (rtgui_rect_contains_point(&(RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win)->extent), - emouse->x, emouse->y) == RT_EOK) - { - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win) = RT_NULL; - break; /* mouse event is inside of widget, do not handle it anymore */ - } + RTGUI_OBJECT(win->last_mevent_widget)->event_handler( + RTGUI_OBJECT(win->last_mevent_widget), + event); /* clean last mouse event handled widget */ - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win) = RT_NULL; + win->last_mevent_widget = RT_NULL; } - - if (win->style & RTGUI_WIN_STYLE_UNDER_MODAL) - { - if (win->modal_widget != RT_NULL) - return win->modal_widget->event_handler(win->modal_widget, event); - } - else if (rtgui_container_dispatch_mouse_event(RTGUI_CONTAINER(win), + else if (rtgui_container_dispatch_mouse_event(RTGUI_CONTAINER(win), (struct rtgui_event_mouse*)event) == RT_FALSE) { #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_mouseclick != RT_NULL) + if (RTGUI_WIDGET(object)->on_mouseclick != RT_NULL) { - return widget->on_mouseclick(widget, event); + return RTGUI_WIDGET(object)->on_mouseclick(object, event); } #endif } @@ -512,101 +518,45 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even #endif break; - case RTGUI_EVENT_KBD: - if (win->style & RTGUI_WIN_STYLE_UNDER_MODAL) + case RTGUI_EVENT_KBD: + /* we should dispatch key event firstly */ + if (!(win->flag & RTGUI_WIN_FLAG_HANDLE_KEY)) { - if (win->modal_widget != RT_NULL) - return win->modal_widget->event_handler(win->modal_widget, event); + rt_bool_t res = RT_FALSE; + /* we should dispatch the key event just once. Once entered the + * dispatch mode, we should swtich to key handling mode. */ + win->flag |= RTGUI_WIN_FLAG_HANDLE_KEY; + + /* dispatch the key event */ + if (win->focused_widget != RT_NULL && + RTGUI_OBJECT(win->focused_widget)->event_handler != RT_NULL) + res = RTGUI_OBJECT(win->focused_widget)->event_handler( + RTGUI_OBJECT(win->focused_widget), event); + + /* if the focused widget doesn't handle it, I will handle it. */ + if (res != RT_TRUE && win->on_key != RT_NULL) + res = win->on_key(RTGUI_OBJECT(win), event); + + win->flag &= ~RTGUI_WIN_FLAG_HANDLE_KEY; + return res; } - else if (RTGUI_CONTAINER(win)->focused != widget && - RTGUI_CONTAINER(win)->focused != RT_NULL) + else { - RTGUI_CONTAINER(win)->focused->event_handler(RTGUI_CONTAINER(win)->focused, event); + /* in key handling mode(it may reach here in + * win->focused_widget->event_handler call) */ + if (win->on_key != RT_NULL) + return win->on_key(RTGUI_OBJECT(win), event); } - break; + break; default: /* call parent event handler */ - return rtgui_toplevel_event_handler(widget, event); + return rtgui_toplevel_event_handler(object, event); } return RT_FALSE; } -/* windows event loop */ -void rtgui_win_event_loop(rtgui_win_t* wnd) -{ - rt_err_t result; - rtgui_thread_t* tid; - struct rtgui_event* event; - - tid = rtgui_thread_self(); - RT_ASSERT(tid != RT_NULL); - - /* point to event buffer */ - event = (struct rtgui_event*)tid->event_buffer; - - if (wnd->style & RTGUI_WIN_STYLE_UNDER_MODAL) - { - while (wnd->style & RTGUI_WIN_STYLE_UNDER_MODAL) - { - if (tid->on_idle != RT_NULL) - { - result = rtgui_thread_recv_nosuspend(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - else if (result == -RT_ETIMEOUT) - { - tid->on_idle(RTGUI_WIDGET(wnd), RT_NULL); - } - } - else - { - result = rtgui_thread_recv(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - } - } - } - else - { - while (!(wnd->style & RTGUI_WIN_STYLE_CLOSED)) - { - if (tid->on_idle != RT_NULL) - { - result = rtgui_thread_recv_nosuspend(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - else if (result == -RT_ETIMEOUT) - { - tid->on_idle(RTGUI_WIDGET(wnd), RT_NULL); - } - } - else - { - result = rtgui_thread_recv(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - } - } - } - - /* destroy window */ - rtgui_widget_destroy(RTGUI_WIDGET(wnd)); -} - void rtgui_win_set_rect(rtgui_win_t* win, rtgui_rect_t* rect) { struct rtgui_event_win_resize event; @@ -615,14 +565,14 @@ void rtgui_win_set_rect(rtgui_win_t* win, rtgui_rect_t* rect) RTGUI_WIDGET(win)->extent = *rect; - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* set window resize event to server */ RTGUI_EVENT_WIN_RESIZE_INIT(&event); event.wid = win; event.rect = *rect; - rtgui_thread_send(RTGUI_TOPLEVEL(win)->server, &(event.parent), sizeof(struct rtgui_event_win_resize)); + rtgui_server_post_event(&(event.parent), sizeof(struct rtgui_event_win_resize)); } } @@ -660,10 +610,18 @@ void rtgui_win_set_onclose(rtgui_win_t* win, rtgui_event_handler_ptr handler) } } +void rtgui_win_set_onkey(rtgui_win_t* win, rtgui_event_handler_ptr handler) +{ + if (win != RT_NULL) + { + win->on_key = handler; + } +} + void rtgui_win_set_title(rtgui_win_t* win, const char *title) { /* send title to server */ - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { } |
