aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--types/wlr_cursor.c170
1 files changed, 91 insertions, 79 deletions
diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c
index 141e8eea..8f79046e 100644
--- a/types/wlr_cursor.c
+++ b/types/wlr_cursor.c
@@ -59,12 +59,6 @@ struct wlr_cursor_output_cursor {
struct wl_listener layout_output_destroy;
// only when using a surface as the cursor image
- struct wlr_surface *surface;
- struct {
- int32_t x, y;
- } surface_hotspot;
- struct wl_listener surface_commit;
- struct wl_listener surface_destroy;
struct wl_listener output_commit;
// only when using an XCursor as the cursor image
@@ -85,6 +79,14 @@ struct wlr_cursor_state {
struct wl_listener layout_add;
struct wl_listener layout_change;
struct wl_listener layout_destroy;
+
+ // only when using a surface as the cursor image
+ struct wlr_surface *surface;
+ struct {
+ int32_t x, y;
+ } surface_hotspot;
+ struct wl_listener surface_commit;
+ struct wl_listener surface_destroy;
};
struct wlr_cursor *wlr_cursor_create(void) {
@@ -128,6 +130,9 @@ struct wlr_cursor *wlr_cursor_create(void) {
wl_signal_init(&cur->events.tablet_tool_button);
wl_signal_init(&cur->events.tablet_tool_proximity);
+ wl_list_init(&cur->state->surface_destroy.link);
+ wl_list_init(&cur->state->surface_commit.link);
+
cur->x = 100;
cur->y = 100;
@@ -138,9 +143,6 @@ static void cursor_output_cursor_reset_image(struct wlr_cursor_output_cursor *ou
static void output_cursor_destroy(struct wlr_cursor_output_cursor *output_cursor) {
cursor_output_cursor_reset_image(output_cursor);
- wl_list_remove(&output_cursor->surface_destroy.link);
- wl_list_remove(&output_cursor->surface_commit.link);
- wl_list_remove(&output_cursor->output_commit.link);
wl_list_remove(&output_cursor->layout_output_destroy.link);
wl_list_remove(&output_cursor->link);
wlr_output_cursor_destroy(output_cursor->output_cursor);
@@ -199,7 +201,24 @@ static void cursor_device_destroy(struct wlr_cursor_device *c_device) {
free(c_device);
}
+static void cursor_reset_image(struct wlr_cursor *cur) {
+ if (cur->state->surface != NULL) {
+ struct wlr_cursor_output_cursor *output_cursor;
+ wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
+ wlr_surface_send_leave(cur->state->surface,
+ output_cursor->output_cursor->output);
+ }
+ }
+
+ wl_list_remove(&cur->state->surface_destroy.link);
+ wl_list_remove(&cur->state->surface_commit.link);
+ wl_list_init(&cur->state->surface_destroy.link);
+ wl_list_init(&cur->state->surface_commit.link);
+ cur->state->surface = NULL;
+}
+
void wlr_cursor_destroy(struct wlr_cursor *cur) {
+ cursor_reset_image(cur);
cursor_detach_output_layout(cur);
struct wlr_cursor_device *device, *device_tmp = NULL;
@@ -369,17 +388,8 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev,
}
static void cursor_output_cursor_reset_image(struct wlr_cursor_output_cursor *output_cursor) {
- if (output_cursor->surface != NULL) {
- wlr_surface_send_leave(output_cursor->surface,
- output_cursor->output_cursor->output);
- }
- wl_list_remove(&output_cursor->surface_destroy.link);
- wl_list_remove(&output_cursor->surface_commit.link);
wl_list_remove(&output_cursor->output_commit.link);
- wl_list_init(&output_cursor->surface_destroy.link);
- wl_list_init(&output_cursor->surface_commit.link);
wl_list_init(&output_cursor->output_commit.link);
- output_cursor->surface = NULL;
output_cursor->xcursor = NULL;
output_cursor->xcursor_index = 0;
@@ -389,30 +399,37 @@ static void cursor_output_cursor_reset_image(struct wlr_cursor_output_cursor *ou
output_cursor->xcursor_timer = NULL;
}
-static void output_cursor_output_commit_surface(
- struct wlr_cursor_output_cursor *output_cursor) {
- struct wlr_surface *surface = output_cursor->surface;
- struct wlr_output *output = output_cursor->output_cursor->output;
- assert(output_cursor->surface != NULL);
+static void cursor_commit_surface(struct wlr_cursor *cur) {
+ struct wlr_surface *surface = cur->state->surface;
+ assert(surface != NULL);
struct wlr_texture *texture = wlr_surface_get_texture(surface);
- int32_t hotspot_x = output_cursor->surface_hotspot.x;
- int32_t hotspot_y = output_cursor->surface_hotspot.y;
+ int32_t hotspot_x = cur->state->surface_hotspot.x;
+ int32_t hotspot_y = cur->state->surface_hotspot.y;
- output_cursor_set_texture(output_cursor->output_cursor, texture, false,
- surface->current.scale, surface->current.transform,
- hotspot_x, hotspot_y);
+ struct wlr_cursor_output_cursor *output_cursor;
+ wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
+ struct wlr_output *output = output_cursor->output_cursor->output;
- if (output_cursor->output_cursor->visible) {
- wlr_surface_send_enter(surface, output);
- } else {
- wlr_surface_send_leave(surface, output);
+ output_cursor_set_texture(output_cursor->output_cursor, texture, false,
+ surface->current.scale, surface->current.transform,
+ hotspot_x, hotspot_y);
+
+ if (output_cursor->output_cursor->visible) {
+ wlr_surface_send_enter(surface, output);
+ } else {
+ wlr_surface_send_leave(surface, output);
+ }
}
}
void wlr_cursor_set_image(struct wlr_cursor *cur, const uint8_t *pixels,
int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x,
int32_t hotspot_y, float scale) {
+ if (scale <= 0) {
+ cursor_reset_image(cur);
+ }
+
struct wlr_cursor_output_cursor *output_cursor;
wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
float output_scale = output_cursor->output_cursor->output->scale;
@@ -467,6 +484,8 @@ static void output_cursor_set_xcursor_image(struct wlr_cursor_output_cursor *out
void wlr_cursor_set_xcursor(struct wlr_cursor *cur,
struct wlr_xcursor_manager *manager, const char *name) {
+ cursor_reset_image(cur);
+
struct wlr_cursor_output_cursor *output_cursor;
wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
float scale = output_cursor->output_cursor->output->scale;
@@ -482,25 +501,22 @@ void wlr_cursor_set_xcursor(struct wlr_cursor *cur,
}
}
-static void output_cursor_output_handle_surface_destroy(
+static void cursor_handle_surface_destroy(
struct wl_listener *listener, void *data) {
- struct wlr_cursor_output_cursor *output_cursor =
- wl_container_of(listener, output_cursor, surface_destroy);
- assert(output_cursor->surface != NULL);
- wlr_output_cursor_set_buffer(output_cursor->output_cursor, NULL, 0, 0);
- cursor_output_cursor_reset_image(output_cursor);
+ struct wlr_cursor_state *state = wl_container_of(listener, state, surface_destroy);
+ assert(state->surface != NULL);
+ wlr_cursor_unset_image(&state->cursor);
}
-static void output_cursor_output_handle_surface_commit(
+static void cursor_handle_surface_commit(
struct wl_listener *listener, void *data) {
- struct wlr_cursor_output_cursor *output_cursor =
- wl_container_of(listener, output_cursor, surface_commit);
- struct wlr_surface *surface = output_cursor->surface;
+ struct wlr_cursor_state *state = wl_container_of(listener, state, surface_commit);
+ struct wlr_surface *surface = state->surface;
- output_cursor->surface_hotspot.x -= surface->current.dx;
- output_cursor->surface_hotspot.y -= surface->current.dy;
+ state->surface_hotspot.x -= surface->current.dx;
+ state->surface_hotspot.y -= surface->current.dy;
- output_cursor_output_commit_surface(output_cursor);
+ cursor_commit_surface(&state->cursor);
}
static void output_cursor_output_handle_output_commit(
@@ -508,12 +524,12 @@ static void output_cursor_output_handle_output_commit(
struct wlr_cursor_output_cursor *output_cursor =
wl_container_of(listener, output_cursor, output_commit);
const struct wlr_output_event_commit *event = data;
- struct wlr_surface *surface = output_cursor->surface;
+ struct wlr_surface *surface = output_cursor->cursor->state->surface;
assert(surface != NULL);
if (output_cursor->output_cursor->visible &&
(event->committed & WLR_OUTPUT_STATE_BUFFER)) {
- wlr_surface_send_frame_done(output_cursor->surface, event->when);
+ wlr_surface_send_frame_done(surface, event->when);
}
}
@@ -524,40 +540,38 @@ void wlr_cursor_set_surface(struct wlr_cursor *cur, struct wlr_surface *surface,
return;
}
- struct wlr_cursor_output_cursor *output_cursor;
- wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
- if (surface == output_cursor->surface &&
- hotspot_x == output_cursor->surface_hotspot.x &&
- hotspot_y == output_cursor->surface_hotspot.y) {
- continue;
- }
+ if (surface == cur->state->surface &&
+ hotspot_x == cur->state->surface_hotspot.x &&
+ hotspot_y == cur->state->surface_hotspot.y) {
+ return;
+ }
- if (surface != output_cursor->surface) {
- // Only send wl_surface.leave if the surface changes
- cursor_output_cursor_reset_image(output_cursor);
-
- output_cursor->surface = surface;
-
- wl_signal_add(&surface->events.destroy,
- &output_cursor->surface_destroy);
- output_cursor->surface_destroy.notify =
- output_cursor_output_handle_surface_destroy;
- wl_signal_add(&surface->events.commit,
- &output_cursor->surface_commit);
- output_cursor->surface_commit.notify =
- output_cursor_output_handle_surface_commit;
-
- wl_signal_add(&output_cursor->output_cursor->output->events.commit,
- &output_cursor->output_commit);
- output_cursor->output_commit.notify =
- output_cursor_output_handle_output_commit;
- }
+ if (surface != cur->state->surface) {
+ // Only send wl_surface.leave if the surface changes
+ cursor_reset_image(cur);
+
+ cur->state->surface = surface;
+
+ wl_signal_add(&surface->events.destroy, &cur->state->surface_destroy);
+ cur->state->surface_destroy.notify = cursor_handle_surface_destroy;
+ wl_signal_add(&surface->events.commit, &cur->state->surface_commit);
+ cur->state->surface_commit.notify = cursor_handle_surface_commit;
+ }
+
+ cur->state->surface_hotspot.x = hotspot_x;
+ cur->state->surface_hotspot.y = hotspot_y;
- output_cursor->surface_hotspot.x = hotspot_x;
- output_cursor->surface_hotspot.y = hotspot_y;
+ struct wlr_cursor_output_cursor *output_cursor;
+ wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
+ cursor_output_cursor_reset_image(output_cursor);
- output_cursor_output_commit_surface(output_cursor);
+ wl_signal_add(&output_cursor->output_cursor->output->events.commit,
+ &output_cursor->output_commit);
+ output_cursor->output_commit.notify =
+ output_cursor_output_handle_output_commit;
}
+
+ cursor_commit_surface(cur);
}
static void handle_pointer_motion(struct wl_listener *listener, void *data) {
@@ -985,8 +999,6 @@ static void layout_add(struct wlr_cursor_state *state,
}
output_cursor->cursor = &state->cursor;
- wl_list_init(&output_cursor->surface_destroy.link);
- wl_list_init(&output_cursor->surface_commit.link);
wl_list_init(&output_cursor->output_commit.link);
output_cursor->output_cursor = wlr_output_cursor_create(l_output->output);