diff --git a/include/input/cursor.h b/include/input/cursor.h index 540cc3d..c126312 100644 --- a/include/input/cursor.h +++ b/include/input/cursor.h @@ -67,6 +67,12 @@ struct kiwmi_cursor_scroll_event { bool handled; }; +void cursor_refresh_focus( + struct kiwmi_cursor *cursor, + struct wlr_surface **new_surface, + double *cursor_sx, + double *cursor_sy); + struct kiwmi_cursor *cursor_create( struct kiwmi_server *server, struct wlr_output_layout *output_layout); diff --git a/kiwmi/desktop/view.c b/kiwmi/desktop/view.c index 17b392a..aa5459c 100644 --- a/kiwmi/desktop/view.c +++ b/kiwmi/desktop/view.c @@ -113,8 +113,13 @@ view_set_pos(struct kiwmi_view *view, uint32_t x, uint32_t y) } } + struct kiwmi_desktop *desktop = view->desktop; + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + struct kiwmi_cursor *cursor = server->input.cursor; + cursor_refresh_focus(cursor, NULL, NULL, NULL); + struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { + wl_list_for_each (output, &desktop->outputs, link) { output_damage(output); } } diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index 345f1f1..3402a02 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -19,6 +19,7 @@ #include "desktop/desktop.h" #include "desktop/output.h" #include "desktop/view.h" +#include "input/cursor.h" #include "input/input.h" #include "input/seat.h" #include "server.h" @@ -204,9 +205,14 @@ xdg_surface_commit_notify(struct wl_listener *listener, void *UNUSED(data)) { struct kiwmi_view *view = wl_container_of(listener, view, commit); + struct kiwmi_desktop *desktop = view->desktop; + struct kiwmi_server *server = wl_container_of(desktop, server, desktop); + struct kiwmi_cursor *cursor = server->input.cursor; + cursor_refresh_focus(cursor, NULL, NULL, NULL); + if (pixman_region32_not_empty(&view->wlr_surface->buffer_damage)) { struct kiwmi_output *output; - wl_list_for_each (output, &view->desktop->outputs, link) { + wl_list_for_each (output, &desktop->outputs, link) { output_damage(output); } } @@ -225,6 +231,7 @@ xdg_surface_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) if (seat->focused_view == view) { seat->focused_view = NULL; } + cursor_refresh_focus(server->input.cursor, NULL, NULL, NULL); struct kiwmi_view_child *child, *tmpchild; wl_list_for_each_safe (child, tmpchild, &view->children, link) { diff --git a/kiwmi/input/cursor.c b/kiwmi/input/cursor.c index 35494c8..5f253da 100644 --- a/kiwmi/input/cursor.c +++ b/kiwmi/input/cursor.c @@ -28,10 +28,9 @@ static void process_cursor_motion(struct kiwmi_server *server, uint32_t time) { - struct kiwmi_desktop *desktop = &server->desktop; - struct kiwmi_input *input = &server->input; - struct kiwmi_cursor *cursor = input->cursor; - struct wlr_seat *seat = input->seat->seat; + struct kiwmi_input *input = &server->input; + struct kiwmi_cursor *cursor = input->cursor; + struct wlr_seat *seat = input->seat->seat; switch (cursor->cursor_mode) { case KIWMI_CURSOR_MOVE: { @@ -84,48 +83,13 @@ process_cursor_motion(struct kiwmi_server *server, uint32_t time) break; } - double ox = 0; - double oy = 0; - struct wlr_output *wlr_output = wlr_output_layout_output_at( - desktop->output_layout, cursor->cursor->x, cursor->cursor->y); - - wlr_output_layout_output_coords( - desktop->output_layout, wlr_output, &ox, &oy); - - struct kiwmi_output *output = wlr_output->data; - - struct wlr_surface *surface = NULL; - double sx; - double sy; - - struct kiwmi_layer *layer = layer_at( - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], - &surface, - cursor->cursor->x, - cursor->cursor->y, - &sx, - &sy); - - if (!layer) { - struct kiwmi_view *view = view_at( - desktop, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); - - if (!view) { - wlr_xcursor_manager_set_cursor_image( - cursor->xcursor_manager, "left_ptr", cursor->cursor); - } - } - - if (surface) { - bool focus_changed = surface != seat->pointer_state.focused_surface; - - wlr_seat_pointer_notify_enter(seat, surface, sx, sy); - - if (!focus_changed) { - wlr_seat_pointer_notify_motion(seat, time, sx, sy); - } - } else { - wlr_seat_pointer_clear_focus(seat); + struct wlr_surface *old_focus = seat->pointer_state.focused_surface; + struct wlr_surface *new_focus; + double sx, sy; + cursor_refresh_focus(cursor, &new_focus, &sx, &sy); + if (new_focus && new_focus == old_focus) { + wlr_seat_pointer_notify_enter(seat, new_focus, sx, sy); + wlr_seat_pointer_notify_motion(seat, time, sx, sy); } } @@ -308,3 +272,93 @@ cursor_destroy(struct kiwmi_cursor *cursor) free(cursor); } + +void +cursor_refresh_focus( + struct kiwmi_cursor *cursor, + struct wlr_surface **new_surface, + double *cursor_sx, + double *cursor_sy) +{ + struct kiwmi_desktop *desktop = &cursor->server->desktop; + struct wlr_seat *seat = cursor->server->input.seat->seat; + + double ox = cursor->cursor->x; + double oy = cursor->cursor->y; + struct wlr_output *wlr_output = wlr_output_layout_output_at( + desktop->output_layout, cursor->cursor->x, cursor->cursor->y); + + wlr_output_layout_output_coords( + desktop->output_layout, wlr_output, &ox, &oy); + + struct kiwmi_output *output = wlr_output->data; + + struct wlr_surface *surface = NULL; + double sx; + double sy; + + struct kiwmi_layer *layer = layer_at( + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + &surface, + ox, + oy, + &sx, + &sy); + struct kiwmi_view *view; + + if (!layer) { + layer = layer_at( + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + &surface, + ox, + oy, + &sx, + &sy); + } + + if (!layer) { + view = view_at( + desktop, cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); + } + + if (!layer) { + layer = layer_at( + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + &surface, + ox, + oy, + &sx, + &sy); + } + + if (!layer) { + layer = layer_at( + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + &surface, + ox, + oy, + &sx, + &sy); + } + + if (!layer && !view) { + wlr_xcursor_manager_set_cursor_image( + cursor->xcursor_manager, "left_ptr", cursor->cursor); + } + + if (surface && surface != seat->pointer_state.focused_surface) { + wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + } else if (!surface) { + wlr_seat_pointer_clear_focus(seat); + } + + if (new_surface) { + *new_surface = surface; + } + if (cursor_sx) { + *cursor_sx = surface ? sx : 0; + } + if (cursor_sy) { + *cursor_sy = surface ? sy : 0; + } +} diff --git a/kiwmi/input/seat.c b/kiwmi/input/seat.c index 33bb5c3..57984f9 100644 --- a/kiwmi/input/seat.c +++ b/kiwmi/input/seat.c @@ -83,6 +83,7 @@ seat_focus_view(struct kiwmi_seat *seat, struct kiwmi_view *view) // move view to front wl_list_remove(&view->link); wl_list_insert(&desktop->views, &view->link); + cursor_refresh_focus(seat->input->cursor, NULL, NULL, NULL); seat->focused_view = view; view_set_activated(view, true);