mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-11-08 13:29:45 -05:00
Remove support for renderering software cursors
This commit is contained in:
parent
06644575da
commit
4ff8f944aa
7 changed files with 12 additions and 578 deletions
|
|
@ -29,10 +29,10 @@ examples = {
|
|||
'src': 'simple.c',
|
||||
'dep': [wlroots],
|
||||
},
|
||||
'pointer': {
|
||||
'src': 'pointer.c',
|
||||
'dep': [wlroots],
|
||||
},
|
||||
# 'pointer': {
|
||||
# 'src': 'pointer.c',
|
||||
# 'dep': [wlroots],
|
||||
# },
|
||||
'touch': {
|
||||
'src': ['touch.c', 'cat.c'],
|
||||
'dep': [wlroots],
|
||||
|
|
@ -45,10 +45,10 @@ examples = {
|
|||
'src': ['rotation.c', 'cat.c'],
|
||||
'dep': [wlroots],
|
||||
},
|
||||
'multi-pointer': {
|
||||
'src': 'multi-pointer.c',
|
||||
'dep': [wlroots],
|
||||
},
|
||||
# 'multi-pointer': {
|
||||
# 'src': 'multi-pointer.c',
|
||||
# 'dep': [wlroots],
|
||||
# },
|
||||
'output-layout': {
|
||||
'src': ['output-layout.c', 'cat.c'],
|
||||
'dep': [wlroots],
|
||||
|
|
|
|||
|
|
@ -131,25 +131,6 @@ void wlr_cursor_warp_absolute(struct wlr_cursor *cur,
|
|||
void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev,
|
||||
double delta_x, double delta_y);
|
||||
|
||||
/**
|
||||
* Set the cursor image. stride is given in bytes. If pixels is NULL, hides the
|
||||
* cursor.
|
||||
*
|
||||
* If scale isn't zero, the image is only set on outputs having the provided
|
||||
* scale.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Set the cursor surface. The surface can be committed to update the cursor
|
||||
* image. The surface position is subtracted from the hotspot. A NULL surface
|
||||
* commit hides the cursor.
|
||||
*/
|
||||
void wlr_cursor_set_surface(struct wlr_cursor *cur, struct wlr_surface *surface,
|
||||
int32_t hotspot_x, int32_t hotspot_y);
|
||||
|
||||
/**
|
||||
* Attaches this input device to this cursor. The input device must be one of:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -24,28 +24,6 @@ struct wlr_output_mode {
|
|||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct wlr_output_cursor {
|
||||
struct wlr_output *output;
|
||||
double x, y;
|
||||
bool enabled;
|
||||
bool visible;
|
||||
uint32_t width, height;
|
||||
int32_t hotspot_x, hotspot_y;
|
||||
struct wl_list link;
|
||||
|
||||
// only when using a software cursor without a surface
|
||||
struct wlr_texture *texture;
|
||||
|
||||
// only when using a cursor surface
|
||||
struct wlr_surface *surface;
|
||||
struct wl_listener surface_commit;
|
||||
struct wl_listener surface_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
};
|
||||
|
||||
enum wlr_output_state_field {
|
||||
WLR_OUTPUT_STATE_BUFFER = 1 << 0,
|
||||
WLR_OUTPUT_STATE_DAMAGE = 1 << 1,
|
||||
|
|
@ -138,8 +116,6 @@ struct wlr_output {
|
|||
|
||||
int attach_render_locks; // number of locks forcing rendering
|
||||
|
||||
struct wl_list cursors; // wlr_output_cursor::link
|
||||
struct wlr_output_cursor *hardware_cursor;
|
||||
int software_cursor_locks; // number of locks forcing software cursors
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
|
|
@ -303,27 +279,14 @@ void wlr_output_lock_attach_render(struct wlr_output *output, bool lock);
|
|||
* a lock.
|
||||
*/
|
||||
void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock);
|
||||
/**
|
||||
* Renders software cursors. This is a utility function that can be called when
|
||||
* compositors render.
|
||||
*/
|
||||
void wlr_output_render_software_cursors(struct wlr_output *output,
|
||||
pixman_region32_t *damage);
|
||||
|
||||
|
||||
struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output);
|
||||
/**
|
||||
* Sets the cursor image. The image must be already scaled for the output.
|
||||
*/
|
||||
#if 0
|
||||
bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
|
||||
const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height,
|
||||
int32_t hotspot_x, int32_t hotspot_y);
|
||||
void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
|
||||
struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y);
|
||||
bool wlr_output_cursor_move(struct wlr_output_cursor *cursor,
|
||||
double x, double y);
|
||||
void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the transform that, when composed with `tr`, gives
|
||||
|
|
|
|||
|
|
@ -57,13 +57,4 @@ int wlr_xcursor_manager_load(struct wlr_xcursor_manager *manager,
|
|||
struct wlr_xcursor *wlr_xcursor_manager_get_xcursor(
|
||||
struct wlr_xcursor_manager *manager, const char *name, float scale);
|
||||
|
||||
/**
|
||||
* Set a wlr_cursor's cursor image to the specified cursor name for all scale
|
||||
* factors. wlr_cursor will take over from this point and ensure the correct
|
||||
* cursor is used on each output, assuming a wlr_output_layout is attached to
|
||||
* it.
|
||||
*/
|
||||
void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager,
|
||||
const char *name, struct wlr_cursor *cursor);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -42,23 +42,13 @@ struct wlr_cursor_device {
|
|||
struct wl_listener destroy;
|
||||
};
|
||||
|
||||
struct wlr_cursor_output_cursor {
|
||||
struct wlr_cursor *cursor;
|
||||
struct wlr_output_cursor *output_cursor;
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_listener layout_output_destroy;
|
||||
};
|
||||
|
||||
struct wlr_cursor_state {
|
||||
struct wlr_cursor *cursor;
|
||||
struct wl_list devices; // wlr_cursor_device::link
|
||||
struct wl_list output_cursors; // wlr_cursor_output_cursor::link
|
||||
struct wlr_output_layout *layout;
|
||||
struct wlr_output *mapped_output;
|
||||
struct wlr_box *mapped_box;
|
||||
|
||||
struct wl_listener layout_add;
|
||||
struct wl_listener layout_change;
|
||||
struct wl_listener layout_destroy;
|
||||
};
|
||||
|
|
@ -81,7 +71,6 @@ struct wlr_cursor *wlr_cursor_create(void) {
|
|||
cur->state->mapped_output = NULL;
|
||||
|
||||
wl_list_init(&cur->state->devices);
|
||||
wl_list_init(&cur->state->output_cursors);
|
||||
|
||||
// pointer signals
|
||||
wl_signal_init(&cur->events.motion);
|
||||
|
|
@ -114,28 +103,13 @@ struct wlr_cursor *wlr_cursor_create(void) {
|
|||
return cur;
|
||||
}
|
||||
|
||||
static void output_cursor_destroy(
|
||||
struct wlr_cursor_output_cursor *output_cursor) {
|
||||
wl_list_remove(&output_cursor->layout_output_destroy.link);
|
||||
wl_list_remove(&output_cursor->link);
|
||||
wlr_output_cursor_destroy(output_cursor->output_cursor);
|
||||
free(output_cursor);
|
||||
}
|
||||
|
||||
static void cursor_detach_output_layout(struct wlr_cursor *cur) {
|
||||
if (!cur->state->layout) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_cursor_output_cursor *output_cursor, *tmp;
|
||||
wl_list_for_each_safe(output_cursor, tmp, &cur->state->output_cursors,
|
||||
link) {
|
||||
output_cursor_destroy(output_cursor);
|
||||
}
|
||||
|
||||
wl_list_remove(&cur->state->layout_destroy.link);
|
||||
wl_list_remove(&cur->state->layout_change.link);
|
||||
wl_list_remove(&cur->state->layout_add.link);
|
||||
|
||||
cur->state->layout = NULL;
|
||||
}
|
||||
|
|
@ -200,15 +174,6 @@ static void cursor_warp_unchecked(struct wlr_cursor *cur,
|
|||
double lx, double ly) {
|
||||
assert(cur->state->layout);
|
||||
|
||||
struct wlr_cursor_output_cursor *output_cursor;
|
||||
wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
|
||||
double output_x = lx, output_y = ly;
|
||||
wlr_output_layout_output_coords(cur->state->layout,
|
||||
output_cursor->output_cursor->output, &output_x, &output_y);
|
||||
wlr_output_cursor_move(output_cursor->output_cursor,
|
||||
output_x, output_y);
|
||||
}
|
||||
|
||||
cur->x = lx;
|
||||
cur->y = ly;
|
||||
}
|
||||
|
|
@ -320,30 +285,6 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev,
|
|||
wlr_cursor_warp_closest(cur, dev, lx, ly);
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
if (scale > 0 && output_scale != scale) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wlr_output_cursor_set_image(output_cursor->output_cursor, pixels,
|
||||
stride, width, height, hotspot_x, hotspot_y);
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_cursor_set_surface(struct wlr_cursor *cur, struct wlr_surface *surface,
|
||||
int32_t hotspot_x, int32_t hotspot_y) {
|
||||
struct wlr_cursor_output_cursor *output_cursor;
|
||||
wl_list_for_each(output_cursor, &cur->state->output_cursors, link) {
|
||||
wlr_output_cursor_set_surface(output_cursor->output_cursor, surface,
|
||||
hotspot_x, hotspot_y);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pointer_motion(struct wl_listener *listener, void *data) {
|
||||
struct wlr_event_pointer_motion *event = data;
|
||||
struct wlr_cursor_device *device =
|
||||
|
|
@ -693,51 +634,6 @@ static void handle_layout_destroy(struct wl_listener *listener, void *data) {
|
|||
cursor_detach_output_layout(state->cursor);
|
||||
}
|
||||
|
||||
static void handle_layout_output_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_cursor_output_cursor *output_cursor =
|
||||
wl_container_of(listener, output_cursor, layout_output_destroy);
|
||||
//struct wlr_output_layout_output *l_output = data;
|
||||
output_cursor_destroy(output_cursor);
|
||||
}
|
||||
|
||||
static void layout_add(struct wlr_cursor_state *state,
|
||||
struct wlr_output_layout_output *l_output) {
|
||||
struct wlr_cursor_output_cursor *output_cursor;
|
||||
wl_list_for_each(output_cursor, &state->output_cursors, link) {
|
||||
if (output_cursor->output_cursor->output == l_output->output) {
|
||||
return; // already added
|
||||
}
|
||||
}
|
||||
|
||||
output_cursor = calloc(1, sizeof(struct wlr_cursor_output_cursor));
|
||||
if (output_cursor == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to allocate wlr_cursor_output_cursor");
|
||||
return;
|
||||
}
|
||||
output_cursor->cursor = state->cursor;
|
||||
|
||||
output_cursor->output_cursor = wlr_output_cursor_create(l_output->output);
|
||||
if (output_cursor->output_cursor == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create wlr_output_cursor");
|
||||
free(output_cursor);
|
||||
return;
|
||||
}
|
||||
|
||||
output_cursor->layout_output_destroy.notify = handle_layout_output_destroy;
|
||||
wl_signal_add(&l_output->events.destroy,
|
||||
&output_cursor->layout_output_destroy);
|
||||
|
||||
wl_list_insert(&state->output_cursors, &output_cursor->link);
|
||||
}
|
||||
|
||||
static void handle_layout_add(struct wl_listener *listener, void *data) {
|
||||
struct wlr_cursor_state *state =
|
||||
wl_container_of(listener, state, layout_add);
|
||||
struct wlr_output_layout_output *l_output = data;
|
||||
layout_add(state, l_output);
|
||||
}
|
||||
|
||||
static void handle_layout_change(struct wl_listener *listener, void *data) {
|
||||
struct wlr_cursor_state *state =
|
||||
wl_container_of(listener, state, layout_change);
|
||||
|
|
@ -763,19 +659,12 @@ void wlr_cursor_attach_output_layout(struct wlr_cursor *cur,
|
|||
return;
|
||||
}
|
||||
|
||||
wl_signal_add(&l->events.add, &cur->state->layout_add);
|
||||
cur->state->layout_add.notify = handle_layout_add;
|
||||
wl_signal_add(&l->events.change, &cur->state->layout_change);
|
||||
cur->state->layout_change.notify = handle_layout_change;
|
||||
wl_signal_add(&l->events.destroy, &cur->state->layout_destroy);
|
||||
cur->state->layout_destroy.notify = handle_layout_destroy;
|
||||
|
||||
cur->state->layout = l;
|
||||
|
||||
struct wlr_output_layout_output *l_output;
|
||||
wl_list_for_each(l_output, &l->outputs, link) {
|
||||
layout_add(cur->state, l_output);
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_cursor_map_to_output(struct wlr_cursor *cur,
|
||||
|
|
|
|||
|
|
@ -311,7 +311,6 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
|
|||
wl_list_init(&output->modes);
|
||||
output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
output->scale = 1;
|
||||
wl_list_init(&output->cursors);
|
||||
wl_list_init(&output->resources);
|
||||
wl_signal_init(&output->events.frame);
|
||||
wl_signal_init(&output->events.needs_frame);
|
||||
|
|
@ -351,11 +350,6 @@ void wlr_output_destroy(struct wlr_output *output) {
|
|||
|
||||
// The backend is responsible for free-ing the list of modes
|
||||
|
||||
struct wlr_output_cursor *cursor, *tmp_cursor;
|
||||
wl_list_for_each_safe(cursor, tmp_cursor, &output->cursors, link) {
|
||||
wlr_output_cursor_destroy(cursor);
|
||||
}
|
||||
|
||||
if (output->idle_frame != NULL) {
|
||||
wl_event_source_remove(output->idle_frame);
|
||||
}
|
||||
|
|
@ -486,14 +480,6 @@ bool wlr_output_commit(struct wlr_output *output) {
|
|||
return false;
|
||||
}
|
||||
|
||||
struct wlr_output_cursor *cursor;
|
||||
wl_list_for_each(cursor, &output->cursors, link) {
|
||||
if (!cursor->enabled || !cursor->visible || cursor->surface == NULL) {
|
||||
continue;
|
||||
}
|
||||
wlr_surface_send_frame_done(cursor->surface, &now);
|
||||
}
|
||||
|
||||
wlr_signal_emit_safe(&output->events.commit, output);
|
||||
|
||||
output->frame_pending = true;
|
||||
|
|
@ -512,16 +498,6 @@ bool wlr_output_attach_buffer(struct wlr_output *output,
|
|||
return false;
|
||||
}
|
||||
|
||||
// If the output has at least one software cursor, refuse to attach the
|
||||
// buffer
|
||||
struct wlr_output_cursor *cursor;
|
||||
wl_list_for_each(cursor, &output->cursors, link) {
|
||||
if (cursor->enabled && cursor->visible &&
|
||||
cursor != output->hardware_cursor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!output->impl->attach_buffer(output, buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -640,8 +616,6 @@ void wlr_output_lock_attach_render(struct wlr_output *output, bool lock) {
|
|||
output->attach_render_locks);
|
||||
}
|
||||
|
||||
static void output_cursor_damage_whole(struct wlr_output_cursor *cursor);
|
||||
|
||||
void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock) {
|
||||
if (lock) {
|
||||
++output->software_cursor_locks;
|
||||
|
|
@ -652,200 +626,9 @@ void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock) {
|
|||
wlr_log(WLR_DEBUG, "%s hardware cursors on output '%s' (locks: %d)",
|
||||
lock ? "Disabling" : "Enabling", output->name,
|
||||
output->software_cursor_locks);
|
||||
|
||||
if (output->software_cursor_locks > 0 && output->hardware_cursor != NULL) {
|
||||
assert(output->impl->set_cursor);
|
||||
output->impl->set_cursor(output, NULL, 1,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, true);
|
||||
output_cursor_damage_whole(output->hardware_cursor);
|
||||
output->hardware_cursor = NULL;
|
||||
}
|
||||
|
||||
// If it's possible to use hardware cursors again, don't switch immediately
|
||||
// since a recorder is likely to lock software cursors for the next frame
|
||||
// again.
|
||||
}
|
||||
|
||||
static void output_scissor(struct wlr_output *output, pixman_box32_t *rect) {
|
||||
struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend);
|
||||
assert(renderer);
|
||||
|
||||
struct wlr_box box = {
|
||||
.x = rect->x1,
|
||||
.y = rect->y1,
|
||||
.width = rect->x2 - rect->x1,
|
||||
.height = rect->y2 - rect->y1,
|
||||
};
|
||||
|
||||
int ow, oh;
|
||||
wlr_output_transformed_resolution(output, &ow, &oh);
|
||||
|
||||
enum wl_output_transform transform =
|
||||
wlr_output_transform_invert(output->transform);
|
||||
wlr_box_transform(&box, &box, transform, ow, oh);
|
||||
|
||||
wlr_renderer_scissor(renderer, &box);
|
||||
}
|
||||
|
||||
static void output_cursor_get_box(struct wlr_output_cursor *cursor,
|
||||
struct wlr_box *box);
|
||||
|
||||
static void output_cursor_render(struct wlr_output_cursor *cursor,
|
||||
pixman_region32_t *damage) {
|
||||
struct wlr_renderer *renderer =
|
||||
wlr_backend_get_renderer(cursor->output->backend);
|
||||
assert(renderer);
|
||||
|
||||
struct wlr_texture *texture = cursor->texture;
|
||||
if (cursor->surface != NULL) {
|
||||
texture = wlr_surface_get_texture(cursor->surface);
|
||||
}
|
||||
if (texture == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_box box;
|
||||
output_cursor_get_box(cursor, &box);
|
||||
|
||||
pixman_region32_t surface_damage;
|
||||
pixman_region32_init(&surface_damage);
|
||||
pixman_region32_union_rect(&surface_damage, &surface_damage, box.x, box.y,
|
||||
box.width, box.height);
|
||||
pixman_region32_intersect(&surface_damage, &surface_damage, damage);
|
||||
if (!pixman_region32_not_empty(&surface_damage)) {
|
||||
goto surface_damage_finish;
|
||||
}
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
|
||||
cursor->output->transform_matrix);
|
||||
|
||||
int nrects;
|
||||
pixman_box32_t *rects = pixman_region32_rectangles(&surface_damage, &nrects);
|
||||
for (int i = 0; i < nrects; ++i) {
|
||||
output_scissor(cursor->output, &rects[i]);
|
||||
wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0f);
|
||||
}
|
||||
wlr_renderer_scissor(renderer, NULL);
|
||||
|
||||
surface_damage_finish:
|
||||
pixman_region32_fini(&surface_damage);
|
||||
}
|
||||
|
||||
void wlr_output_render_software_cursors(struct wlr_output *output,
|
||||
pixman_region32_t *damage) {
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(output, &width, &height);
|
||||
|
||||
pixman_region32_t render_damage;
|
||||
pixman_region32_init(&render_damage);
|
||||
pixman_region32_union_rect(&render_damage, &render_damage, 0, 0,
|
||||
width, height);
|
||||
if (damage != NULL) {
|
||||
// Damage tracking supported
|
||||
pixman_region32_intersect(&render_damage, &render_damage, damage);
|
||||
}
|
||||
|
||||
if (pixman_region32_not_empty(&render_damage)) {
|
||||
struct wlr_output_cursor *cursor;
|
||||
wl_list_for_each(cursor, &output->cursors, link) {
|
||||
if (!cursor->enabled || !cursor->visible ||
|
||||
output->hardware_cursor == cursor) {
|
||||
continue;
|
||||
}
|
||||
output_cursor_render(cursor, &render_damage);
|
||||
}
|
||||
}
|
||||
|
||||
pixman_region32_fini(&render_damage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the cursor box, scaled for its output.
|
||||
*/
|
||||
static void output_cursor_get_box(struct wlr_output_cursor *cursor,
|
||||
struct wlr_box *box) {
|
||||
box->x = cursor->x - cursor->hotspot_x;
|
||||
box->y = cursor->y - cursor->hotspot_y;
|
||||
box->width = cursor->width;
|
||||
box->height = cursor->height;
|
||||
}
|
||||
|
||||
static void output_cursor_damage_whole(struct wlr_output_cursor *cursor) {
|
||||
struct wlr_box box;
|
||||
output_cursor_get_box(cursor, &box);
|
||||
pixman_region32_union_rect(&cursor->output->damage, &cursor->output->damage,
|
||||
box.x, box.y, box.width, box.height);
|
||||
wlr_output_update_needs_frame(cursor->output);
|
||||
}
|
||||
|
||||
static void output_cursor_reset(struct wlr_output_cursor *cursor) {
|
||||
if (cursor->output->hardware_cursor != cursor) {
|
||||
output_cursor_damage_whole(cursor);
|
||||
}
|
||||
if (cursor->surface != NULL) {
|
||||
wl_list_remove(&cursor->surface_commit.link);
|
||||
wl_list_remove(&cursor->surface_destroy.link);
|
||||
cursor->surface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void output_cursor_update_visible(struct wlr_output_cursor *cursor) {
|
||||
struct wlr_box output_box;
|
||||
output_box.x = output_box.y = 0;
|
||||
wlr_output_transformed_resolution(cursor->output, &output_box.width,
|
||||
&output_box.height);
|
||||
|
||||
struct wlr_box cursor_box;
|
||||
output_cursor_get_box(cursor, &cursor_box);
|
||||
|
||||
struct wlr_box intersection;
|
||||
bool visible =
|
||||
wlr_box_intersection(&intersection, &output_box, &cursor_box);
|
||||
|
||||
if (cursor->surface != NULL) {
|
||||
if (cursor->visible && !visible) {
|
||||
wlr_surface_send_leave(cursor->surface, cursor->output);
|
||||
}
|
||||
if (!cursor->visible && visible) {
|
||||
wlr_surface_send_enter(cursor->surface, cursor->output);
|
||||
}
|
||||
}
|
||||
|
||||
cursor->visible = visible;
|
||||
}
|
||||
|
||||
static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
|
||||
int32_t scale = cursor->output->scale;
|
||||
enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
struct wlr_texture *texture = cursor->texture;
|
||||
if (cursor->surface != NULL) {
|
||||
texture = wlr_surface_get_texture(cursor->surface);
|
||||
scale = cursor->surface->current.scale;
|
||||
transform = cursor->surface->current.transform;
|
||||
}
|
||||
|
||||
if (cursor->output->software_cursor_locks > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_output_cursor *hwcur = cursor->output->hardware_cursor;
|
||||
if (cursor->output->impl->set_cursor && (hwcur == NULL || hwcur == cursor)) {
|
||||
// If the cursor was hidden or was a software cursor, the hardware
|
||||
// cursor position is outdated
|
||||
assert(cursor->output->impl->move_cursor);
|
||||
cursor->output->impl->move_cursor(cursor->output,
|
||||
(int)cursor->x, (int)cursor->y);
|
||||
if (cursor->output->impl->set_cursor(cursor->output, texture,
|
||||
scale, transform, cursor->hotspot_x, cursor->hotspot_y, true)) {
|
||||
cursor->output->hardware_cursor = cursor;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
|
||||
const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height,
|
||||
int32_t hotspot_x, int32_t hotspot_y) {
|
||||
|
|
@ -887,163 +670,7 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
|
|||
output_cursor_damage_whole(cursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void output_cursor_commit(struct wlr_output_cursor *cursor,
|
||||
bool update_hotspot) {
|
||||
if (cursor->output->hardware_cursor != cursor) {
|
||||
output_cursor_damage_whole(cursor);
|
||||
}
|
||||
|
||||
struct wlr_surface *surface = cursor->surface;
|
||||
assert(surface != NULL);
|
||||
|
||||
// Some clients commit a cursor surface with a NULL buffer to hide it.
|
||||
cursor->enabled = wlr_surface_has_buffer(surface);
|
||||
cursor->width = surface->current.width * cursor->output->scale;
|
||||
cursor->height = surface->current.height * cursor->output->scale;
|
||||
output_cursor_update_visible(cursor);
|
||||
if (update_hotspot) {
|
||||
cursor->hotspot_x -= surface->current.dx * cursor->output->scale;
|
||||
cursor->hotspot_y -= surface->current.dy * cursor->output->scale;
|
||||
}
|
||||
|
||||
if (output_cursor_attempt_hardware(cursor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback to software cursor
|
||||
output_cursor_damage_whole(cursor);
|
||||
}
|
||||
|
||||
static void output_cursor_handle_commit(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_output_cursor *cursor =
|
||||
wl_container_of(listener, cursor, surface_commit);
|
||||
output_cursor_commit(cursor, true);
|
||||
}
|
||||
|
||||
static void output_cursor_handle_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_output_cursor *cursor = wl_container_of(listener, cursor,
|
||||
surface_destroy);
|
||||
output_cursor_reset(cursor);
|
||||
}
|
||||
|
||||
void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
|
||||
struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y) {
|
||||
hotspot_x *= cursor->output->scale;
|
||||
hotspot_y *= cursor->output->scale;
|
||||
|
||||
if (surface && surface == cursor->surface) {
|
||||
// Only update the hotspot: surface hasn't changed
|
||||
|
||||
if (cursor->output->hardware_cursor != cursor) {
|
||||
output_cursor_damage_whole(cursor);
|
||||
}
|
||||
cursor->hotspot_x = hotspot_x;
|
||||
cursor->hotspot_y = hotspot_y;
|
||||
if (cursor->output->hardware_cursor != cursor) {
|
||||
output_cursor_damage_whole(cursor);
|
||||
} else {
|
||||
assert(cursor->output->impl->set_cursor);
|
||||
cursor->output->impl->set_cursor(cursor->output, NULL,
|
||||
1, WL_OUTPUT_TRANSFORM_NORMAL, hotspot_x, hotspot_y, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
output_cursor_reset(cursor);
|
||||
|
||||
cursor->surface = surface;
|
||||
cursor->hotspot_x = hotspot_x;
|
||||
cursor->hotspot_y = hotspot_y;
|
||||
|
||||
if (surface != NULL) {
|
||||
wl_signal_add(&surface->events.commit, &cursor->surface_commit);
|
||||
wl_signal_add(&surface->events.destroy, &cursor->surface_destroy);
|
||||
|
||||
cursor->visible = false;
|
||||
output_cursor_commit(cursor, false);
|
||||
} else {
|
||||
cursor->enabled = false;
|
||||
cursor->width = 0;
|
||||
cursor->height = 0;
|
||||
|
||||
if (cursor->output->hardware_cursor == cursor) {
|
||||
assert(cursor->output->impl->set_cursor);
|
||||
cursor->output->impl->set_cursor(cursor->output, NULL, 1,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool wlr_output_cursor_move(struct wlr_output_cursor *cursor,
|
||||
double x, double y) {
|
||||
if (cursor->x == x && cursor->y == y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cursor->output->hardware_cursor != cursor) {
|
||||
output_cursor_damage_whole(cursor);
|
||||
}
|
||||
|
||||
bool was_visible = cursor->visible;
|
||||
x *= cursor->output->scale;
|
||||
y *= cursor->output->scale;
|
||||
cursor->x = x;
|
||||
cursor->y = y;
|
||||
output_cursor_update_visible(cursor);
|
||||
|
||||
if (!was_visible && !cursor->visible) {
|
||||
// Cursor is still hidden, do nothing
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cursor->output->hardware_cursor != cursor) {
|
||||
output_cursor_damage_whole(cursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(cursor->output->impl->move_cursor);
|
||||
return cursor->output->impl->move_cursor(cursor->output, (int)x, (int)y);
|
||||
}
|
||||
|
||||
struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output) {
|
||||
struct wlr_output_cursor *cursor =
|
||||
calloc(1, sizeof(struct wlr_output_cursor));
|
||||
if (cursor == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cursor->output = output;
|
||||
wl_signal_init(&cursor->events.destroy);
|
||||
wl_list_init(&cursor->surface_commit.link);
|
||||
cursor->surface_commit.notify = output_cursor_handle_commit;
|
||||
wl_list_init(&cursor->surface_destroy.link);
|
||||
cursor->surface_destroy.notify = output_cursor_handle_destroy;
|
||||
wl_list_insert(&output->cursors, &cursor->link);
|
||||
cursor->visible = true; // default position is at (0, 0)
|
||||
return cursor;
|
||||
}
|
||||
|
||||
void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
|
||||
if (cursor == NULL) {
|
||||
return;
|
||||
}
|
||||
output_cursor_reset(cursor);
|
||||
wlr_signal_emit_safe(&cursor->events.destroy, cursor);
|
||||
if (cursor->output->hardware_cursor == cursor) {
|
||||
// If this cursor was the hardware cursor, disable it
|
||||
if (cursor->output->impl->set_cursor) {
|
||||
cursor->output->impl->set_cursor(cursor->output, NULL, 1,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, true);
|
||||
}
|
||||
cursor->output->hardware_cursor = NULL;
|
||||
}
|
||||
wlr_texture_destroy(cursor->texture);
|
||||
wl_list_remove(&cursor->link);
|
||||
free(cursor);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
enum wl_output_transform wlr_output_transform_invert(
|
||||
enum wl_output_transform tr) {
|
||||
|
|
|
|||
|
|
@ -65,20 +65,3 @@ struct wlr_xcursor *wlr_xcursor_manager_get_xcursor(
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager,
|
||||
const char *name, struct wlr_cursor *cursor) {
|
||||
struct wlr_xcursor_manager_theme *theme;
|
||||
wl_list_for_each(theme, &manager->scaled_themes, link) {
|
||||
struct wlr_xcursor *xcursor =
|
||||
wlr_xcursor_theme_get_cursor(theme->theme, name);
|
||||
if (xcursor == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_xcursor_image *image = xcursor->images[0];
|
||||
wlr_cursor_set_image(cursor, image->buffer, image->width * 4,
|
||||
image->width, image->height, image->hotspot_x, image->hotspot_y,
|
||||
theme->scale);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue