server.c 11.6 KB
Newer Older
B
bernard.xiong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * File      : server.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 <rtgui/rtgui.h>
#include <rtgui/event.h>
B
bernard.xiong 已提交
17
#include <rtgui/rtgui_system.h>
18
#include <rtgui/rtgui_object.h>
19
#include <rtgui/rtgui_app.h>
B
bernard.xiong 已提交
20 21 22 23 24
#include <rtgui/driver.h>

#include "mouse.h"
#include "topwin.h"

G
Grissiom 已提交
25
static struct rtgui_app *rtgui_server_app = RT_NULL;
26
static struct rtgui_app *rtgui_wm_application = RT_NULL;
B
bernard.xiong 已提交
27

28
void rtgui_server_handle_update(struct rtgui_event_update_end *event)
B
bernard.xiong 已提交
29
{
30
    struct rtgui_graphic_driver *driver;
31

32 33 34 35 36
    driver = rtgui_graphic_driver_get_default();
    if (driver != RT_NULL)
    {
        rtgui_graphic_driver_screen_update(driver, &(event->rect));
    }
B
bernard.xiong 已提交
37 38
}

39
void rtgui_server_handle_monitor_add(struct rtgui_event_monitor *event)
B
bernard.xiong 已提交
40
{
41 42
    /* add monitor rect to top window list */
    rtgui_topwin_append_monitor_rect(event->wid, &(event->rect));
B
bernard.xiong 已提交
43 44
}

45
void rtgui_server_handle_monitor_remove(struct rtgui_event_monitor *event)
B
bernard.xiong 已提交
46
{
47 48
    /* add monitor rect to top window list */
    rtgui_topwin_remove_monitor_rect(event->wid, &(event->rect));
B
bernard.xiong 已提交
49 50
}

51
void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse *event)
B
bernard.xiong 已提交
52
{
53
    struct rtgui_topwin *wnd;
B
bernard.xiong 已提交
54

55 56
    /* re-init to server thread */
    RTGUI_EVENT_MOUSE_BUTTON_INIT(event);
B
bernard.xiong 已提交
57

G
Grissiom 已提交
58 59 60
	/* set cursor position */
	rtgui_mouse_set_position(event->x, event->y);

61
#ifdef RTGUI_USING_WINMOVE
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
    if (rtgui_winrect_is_moved() &&
            event->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP))
    {
        struct rtgui_topwin *topwin;
        rtgui_rect_t rect;

        if (rtgui_winrect_moved_done(&rect, &topwin) == RT_TRUE)
        {
            struct rtgui_event_win_move ewin;

            /* move window */
            RTGUI_EVENT_WIN_MOVE_INIT(&ewin);
            ewin.wid = topwin->wid;
            if (topwin->title != RT_NULL)
            {
                if (topwin->flag & WINTITLE_BORDER)
                {
                    ewin.x = rect.x1 + WINTITLE_BORDER_SIZE;
                    ewin.y = rect.y1 + WINTITLE_BORDER_SIZE;
                }
                if (!(topwin->flag & WINTITLE_NO)) ewin.y += WINTITLE_HEIGHT;
            }
            else
            {
                ewin.x = rect.x1;
                ewin.y = rect.y1;
            }

            /* send to client thread */
G
Grissiom 已提交
91
            rtgui_send(topwin->app, &(ewin.parent), sizeof(ewin));
92 93 94 95

            return;
        }
    }
96
#endif
B
bernard.xiong 已提交
97

98 99 100 101 102 103
    /* get the wnd which contains the mouse */
    wnd = rtgui_topwin_get_wnd_no_modaled(event->x, event->y);
    if (wnd != RT_NULL)
    {
        event->wid = wnd->wid;

G
Grissiom 已提交
104 105 106
        /* only raise window if the button is pressed down */
        if (event->button & RTGUI_MOUSE_BUTTON_DOWN
            && rtgui_topwin_get_focus() != wnd)
107 108 109 110 111 112 113 114 115 116 117 118
        {
            rtgui_topwin_activate_topwin(wnd);
        }

        if (wnd->title != RT_NULL &&
                rtgui_rect_contains_point(&(RTGUI_WIDGET(wnd->title)->extent), event->x, event->y) == RT_EOK)
        {
            rtgui_topwin_title_onmouse(wnd, event);
        }
        else
        {
            /* send mouse event to thread */
G
Grissiom 已提交
119
            rtgui_send(wnd->app, (struct rtgui_event *)event, sizeof(struct rtgui_event_mouse));
120 121 122
        }
        return ;
    }
