diff --git a/docs/changes.md b/docs/changes.md index 40184f5f5..cf5809986 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -2,7 +2,7 @@ 2023/05/22 * 修复高亮对话框打开无窗口动画的窗口时候绘图不正常的问题(感谢智明提供补丁) - + * 修复鼠标进入和移出窗口时控件over状态没有正确更新的问题(感谢煜楷提供补丁) 2023/05/21 * 增加图片绘制类型:IMAGE\_DRAW\_FILL diff --git a/src/base/input_device_status.c b/src/base/input_device_status.c index 06ca269df..f2be943d1 100644 --- a/src/base/input_device_status.c +++ b/src/base/input_device_status.c @@ -321,7 +321,7 @@ static ret_t input_device_status_dispatch_input_event(input_device_status_t* ids pointer_event_t* evt = (pointer_event_t*)e; pointer_event_rotate(evt, system_info()); - if (evt->x != ids->last_x || evt->y != ids->last_y) { + if (evt->x != ids->last_x || evt->y != ids->last_y || ids->pointer_has_left_window) { ids->last_x = evt->x; ids->last_y = evt->y; @@ -452,3 +452,25 @@ ret_t input_device_status_on_ignore_input_event(input_device_status_t* ids, widg event_t* e) { return input_device_status_dispatch_input_event(ids, widget, e, FALSE); } + +ret_t input_device_status_on_pointer_enter(input_device_status_t* ids, widget_t* widget, xy_t x, xy_t y) { + pointer_event_t e; + ret_t ret = RET_OK; + return_value_if_fail(ids != NULL && widget != NULL, RET_BAD_PARAMS); + + pointer_event_init(&e, EVT_POINTER_MOVE, widget, x, y); + ret = input_device_status_on_input_event(ids, widget, (event_t*)&e); + ids->pointer_has_left_window = FALSE; + + return ret; +} + +ret_t input_device_status_on_pointer_leave(input_device_status_t* ids, widget_t* widget) { + pointer_event_t e; + return_value_if_fail(ids != NULL && widget != NULL, RET_BAD_PARAMS); + + ids->pointer_has_left_window = TRUE; + pointer_event_init(&e, EVT_POINTER_LEAVE, widget, 0, 0); + + return widget_dispatch_leave_event(widget, &e); +} diff --git a/src/base/input_device_status.h b/src/base/input_device_status.h index 4b873842f..49e21299e 100644 --- a/src/base/input_device_status.h +++ b/src/base/input_device_status.h @@ -61,6 +61,7 @@ typedef struct _input_device_status_t { xy_t last_x; xy_t last_y; bool_t pressed; + bool_t pointer_has_left_window; uint64_t last_pointer_down_time; uint64_t last_pointer_up_time; @@ -118,6 +119,10 @@ ret_t input_device_status_on_ignore_input_event(input_device_status_t* ids, widg */ ret_t input_device_status_abort_all_pressed_keys(input_device_status_t* ids); +ret_t input_device_status_on_pointer_enter(input_device_status_t* ids, widget_t* widget, xy_t x, xy_t y); + +ret_t input_device_status_on_pointer_leave(input_device_status_t* ids, widget_t* widget); + END_C_DECLS #endif /*TK_INPUT_DEVICE_STATUS_H*/ diff --git a/src/base/native_window.h b/src/base/native_window.h index e8156f4fe..136e81bb9 100644 --- a/src/base/native_window.h +++ b/src/base/native_window.h @@ -286,7 +286,9 @@ ret_t native_window_update_last_dirty_rect(native_window_t* win); typedef enum _native_window_event_type_t { EVT_NATIVE_WINDOW_RESIZED = 0xff, - EVT_NATIVE_WINDOW_DESTROY + EVT_NATIVE_WINDOW_DESTROY, + EVT_NATIVE_WINDOW_ENTER, + EVT_NATIVE_WINDOW_LEAVE, } native_window_event_type_t; END_C_DECLS diff --git a/src/base/widget.c b/src/base/widget.c index b1309e4b2..8999aacf0 100644 --- a/src/base/widget.c +++ b/src/base/widget.c @@ -3005,7 +3005,7 @@ ret_t widget_on_multi_gesture(widget_t* widget, multi_gesture_event_t* e) { return ret; } -static ret_t widget_dispatch_leave_event(widget_t* widget, pointer_event_t* e) { +ret_t widget_dispatch_leave_event(widget_t* widget, pointer_event_t* e) { ret_t ret = RET_OK; widget_t* target = widget; diff --git a/src/base/widget.h b/src/base/widget.h index d79c8563e..680ed3ed0 100644 --- a/src/base/widget.h +++ b/src/base/widget.h @@ -3326,6 +3326,7 @@ ret_t widget_on_pointer_up(widget_t* widget, pointer_event_t* e); ret_t widget_on_context_menu(widget_t* widget, pointer_event_t* e); bool_t widget_is_focusable(widget_t* widget); ret_t widget_destroy_sync(widget_t* widget); +ret_t widget_dispatch_leave_event(widget_t* widget, pointer_event_t* e); #define WIDGET_EXEC_START_ANIMATOR "start_animator" #define WIDGET_EXEC_STOP_ANIMATOR "stop_animator" diff --git a/src/main_loop/main_loop_sdl.c b/src/main_loop/main_loop_sdl.c index ec4a5c728..4261188bf 100644 --- a/src/main_loop/main_loop_sdl.c +++ b/src/main_loop/main_loop_sdl.c @@ -240,12 +240,26 @@ static ret_t main_loop_sdl2_dispatch_window_event(main_loop_simple_t* loop, SDL_ log_debug("Window %d restored\n", event->window.windowID); widget_invalidate_force(l->wm, NULL); break; - case SDL_WINDOWEVENT_ENTER: + case SDL_WINDOWEVENT_ENTER: { + int x = 0; + int y = 0; + pointer_event_t e; + SDL_Window* win = SDL_GetWindowFromID(event->window.windowID); + log_debug("Mouse entered window %d\n", event->window.windowID); + SDL_GetMouseState(&x, &y); + pointer_event_init(&e, EVT_NATIVE_WINDOW_ENTER, l->wm, x, y); + window_manager_dispatch_native_window_event(l->wm, (event_t*)&e, win); break; - case SDL_WINDOWEVENT_LEAVE: + } + case SDL_WINDOWEVENT_LEAVE: { + event_t e = event_init(EVT_NATIVE_WINDOW_LEAVE, NULL); + SDL_Window* win = SDL_GetWindowFromID(event->window.windowID); + log_debug("Mouse left window %d\n", event->window.windowID); + window_manager_dispatch_native_window_event(l->wm, &e, win); break; + } case SDL_WINDOWEVENT_FOCUS_GAINED: log_debug("Window %d gained keyboard focus\n", event->window.windowID); break; diff --git a/src/window_manager/window_manager_default.c b/src/window_manager/window_manager_default.c index 06aa31a38..bb9dfe148 100644 --- a/src/window_manager/window_manager_default.c +++ b/src/window_manager/window_manager_default.c @@ -1730,6 +1730,16 @@ static ret_t window_manager_default_dispatch_native_window_event(widget_t* widge void* handle) { if (e->type == EVT_NATIVE_WINDOW_RESIZED) { window_manager_default_native_window_resized(widget, handle); + } else if (e->type == EVT_NATIVE_WINDOW_ENTER) { + int32_t x = ((pointer_event_t*)e)->x; + int32_t y = ((pointer_event_t*)e)->y; + window_manager_default_t* wm = WINDOW_MANAGER_DEFAULT(widget); + input_device_status_t* ids = &wm->input_device_status; + input_device_status_on_pointer_enter(ids, widget, x, y); + } else if (e->type == EVT_NATIVE_WINDOW_LEAVE) { + window_manager_default_t* wm = WINDOW_MANAGER_DEFAULT(widget); + input_device_status_t* ids = &wm->input_device_status; + input_device_status_on_pointer_leave(ids, widget); } return RET_OK;