diff options
Diffstat (limited to 'components/rtgui_win/server/mouse.c')
| -rw-r--r-- | components/rtgui_win/server/mouse.c | 647 |
1 files changed, 647 insertions, 0 deletions
diff --git a/components/rtgui_win/server/mouse.c b/components/rtgui_win/server/mouse.c new file mode 100644 index 0000000000..c7244f7d64 --- /dev/null +++ b/components/rtgui_win/server/mouse.c @@ -0,0 +1,647 @@ +/* + * File : mouse.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ + +#include "mouse.h" +#include <rtgui/region.h> +#include <rtgui/driver.h> +#include <rtgui/rtgui_system.h> + +struct rtgui_cursor +{ + /* screen byte per pixel */ + rt_uint16_t bpp; + + /* screen pitch */ + rt_uint16_t screen_pitch; + + /* current cursor x and y */ + rt_uint16_t cx, cy; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* cursor pitch */ + rt_uint16_t cursor_pitch; + + /* show cursor and show cursor count */ + rt_bool_t show_cursor; + rt_base_t show_cursor_count; + + /* cursor rect info */ + rtgui_rect_t rect; + + /* cursor image and saved cursor */ + rtgui_image_t *cursor_image; + rt_uint8_t *cursor_saved; +#endif + +#ifdef RTGUI_USING_WINMOVE + /* move window rect and border */ + rtgui_win_t *win; + rtgui_rect_t win_rect; + rt_uint8_t *win_left, *win_right; + rt_uint8_t *win_top, *win_bottom; + rt_bool_t win_rect_show, win_rect_has_saved; +#endif + + /* screen framebuffer */ + rt_uint8_t* framebuffer; +}; + +struct rtgui_cursor* _rtgui_cursor; + +#ifdef RTGUI_USING_MOUSE_CURSOR +struct rt_mutex cursor_mutex; +static const rt_uint8_t *cursor_xpm[] = { + "16 16 35 1", + " c None", + ". c #A0B8D0", + "+ c #F0F0F0", + "@ c #FFFFFF", + "# c #F0F8F0", + "$ c #A0B0D0", + "% c #90A8C0", + "& c #A0B0C0", + "* c #E0E8F0", + "= c #8090B0", + "- c #D0D8E0", + "; c #7080A0", + "> c #90A0B0", + ", c #FFF8FF", + "' c #F0F8FF", + ") c #607090", + "! c #8098B0", + "~ c #405060", + "{ c #405070", + "] c #506070", + "^ c #607080", + "/ c #708090", + "( c #7088A0", + "_ c #D0D0E0", + ": c #607890", + "< c #C0D0E0", + "[ c #C0C8D0", + "} c #506880", + "| c #5F778F", + "1 c #D0D8F0", + "2 c #506080", + "3 c #C0C8E0", + "4 c #A0A8C0", + "5 c #405870", + "6 c #5F6F8F", + " . ", + " .. ", + " .+. ", + " .@#$ ", + " $@@+% ", + " &@@@*= ", + " %@@@@-; ", + " >@@,''-) ", + " !,''+)~{] ", + " ='-^*/ ", + " (_{:<[^ ", + " ;} |:12 ", + " / )345 ", + " 6}${ ", + " 5{ ", + " "}; + +static void rtgui_cursor_restore (void); +static void rtgui_cursor_save (void); +static void rtgui_cursor_show (void); +#endif + +#ifdef RTGUI_USING_WINMOVE +static void rtgui_winrect_restore (void); +static void rtgui_winrect_save (void); +static void rtgui_winrect_show (void); +#endif + +#define WIN_MOVE_BORDER 4 +void rtgui_mouse_init() +{ + const struct rtgui_graphic_driver* gd = rtgui_graphic_driver_get_default(); + + _rtgui_cursor = (struct rtgui_cursor*) rtgui_malloc(sizeof(struct rtgui_cursor)); + rt_memset(_rtgui_cursor, 0, sizeof(struct rtgui_cursor)); + +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_init(&cursor_mutex, "cursor", RT_IPC_FLAG_FIFO); +#endif + + /* init cursor */ + _rtgui_cursor->bpp = gd->byte_per_pixel; + _rtgui_cursor->framebuffer = gd->get_framebuffer(); + _rtgui_cursor->screen_pitch = _rtgui_cursor->bpp * gd->width; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* init cursor image */ + _rtgui_cursor->cursor_image = rtgui_image_create_from_mem("xpm", (rt_uint8_t*)cursor_xpm, sizeof(cursor_xpm),RT_TRUE); + if (_rtgui_cursor->cursor_image == RT_NULL) + { + rtgui_free(_rtgui_cursor); + _rtgui_cursor = RT_NULL; + + return; + } + + /* init rect */ + _rtgui_cursor->rect.x1 = gd->width/2;
+ _rtgui_cursor->rect.y1 = gd->height/2; + _rtgui_cursor->rect.x2 = _rtgui_cursor->rect.x1 + _rtgui_cursor->cursor_image->w; + _rtgui_cursor->rect.y2 = _rtgui_cursor->rect.y1 + _rtgui_cursor->cursor_image->h; + + _rtgui_cursor->cursor_pitch = _rtgui_cursor->cursor_image->w * _rtgui_cursor->bpp; + + _rtgui_cursor->show_cursor = RT_TRUE; + _rtgui_cursor->show_cursor_count = 0; + _rtgui_cursor->cursor_saved = rtgui_malloc(_rtgui_cursor->cursor_image->w * + _rtgui_cursor->cursor_image->h * _rtgui_cursor->bpp); +#endif
+ + +#ifdef RTGUI_USING_WINMOVE + /* init window move save image */ + _rtgui_cursor->win_rect_has_saved = RT_FALSE; + _rtgui_cursor->win_rect_show = RT_FALSE; + + _rtgui_cursor->win_left = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER); + _rtgui_cursor->win_right = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER); + _rtgui_cursor->win_top = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER); + _rtgui_cursor->win_bottom = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER); +#endif +} + +void rtgui_mouse_moveto(int x, int y) +{ +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER); +#endif + + if (x != _rtgui_cursor->cx || y != _rtgui_cursor->cy) + { +#ifdef RTGUI_USING_WINMOVE + if (_rtgui_cursor->win_rect_show) + { + if (_rtgui_cursor->win_rect_has_saved == RT_TRUE) + { + rtgui_winrect_restore(); + } + +#ifdef RTGUI_USING_MOUSE_CURSOR + rtgui_mouse_hide_cursor(); +#endif + + /* move winrect */ + rtgui_rect_moveto(&(_rtgui_cursor->win_rect), x - _rtgui_cursor->cx, + y - _rtgui_cursor->cy); + rtgui_winrect_save(); + + /* move current cursor */ + _rtgui_cursor->cx = x; + _rtgui_cursor->cy = y; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* show cursor */ + rtgui_mouse_show_cursor(); +#endif + /* show winrect */ + rtgui_winrect_show(); + } + else +#endif + { +#ifdef RTGUI_USING_MOUSE_CURSOR + rtgui_mouse_hide_cursor(); +#endif + /* move current cursor */ + _rtgui_cursor->cx = x; + _rtgui_cursor->cy = y; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* show cursor */ + rtgui_mouse_show_cursor(); +#endif + } + } + +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_release(&cursor_mutex); +#endif +} + +#ifdef RTGUI_USING_MOUSE_CURSOR +void rtgui_mouse_set_cursor_enable(rt_bool_t enable) +{ + _rtgui_cursor->show_cursor = enable; +} + +/* set current cursor image */ +void rtgui_mouse_set_cursor(rtgui_image_t* cursor) +{ +} + +void rtgui_mouse_get_cursor_rect(rtgui_rect_t* rect) +{ + if (rect != RT_NULL) + { + *rect = _rtgui_cursor->rect; + } +} + +void rtgui_mouse_show_cursor() +{ + if (_rtgui_cursor->show_cursor == RT_FALSE) + return; + + _rtgui_cursor->show_cursor_count ++; + if (_rtgui_cursor->show_cursor_count == 1) + { + /* save show mouse area */ + rtgui_cursor_save(); + + /* show mouse cursor */ + rtgui_cursor_show(); + } +} + +void rtgui_mouse_hide_cursor() +{ + if (_rtgui_cursor->show_cursor == RT_FALSE) + return; + + if (_rtgui_cursor->show_cursor_count == 1) + { + /* display the cursor coverage area */ + rtgui_cursor_restore(); + } + _rtgui_cursor->show_cursor_count --; +} + +rt_bool_t rtgui_mouse_is_intersect(rtgui_rect_t* r) +{ + return rtgui_rect_is_intersect(&(_rtgui_cursor->rect), r) == RT_EOK? RT_TRUE : RT_FALSE; +} + +/* display the saved cursor area to screen */ +static void rtgui_cursor_restore() +{ + rt_base_t idx, height, cursor_pitch; + rt_uint8_t *cursor_ptr, *fb_ptr; + + fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch + + _rtgui_cursor->cx * _rtgui_cursor->bpp; + cursor_ptr = _rtgui_cursor->cursor_saved; + + height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h < + rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h : + rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy; + + cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w < + rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch : + (rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp; + + for (idx = 0; idx < height; idx ++) + { + rt_memcpy(fb_ptr, cursor_ptr, cursor_pitch); + + fb_ptr += _rtgui_cursor->screen_pitch; + cursor_ptr += _rtgui_cursor->cursor_pitch; + } +} + +/* save the cursor coverage area from screen */ +static void rtgui_cursor_save() +{ + rt_base_t idx, height, cursor_pitch; + rt_uint8_t *cursor_ptr, *fb_ptr; + + fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch + + _rtgui_cursor->cx * _rtgui_cursor->bpp; + cursor_ptr = _rtgui_cursor->cursor_saved; + + height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h < + rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h : + rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy; + + cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w < + rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch : + (rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp; + + for (idx = 0; idx < height; idx ++) + { + rt_memcpy(cursor_ptr, fb_ptr, cursor_pitch); + + fb_ptr += _rtgui_cursor->screen_pitch; + cursor_ptr += _rtgui_cursor->cursor_pitch; + } +} + +static void rtgui_cursor_show() +{ + rt_uint16_t x, y; + rtgui_color_t* ptr; + rtgui_rect_t rect; + void (*set_pixel) (rtgui_color_t *c, rt_base_t x, rt_base_t y); + + ptr = (rtgui_color_t*) _rtgui_cursor->cursor_image->data; + set_pixel = rtgui_graphic_driver_get_default()->set_pixel; + + rtgui_mouse_get_cursor_rect(&rect); + rtgui_rect_moveto(&rect, _rtgui_cursor->cx, _rtgui_cursor->cy); + + /* draw each point */ + for (y = rect.y1; y < rect.y2; y ++) + { + for (x = rect.x1; x < rect.x2; x++) + { + /* not alpha */ + if ((*ptr >> 24) != 255) + { + set_pixel(ptr, x, y); + } + + /* move to next color buffer */ + ptr ++; + } + } + + /* update rect */ + rtgui_graphic_driver_get_default()->screen_update(&rect); +} +#endif + +#ifdef RTGUI_USING_WINMOVE +void rtgui_winrect_set(rtgui_win_t* win) +{ + /* set win rect show */ + _rtgui_cursor->win_rect_show = RT_TRUE; + + /* set win rect */ + _rtgui_cursor->win_rect = RTGUI_WIDGET_EXTENT(win); + _rtgui_cursor->win = win; +}
+ +void rtgui_cursor_set_location(int x, int y)
+{
+ _rtgui_cursor->cx = x; + _rtgui_cursor->cy = y;
+}
+ +rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t* winrect, rtgui_win_t** win) +{ + rt_bool_t moved = RT_FALSE; + + /* no win rect */ + if (winrect == RT_NULL) return RT_FALSE; + + /* restore winrect */ + if (_rtgui_cursor->win_rect_has_saved) + { + rtgui_winrect_restore(); + + moved = RT_TRUE; + } + + /* clear win rect show */ + _rtgui_cursor->win_rect_show = RT_FALSE; + _rtgui_cursor->win_rect_has_saved = RT_FALSE; + + /* return win rect */ + *winrect = _rtgui_cursor->win_rect; + *win = _rtgui_cursor->win; + + return moved; +} + +rt_bool_t rtgui_winrect_is_moved() +{ + return _rtgui_cursor->win_rect_show; +} + +/* show winrect */ +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); + + c = black; + set_pixel = rtgui_graphic_driver_get_default()->set_pixel; + + win_rect = _rtgui_cursor->win_rect;
+ + win_rect_inner = win_rect; + rtgui_rect_inflate(&win_rect_inner, -WIN_MOVE_BORDER); + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), + &screen_rect); + rtgui_rect_intersect(&screen_rect, &win_rect); + rtgui_rect_intersect(&screen_rect, &win_rect_inner); + + /* draw left */ + for (y = win_rect.y1; y < win_rect.y2; y ++) + { + for (x = win_rect.x1; x < win_rect_inner.x1; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* draw right */ + for (y = win_rect.y1; y < win_rect.y2; y ++) + { + for (x = win_rect_inner.x2; x < win_rect.x2; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* draw top border */ + for (y = win_rect.y1; y < win_rect_inner.y1; y ++) + { + for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* draw bottom border */ + for (y = win_rect_inner.y2; y < win_rect.y2; y ++) + { + for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* update rect */ + rtgui_graphic_driver_get_default()->screen_update(&win_rect); +} + +#define display_direct_memcpy(src, dest, src_pitch, dest_pitch, height, len) \ + for (idx = 0; idx < height; idx ++) \ + { \ + rt_memcpy(dest, src, len); \ + src += src_pitch; \ + dest += dest_pitch; \ + } + +static void rtgui_winrect_restore() +{ + rt_uint8_t *winrect_ptr, *fb_ptr; + int winrect_pitch, idx; + rtgui_rect_t screen_rect, win_rect; + + win_rect = _rtgui_cursor->win_rect; + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), + &screen_rect); + rtgui_rect_intersect(&screen_rect, &win_rect); + + /* restore winrect left */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + win_rect.x1 * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_left; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* restore winrect right */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_right; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* restore winrect top */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_top; + winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + WIN_MOVE_BORDER, winrect_pitch); + + /* restore winrect bottom */ + fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_bottom; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + WIN_MOVE_BORDER, winrect_pitch); +} + +static void rtgui_winrect_save() +{ + rt_uint8_t *winrect_ptr, *fb_ptr; + int winrect_pitch, idx; + rtgui_rect_t screen_rect, win_rect; + + win_rect = _rtgui_cursor->win_rect; + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), + &screen_rect); + rtgui_rect_intersect(&screen_rect, &win_rect); + + /* set winrect has saved */ + _rtgui_cursor->win_rect_has_saved = RT_TRUE; + + /* save winrect left */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + win_rect.x1 * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_left; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* save winrect right */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_right; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* save winrect top */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_top; + winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + WIN_MOVE_BORDER, winrect_pitch); + + /* save winrect bottom */ + fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_bottom; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + WIN_MOVE_BORDER, winrect_pitch); +} +#endif + +void rtgui_mouse_monitor_append(rtgui_list_t* head, rtgui_rect_t* rect) +{ + struct rtgui_mouse_monitor* mmonitor; + + /* check parameters */ + if (head == RT_NULL || rect == RT_NULL) return; + + /* create a mouse monitor node */ + mmonitor = (struct rtgui_mouse_monitor*) rtgui_malloc (sizeof(struct rtgui_mouse_monitor)); + if (mmonitor == RT_NULL) return; /* no memory */ + + /* set mouse monitor node */ + mmonitor->rect = *rect; + rtgui_list_init(&(mmonitor->list)); + + /* append to list */ + rtgui_list_append(head, &(mmonitor->list)); +} + +void rtgui_mouse_monitor_remove(rtgui_list_t* head, rtgui_rect_t* rect) +{ + rtgui_list_t* node; + struct rtgui_mouse_monitor* mmonitor; + + /* check parameters */ + if (head == RT_NULL || rect == RT_NULL) return; + + for (node = head->next; node != RT_NULL; node = node->next) + { + mmonitor = rtgui_list_entry(node, struct rtgui_mouse_monitor, list); + if (mmonitor->rect.x1 == rect->x1 && + mmonitor->rect.x2 == rect->x2 && + mmonitor->rect.y1 == rect->y1 && + mmonitor->rect.y2 == rect->y2) + { + /* found node */ + rtgui_list_remove(head, node); + rtgui_free(mmonitor); + + return ; + } + } +} + +rt_bool_t rtgui_mouse_monitor_contains_point(rtgui_list_t* head, int x, int y) +{ + rtgui_list_t* node; + + /* check parameter */ + if (head == RT_NULL) return RT_FALSE; + + rtgui_list_foreach(node, head) + { + struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node, + struct rtgui_mouse_monitor, list); + + if (rtgui_rect_contains_point(&(monitor->rect), x, y) == RT_EOK) + { + return RT_TRUE; + } + } + + return RT_FALSE; +} |