B
bernard.xiong 已提交
123 124
}

125
static struct rtgui_topwin *last_monitor_topwin = RT_NULL;
B
bernard.xiong 已提交
126

127
void rtgui_server_handle_mouse_motion(struct rtgui_event_mouse *event)
B
bernard.xiong 已提交
128
{
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
    /* the topwin contains current mouse */
    struct rtgui_topwin *win    = RT_NULL;

    /* re-init mouse event */
    RTGUI_EVENT_MOUSE_MOTION_INIT(event);

    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)
        {
            win = RT_NULL;
        }
    }

    if (last_monitor_topwin != RT_NULL)
    {
        event->wid = last_monitor_topwin->wid;
        /* send mouse motion event */
G
Grissiom 已提交
151
        rtgui_send(last_monitor_topwin->app, &(event->parent), sizeof(struct rtgui_event_mouse));
152 153 154 155 156 157 158 159 160 161
    }

    if (last_monitor_topwin != win)
    {
        last_monitor_topwin = win;
        if (last_monitor_topwin != RT_NULL)
        {
            event->wid = last_monitor_topwin->wid;

            /* send mouse motion event */
G
Grissiom 已提交
162
            rtgui_send(last_monitor_topwin->app, &(event->parent), sizeof(struct rtgui_event_mouse));
163 164 165 166 167
        }
    }

    /* move mouse to (x, y) */
    rtgui_mouse_moveto(event->x, event->y);
B
bernard.xiong 已提交
168 169
}

170
void rtgui_server_handle_kbd(struct rtgui_event_kbd *event)
B
bernard.xiong 已提交
171
{
172
    struct rtgui_topwin *wnd;
B
bernard.xiong 已提交
173

174 175
    /* re-init to server thread */
    RTGUI_EVENT_KBD_INIT(event);
B
bernard.xiong 已提交
176

177
    /* todo: handle input method and global shortcut */
B
bernard.xiong 已提交
178

179 180 181 182
    wnd = rtgui_topwin_get_focus();
    if (wnd != RT_NULL)
    {
        RT_ASSERT(wnd->flag & WINTITLE_ACTIVATE)
183

184 185
        /* send to focus window */
        event->wid = wnd->wid;
B
bernard.xiong 已提交
186

187
        /* send keyboard event to thread */
G
Grissiom 已提交
188
        rtgui_send(wnd->app, (struct rtgui_event *)event, sizeof(struct rtgui_event_kbd));
B
bernard.xiong 已提交
189

190 191
        return;
    }
192
}
B
bernard.xiong 已提交
193

194
#ifdef _WIN32_NATIVE
195 196
#include <windows.h>
#endif
B
bernard.xiong 已提交
197

198
static rt_bool_t rtgui_server_event_handler(struct rtgui_object *object,
199
        struct rtgui_event *event)
