diff options
author | Brian Ashworth <bosrsf04@gmail.com> | 2020-01-05 16:50:48 -0500 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2020-01-05 23:03:34 +0100 |
commit | 897c36b12cc4b706bcb730a47181d829d7ab9729 (patch) | |
tree | 23245af66dea5b04306102bd60d7726658932e28 | |
parent | render: do not render indicator on floating views (diff) | |
download | sway-897c36b12cc4b706bcb730a47181d829d7ab9729.tar.gz sway-897c36b12cc4b706bcb730a47181d829d7ab9729.tar.zst sway-897c36b12cc4b706bcb730a47181d829d7ab9729.zip |
input/cursor: handle image surface destroy
This adds a listener for the destroy event of the cursor image surface.
This prevents a use-after-free when the last visible image surface is
freed, there has not been a new cursor set, and the cursor is reshown.
-rw-r--r-- | include/sway/input/cursor.h | 1 | ||||
-rw-r--r-- | sway/input/cursor.c | 18 |
2 files changed, 19 insertions, 0 deletions
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 0bcd262f..5b6f9a9f 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h | |||
@@ -58,6 +58,7 @@ struct sway_cursor { | |||
58 | uint32_t tool_buttons; | 58 | uint32_t tool_buttons; |
59 | 59 | ||
60 | struct wl_listener request_set_cursor; | 60 | struct wl_listener request_set_cursor; |
61 | struct wl_listener image_surface_destroy; | ||
61 | 62 | ||
62 | struct wl_listener constraint_commit; | 63 | struct wl_listener constraint_commit; |
63 | 64 | ||
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 680fe39e..215dc767 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -789,6 +789,15 @@ static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { | |||
789 | cursor->pointer_gestures, cursor->seat->wlr_seat, | 789 | cursor->pointer_gestures, cursor->seat->wlr_seat, |
790 | event->time_msec, event->cancelled); | 790 | event->time_msec, event->cancelled); |
791 | } | 791 | } |
792 | |||
793 | static void handle_image_surface_destroy(struct wl_listener *listener, | ||
794 | void *data) { | ||
795 | struct sway_cursor *cursor = | ||
796 | wl_container_of(listener, cursor, image_surface_destroy); | ||
797 | cursor_set_image(cursor, NULL, cursor->image_client); | ||
798 | cursor_rebase(cursor); | ||
799 | } | ||
800 | |||
792 | void cursor_set_image(struct sway_cursor *cursor, const char *image, | 801 | void cursor_set_image(struct sway_cursor *cursor, const char *image, |
793 | struct wl_client *client) { | 802 | struct wl_client *client) { |
794 | if (!(cursor->seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER)) { | 803 | if (!(cursor->seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER)) { |
@@ -797,7 +806,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image, | |||
797 | 806 | ||
798 | const char *current_image = cursor->image; | 807 | const char *current_image = cursor->image; |
799 | cursor->image = image; | 808 | cursor->image = image; |
809 | wl_list_remove(&cursor->image_surface_destroy.link); | ||
800 | cursor->image_surface = NULL; | 810 | cursor->image_surface = NULL; |
811 | wl_list_init(&cursor->image_surface_destroy.link); | ||
801 | cursor->hotspot_x = cursor->hotspot_y = 0; | 812 | cursor->hotspot_x = cursor->hotspot_y = 0; |
802 | cursor->image_client = client; | 813 | cursor->image_client = client; |
803 | 814 | ||
@@ -821,7 +832,10 @@ void cursor_set_image_surface(struct sway_cursor *cursor, | |||
821 | } | 832 | } |
822 | 833 | ||
823 | cursor->image = NULL; | 834 | cursor->image = NULL; |
835 | wl_list_remove(&cursor->image_surface_destroy.link); | ||
824 | cursor->image_surface = surface; | 836 | cursor->image_surface = surface; |
837 | wl_signal_add(&cursor->image_surface->events.destroy, | ||
838 | &cursor->image_surface_destroy); | ||
825 | cursor->hotspot_x = hotspot_x; | 839 | cursor->hotspot_x = hotspot_x; |
826 | cursor->hotspot_y = hotspot_y; | 840 | cursor->hotspot_y = hotspot_y; |
827 | cursor->image_client = client; | 841 | cursor->image_client = client; |
@@ -840,6 +854,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) { | |||
840 | 854 | ||
841 | wl_event_source_remove(cursor->hide_source); | 855 | wl_event_source_remove(cursor->hide_source); |
842 | 856 | ||
857 | wl_list_remove(&cursor->image_surface_destroy.link); | ||
843 | wl_list_remove(&cursor->pinch_begin.link); | 858 | wl_list_remove(&cursor->pinch_begin.link); |
844 | wl_list_remove(&cursor->pinch_update.link); | 859 | wl_list_remove(&cursor->pinch_update.link); |
845 | wl_list_remove(&cursor->pinch_end.link); | 860 | wl_list_remove(&cursor->pinch_end.link); |
@@ -885,6 +900,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | |||
885 | cursor->hide_source = wl_event_loop_add_timer(server.wl_event_loop, | 900 | cursor->hide_source = wl_event_loop_add_timer(server.wl_event_loop, |
886 | hide_notify, cursor); | 901 | hide_notify, cursor); |
887 | 902 | ||
903 | wl_list_init(&cursor->image_surface_destroy.link); | ||
904 | cursor->image_surface_destroy.notify = handle_image_surface_destroy; | ||
905 | |||
888 | cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); | 906 | cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); |
889 | cursor->pinch_begin.notify = handle_pointer_pinch_begin; | 907 | cursor->pinch_begin.notify = handle_pointer_pinch_begin; |
890 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); | 908 | wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); |