diff options
author | emersion <contact@emersion.fr> | 2018-03-30 10:53:18 -0400 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-03-30 10:53:18 -0400 |
commit | 6c9d67b1059409750de683aec3b8b9be2da987cc (patch) | |
tree | 37f052eee9461d9e9178b7e160b6a1ba38adae83 | |
parent | Fix crash when override redirect views close (diff) | |
download | sway-6c9d67b1059409750de683aec3b8b9be2da987cc.tar.gz sway-6c9d67b1059409750de683aec3b8b9be2da987cc.tar.zst sway-6c9d67b1059409750de683aec3b8b9be2da987cc.zip |
Handle set_cursor requests from clients
Allow clients to set a custom cursor if they have the seat's
pointer focus.
-rw-r--r-- | include/sway/input/cursor.h | 1 | ||||
-rw-r--r-- | sway/input/cursor.c | 50 |
2 files changed, 43 insertions, 8 deletions
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index a16b793b..64917ce5 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h | |||
@@ -9,6 +9,7 @@ struct sway_cursor { | |||
9 | struct wlr_xcursor_manager *xcursor_manager; | 9 | struct wlr_xcursor_manager *xcursor_manager; |
10 | 10 | ||
11 | double x, y; | 11 | double x, y; |
12 | struct wl_client *image_client; | ||
12 | 13 | ||
13 | struct wl_listener motion; | 14 | struct wl_listener motion; |
14 | struct wl_listener motion_absolute; | 15 | struct wl_listener motion_absolute; |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d57ac3e3..cded0005 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -25,10 +25,12 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
25 | struct wlr_surface *surface = NULL; | 25 | struct wlr_surface *surface = NULL; |
26 | double sx, sy; | 26 | double sx, sy; |
27 | 27 | ||
28 | struct sway_container *focus = NULL; | ||
29 | |||
28 | // check for unmanaged views first | 30 | // check for unmanaged views first |
29 | struct sway_view *view; | 31 | struct sway_view *view; |
30 | wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views, | 32 | wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views, |
31 | unmanaged_view_link) { | 33 | unmanaged_view_link) { |
32 | if (view->type == SWAY_XWAYLAND_VIEW) { | 34 | if (view->type == SWAY_XWAYLAND_VIEW) { |
33 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | 35 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
34 | struct wlr_box box = { | 36 | struct wlr_box box = { |
@@ -39,19 +41,34 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
39 | }; | 41 | }; |
40 | 42 | ||
41 | if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { | 43 | if (wlr_box_contains_point(&box, cursor->x, cursor->y)) { |
44 | focus = view->swayc; | ||
42 | surface = xsurface->surface; | 45 | surface = xsurface->surface; |
43 | sx = cursor->x - box.x; | 46 | sx = cursor->x - box.x; |
44 | sy = cursor->y - box.y; | 47 | sy = cursor->y - box.y; |
45 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); | 48 | break; |
46 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); | ||
47 | return; | ||
48 | } | 49 | } |
49 | } | 50 | } |
50 | } | 51 | } |
51 | 52 | ||
52 | struct sway_container *swayc = | 53 | // then check for managed views |
53 | container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); | 54 | if (focus == NULL) { |
54 | if (swayc) { | 55 | focus = container_at(&root_container, cursor->x, cursor->y, &surface, |
56 | &sx, &sy); | ||
57 | } | ||
58 | |||
59 | // reset cursor if switching between clients | ||
60 | struct wl_client *client = NULL; | ||
61 | if (focus) { | ||
62 | client = wl_resource_get_client(surface->resource); | ||
63 | } | ||
64 | if (client != cursor->image_client) { | ||
65 | wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, | ||
66 | "left_ptr", cursor->cursor); | ||
67 | cursor->image_client = client; | ||
68 | } | ||
69 | |||
70 | // send pointer enter/leave | ||
71 | if (focus) { | ||
55 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); | 72 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); |
56 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); | 73 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); |
57 | } else { | 74 | } else { |
@@ -145,7 +162,24 @@ static void handle_request_set_cursor(struct wl_listener *listener, | |||
145 | struct sway_cursor *cursor = | 162 | struct sway_cursor *cursor = |
146 | wl_container_of(listener, cursor, request_set_cursor); | 163 | wl_container_of(listener, cursor, request_set_cursor); |
147 | struct wlr_seat_pointer_request_set_cursor_event *event = data; | 164 | struct wlr_seat_pointer_request_set_cursor_event *event = data; |
148 | wlr_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); | 165 | |
166 | struct wl_client *focused_client = NULL; | ||
167 | struct wlr_surface *focused_surface = | ||
168 | cursor->seat->wlr_seat->pointer_state.focused_surface; | ||
169 | if (focused_surface != NULL) { | ||
170 | focused_client = wl_resource_get_client(focused_surface->resource); | ||
171 | } | ||
172 | |||
173 | // TODO: check cursor mode | ||
174 | if (focused_client == NULL || | ||
175 | event->seat_client->client != focused_client) { | ||
176 | wlr_log(L_DEBUG, "denying request to set cursor from unfocused client"); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | wlr_cursor_set_surface(cursor->cursor, event->surface, event->hotspot_x, | ||
181 | event->hotspot_y); | ||
182 | cursor->image_client = focused_client; | ||
149 | } | 183 | } |
150 | 184 | ||
151 | void sway_cursor_destroy(struct sway_cursor *cursor) { | 185 | void sway_cursor_destroy(struct sway_cursor *cursor) { |