200 201 202 203 204 205 206
{
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(event != RT_NULL);

    /* dispatch event */
    switch (event->type)
    {
207
    case RTGUI_EVENT_APP_CREATE:
208 209 210 211
    case RTGUI_EVENT_APP_DESTROY:
        if (rtgui_wm_application != RT_NULL)
        {
            /* forward event to wm application */
G
Grissiom 已提交
212
            rtgui_send(rtgui_wm_application, event, sizeof(struct rtgui_event_application));
213 214 215 216 217 218 219 220 221
        }
        else
        {
            /* always ack with OK */
            rtgui_ack(event, RTGUI_STATUS_OK);
        }
        break;

        /* mouse and keyboard event */
222 223
    case RTGUI_EVENT_MOUSE_MOTION:
        /* handle mouse motion event */
224
        rtgui_server_handle_mouse_motion((struct rtgui_event_mouse *)event);
225 226 227 228
        break;

    case RTGUI_EVENT_MOUSE_BUTTON:
        /* handle mouse button */
229
        rtgui_server_handle_mouse_btn((struct rtgui_event_mouse *)event);
230 231 232 233
        break;

    case RTGUI_EVENT_KBD:
        /* handle keyboard event */
234
        rtgui_server_handle_kbd((struct rtgui_event_kbd *)event);
235 236
        break;

237
        /* window event */
238
    case RTGUI_EVENT_WIN_CREATE:
239 240 241 242
        if (rtgui_topwin_add((struct rtgui_event_win_create *)event) == RT_EOK)
            rtgui_ack(event, RTGUI_STATUS_OK);
        else
            rtgui_ack(event, RTGUI_STATUS_ERROR);
243 244 245
        break;

    case RTGUI_EVENT_WIN_SHOW:
246
        if (rtgui_topwin_show((struct rtgui_event_win *)event) == RT_EOK)
247
            rtgui_ack(event, RTGUI_STATUS_OK);
248
        else
249
            rtgui_ack(event, RTGUI_STATUS_ERROR);
250 251 252
        break;

    case RTGUI_EVENT_WIN_HIDE:
253
        if (rtgui_topwin_hide((struct rtgui_event_win *)event) == RT_EOK)
254
            rtgui_ack(event, RTGUI_STATUS_OK);
255
        else
256
            rtgui_ack(event, RTGUI_STATUS_ERROR);
257 258 259
        break;

    case RTGUI_EVENT_WIN_MOVE:
260
        if (rtgui_topwin_move((struct rtgui_event_win_move *)event) == RT_EOK)
261
            rtgui_ack(event, RTGUI_STATUS_OK);
262
        else
263
            rtgui_ack(event, RTGUI_STATUS_ERROR);
264 265
        break;

266 267 268 269 270 271
    case RTGUI_EVENT_WIN_MODAL_ENTER:
        if (rtgui_topwin_modal_enter((struct rtgui_event_win_modal_enter *)event) == RT_EOK)
            rtgui_ack(event, RTGUI_STATUS_OK);
        else
            rtgui_ack(event, RTGUI_STATUS_ERROR);
        break;
272

273 274 275 276 277 278
    case RTGUI_EVENT_WIN_ACTIVATE:
        if (rtgui_topwin_activate((struct rtgui_event_win_activate *)event) == RT_EOK)
            rtgui_ack(event, RTGUI_STATUS_OK);
        else
            rtgui_ack(event, RTGUI_STATUS_ERROR);
        break;
279 280

    case RTGUI_EVENT_WIN_DESTROY:
281 282 283 284
        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)
285 286 287 288 289
            rtgui_ack(event, RTGUI_STATUS_OK);
        else
            rtgui_ack(event, RTGUI_STATUS_ERROR);
        break;

290
    case RTGUI_EVENT_WIN_RESIZE:
291 292
        rtgui_topwin_resize(((struct rtgui_event_win_resize *)event)->wid,
                            &(((struct rtgui_event_win_resize *)event)->rect));
293
        break;
B
bernard.xiong 已提交
294

295 296 297 298 299 300 301 302 303 304 305 306 307 308
    case RTGUI_EVENT_SET_WM:
        if (rtgui_wm_application != RT_NULL)
        {
            rtgui_ack(event, RTGUI_STATUS_ERROR);
        }
        else
        {
            struct rtgui_event_set_wm *set_wm;

            set_wm = (struct rtgui_event_set_wm *) event;
            rtgui_wm_application = set_wm->app;
            rtgui_ack(event, RTGUI_STATUS_OK);
        }
        break;
309

310
        /* other event */
311 312 313
    case RTGUI_EVENT_COMMAND:
        break;

314 315 316 317
    case RTGUI_EVENT_UPDATE_BEGIN:
#ifdef RTGUI_USING_MOUSE_CURSOR
        /* hide cursor */
        rtgui_mouse_hide_cursor();
B
bernard.xiong 已提交
318
#endif
319 320 321 322
        break;

    case RTGUI_EVENT_UPDATE_END:
        /* handle screen update */
323
        rtgui_server_handle_update((struct rtgui_event_update_end *)event);
324 325 326 327 328 329 330 331
#ifdef RTGUI_USING_MOUSE_CURSOR
        /* show cursor */
        rtgui_mouse_show_cursor();
#endif
        break;

    case RTGUI_EVENT_MONITOR_ADD:
        /* handle mouse monitor */
332
        rtgui_server_handle_monitor_add((struct rtgui_event_monitor *)event);
333
        break;
334 335 336
    default:
        rt_kprintf("RTGUI: wrong event sent to server: %d", event->type);
        return RT_FALSE;
337 338
    }

339
    return RT_TRUE;
340
}
B
bernard.xiong 已提交
341 342 343 344

/**
 * rtgui server thread's entry
 */
345
static void rtgui_server_entry(void *parameter)
B
bernard.xiong 已提交
346
{
347 348 349 350
#ifdef _WIN32_NATIVE
    /* set the server thread to highest */
    HANDLE hCurrentThread = GetCurrentThread();
    SetThreadPriority(hCurrentThread, THREAD_PRIORITY_HIGHEST);
B
bernard.xiong 已提交
351 352
#endif

353
    /* create rtgui server application */
G
Grissiom 已提交
354 355 356
    rtgui_server_app = rtgui_app_create("rtgui");
    rt_kprintf("RTGUI: create server: %p", rtgui_server_app);
    if (rtgui_server_app == RT_NULL)
357
        return;
B
bernard.xiong 已提交
358

G
Grissiom 已提交
359
    rtgui_object_set_event_handler(RTGUI_OBJECT(rtgui_server_app),
360
                                   rtgui_server_event_handler);
361 362
    /* init mouse and show */
    rtgui_mouse_init();
B
bernard.xiong 已提交
363
#ifdef RTGUI_USING_MOUSE_CURSOR
364
    rtgui_mouse_show_cursor();
B
bernard.xiong 已提交
365 366
#endif

G
Grissiom 已提交
367
    rtgui_app_run(rtgui_server_app);
B
bernard.xiong 已提交
368

G
Grissiom 已提交
369 370
    rtgui_app_destroy(rtgui_server_app);
    rtgui_server_app = RT_NULL;
B
bernard.xiong 已提交
371 372
}

373
void rtgui_server_post_event(struct rtgui_event *event, rt_size_t size)
B
bernard.xiong 已提交
374
{
G
Grissiom 已提交
375 376
    if (rtgui_server_app != RT_NULL)
        rtgui_send(rtgui_server_app, event, size);
377 378
    else
        rt_kprintf("post when server is not running\n");
379 380
}

381
rt_err_t rtgui_server_post_event_sync(struct rtgui_event *event, rt_size_t size)
382
{
G
Grissiom 已提交
383 384
    if (rtgui_server_app != RT_NULL)
        return rtgui_send_sync(rtgui_server_app, event, size);
385 386 387 388 389
    else
    {
        rt_kprintf("post when server is not running\n");
        return -RT_ENOSYS;
    }
B
bernard.xiong 已提交
390 391
}

G
Grissiom 已提交
392 393 394 395 396 397 398 399 400 401
struct rtgui_app* rtgui_get_server(void)
{
    rt_thread_t tid = rt_thread_find("rtgui");

    if (tid == RT_NULL)
        return RT_NULL;
    return (struct rtgui_app*)tid->user_data;
}
RTM_EXPORT(rtgui_get_server);

402
void rtgui_server_init(void)
B
bernard.xiong 已提交
403
{
G
Grissiom 已提交
404
    rt_thread_t tid;
405

G
Grissiom 已提交
406 407 408 409 410
    tid = rt_thread_create("rtgui",
                           rtgui_server_entry, RT_NULL,
                           RTGUI_SVR_THREAD_STACK_SIZE,
                           RTGUI_SVR_THREAD_PRIORITY,
                           RTGUI_SVR_THREAD_TIMESLICE);
B
bernard.xiong 已提交
411

412
    /* start rtgui server thread */
G
Grissiom 已提交
413 414
    if (tid != RT_NULL)
        rt_thread_startup(tid);
B
bernard.xiong 已提交
415
}