mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 21:05:58 +01:00
Merge pull request #965 from emersion/fix-hardware-cursor-scale-transform
Fix hardware cursors scale & transform
This commit is contained in:
commit
f520dd8fac
5 changed files with 49 additions and 19 deletions
|
@ -538,7 +538,8 @@ static void drm_connector_transform(struct wlr_output *output,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool drm_connector_set_cursor(struct wlr_output *output,
|
static bool drm_connector_set_cursor(struct wlr_output *output,
|
||||||
struct wlr_texture *texture, int32_t hotspot_x, int32_t hotspot_y,
|
struct wlr_texture *texture, int32_t scale,
|
||||||
|
enum wl_output_transform transform, int32_t hotspot_x, int32_t hotspot_y,
|
||||||
bool update_texture) {
|
bool update_texture) {
|
||||||
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
|
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
|
||||||
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
|
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
|
||||||
|
@ -581,15 +582,12 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum wl_output_transform transform = output->transform;
|
|
||||||
wlr_matrix_projection(plane->matrix, plane->surf.width,
|
wlr_matrix_projection(plane->matrix, plane->surf.width,
|
||||||
plane->surf.height, transform);
|
plane->surf.height, output->transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y };
|
struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y };
|
||||||
enum wl_output_transform transform =
|
wlr_box_transform(&hotspot, wlr_output_transform_invert(output->transform),
|
||||||
wlr_output_transform_invert(output->transform);
|
|
||||||
wlr_box_transform(&hotspot, transform,
|
|
||||||
plane->surf.width, plane->surf.height, &hotspot);
|
plane->surf.width, plane->surf.height, &hotspot);
|
||||||
|
|
||||||
if (plane->cursor_hotspot_x != hotspot.x ||
|
if (plane->cursor_hotspot_x != hotspot.x ||
|
||||||
|
@ -617,6 +615,8 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
|
||||||
if (texture != NULL) {
|
if (texture != NULL) {
|
||||||
int width, height;
|
int width, height;
|
||||||
wlr_texture_get_size(texture, &width, &height);
|
wlr_texture_get_size(texture, &width, &height);
|
||||||
|
width = width * output->scale / scale;
|
||||||
|
height = height * output->scale / scale;
|
||||||
|
|
||||||
if (width > (int)plane->surf.width || height > (int)plane->surf.height) {
|
if (width > (int)plane->surf.width || height > (int)plane->surf.height) {
|
||||||
wlr_log(L_ERROR, "Cursor too large (max %dx%d)",
|
wlr_log(L_ERROR, "Cursor too large (max %dx%d)",
|
||||||
|
@ -639,9 +639,14 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
|
||||||
|
|
||||||
struct wlr_renderer *rend = plane->surf.renderer->wlr_rend;
|
struct wlr_renderer *rend = plane->surf.renderer->wlr_rend;
|
||||||
|
|
||||||
|
struct wlr_box cursor_box = { .width = width, .height = height };
|
||||||
|
|
||||||
|
float matrix[9];
|
||||||
|
wlr_matrix_project_box(matrix, &cursor_box, transform, 0, plane->matrix);
|
||||||
|
|
||||||
wlr_renderer_begin(rend, plane->surf.width, plane->surf.height);
|
wlr_renderer_begin(rend, plane->surf.width, plane->surf.height);
|
||||||
wlr_renderer_clear(rend, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
wlr_renderer_clear(rend, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
||||||
wlr_render_texture(rend, texture, plane->matrix, 0, 0, 1.0f);
|
wlr_render_texture_with_matrix(rend, texture, matrix, 1.0);
|
||||||
wlr_renderer_end(rend);
|
wlr_renderer_end(rend);
|
||||||
|
|
||||||
wlr_renderer_read_pixels(rend, WL_SHM_FORMAT_ARGB8888, bo_stride,
|
wlr_renderer_read_pixels(rend, WL_SHM_FORMAT_ARGB8888, bo_stride,
|
||||||
|
|
|
@ -72,16 +72,20 @@ static void output_transform(struct wlr_output *_output,
|
||||||
output->wlr_output.transform = transform;
|
output->wlr_output.transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool output_set_cursor(struct wlr_output *_output,
|
static bool output_set_cursor(struct wlr_output *wlr_output,
|
||||||
struct wlr_texture *texture, int32_t hotspot_x, int32_t hotspot_y,
|
struct wlr_texture *texture, int32_t scale,
|
||||||
|
enum wl_output_transform transform, int32_t hotspot_x, int32_t hotspot_y,
|
||||||
bool update_texture) {
|
bool update_texture) {
|
||||||
struct wlr_wl_output *output =
|
struct wlr_wl_output *output = (struct wlr_wl_output *)wlr_output;
|
||||||
(struct wlr_wl_output *)_output;
|
|
||||||
struct wlr_wl_backend *backend = output->backend;
|
struct wlr_wl_backend *backend = output->backend;
|
||||||
|
|
||||||
|
struct wlr_box hotspot = { .x = hotspot_x, .y = hotspot_y };
|
||||||
|
wlr_box_transform(&hotspot, wlr_output_transform_invert(wlr_output->transform),
|
||||||
|
output->cursor.width, output->cursor.height, &hotspot);
|
||||||
|
|
||||||
// TODO: use output->wlr_output.transform to transform pixels and hotpot
|
// TODO: use output->wlr_output.transform to transform pixels and hotpot
|
||||||
output->cursor.hotspot_x = hotspot_x;
|
output->cursor.hotspot_x = hotspot.x;
|
||||||
output->cursor.hotspot_y = hotspot_y;
|
output->cursor.hotspot_y = hotspot.y;
|
||||||
|
|
||||||
if (!update_texture) {
|
if (!update_texture) {
|
||||||
// Update hotspot without changing cursor image
|
// Update hotspot without changing cursor image
|
||||||
|
@ -98,6 +102,11 @@ static bool output_set_cursor(struct wlr_output *_output,
|
||||||
if (texture != NULL) {
|
if (texture != NULL) {
|
||||||
int width, height;
|
int width, height;
|
||||||
wlr_texture_get_size(texture, &width, &height);
|
wlr_texture_get_size(texture, &width, &height);
|
||||||
|
width = width * wlr_output->scale / scale;
|
||||||
|
height = height * wlr_output->scale / scale;
|
||||||
|
|
||||||
|
output->cursor.width = width;
|
||||||
|
output->cursor.height = height;
|
||||||
|
|
||||||
if (output->cursor.egl_window == NULL) {
|
if (output->cursor.egl_window == NULL) {
|
||||||
output->cursor.egl_window =
|
output->cursor.egl_window =
|
||||||
|
@ -110,12 +119,20 @@ static bool output_set_cursor(struct wlr_output *_output,
|
||||||
|
|
||||||
wlr_egl_make_current(&backend->egl, egl_surface, NULL);
|
wlr_egl_make_current(&backend->egl, egl_surface, NULL);
|
||||||
|
|
||||||
|
struct wlr_box cursor_box = {
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
|
float projection[9];
|
||||||
|
wlr_matrix_projection(projection, width, height, wlr_output->transform);
|
||||||
|
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
wlr_matrix_projection(matrix, width, height, WL_OUTPUT_TRANSFORM_NORMAL);
|
wlr_matrix_project_box(matrix, &cursor_box, transform, 0, projection);
|
||||||
|
|
||||||
wlr_renderer_begin(backend->renderer, width, height);
|
wlr_renderer_begin(backend->renderer, width, height);
|
||||||
wlr_renderer_clear(backend->renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
wlr_renderer_clear(backend->renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
|
||||||
wlr_render_texture(backend->renderer, texture, matrix, 0, 0, 1.0);
|
wlr_render_texture_with_matrix(backend->renderer, texture, matrix, 1.0);
|
||||||
wlr_renderer_end(backend->renderer);
|
wlr_renderer_end(backend->renderer);
|
||||||
|
|
||||||
wlr_egl_swap_buffers(&backend->egl, egl_surface, NULL);
|
wlr_egl_swap_buffers(&backend->egl, egl_surface, NULL);
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct wlr_wl_output {
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
struct wl_egl_window *egl_window;
|
struct wl_egl_window *egl_window;
|
||||||
int32_t hotspot_x, hotspot_y;
|
int32_t hotspot_x, hotspot_y;
|
||||||
|
int32_t width, height;
|
||||||
} cursor;
|
} cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ struct wlr_output_impl {
|
||||||
void (*transform)(struct wlr_output *output,
|
void (*transform)(struct wlr_output *output,
|
||||||
enum wl_output_transform transform);
|
enum wl_output_transform transform);
|
||||||
bool (*set_cursor)(struct wlr_output *output, struct wlr_texture *texture,
|
bool (*set_cursor)(struct wlr_output *output, struct wlr_texture *texture,
|
||||||
|
int32_t scale, enum wl_output_transform transform,
|
||||||
int32_t hotspot_x, int32_t hotspot_y, bool update_texture);
|
int32_t hotspot_x, int32_t hotspot_y, bool update_texture);
|
||||||
bool (*move_cursor)(struct wlr_output *output, int x, int y);
|
bool (*move_cursor)(struct wlr_output *output, int x, int y);
|
||||||
void (*destroy)(struct wlr_output *output);
|
void (*destroy)(struct wlr_output *output);
|
||||||
|
|
|
@ -695,9 +695,13 @@ static void output_cursor_update_visible(struct wlr_output_cursor *cursor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
|
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;
|
struct wlr_texture *texture = cursor->texture;
|
||||||
if (cursor->surface != NULL) {
|
if (cursor->surface != NULL) {
|
||||||
texture = cursor->surface->texture;
|
texture = cursor->surface->texture;
|
||||||
|
scale = cursor->surface->current->scale;
|
||||||
|
transform = cursor->surface->current->transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_output_cursor *hwcur = cursor->output->hardware_cursor;
|
struct wlr_output_cursor *hwcur = cursor->output->hardware_cursor;
|
||||||
|
@ -708,7 +712,7 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
|
||||||
(int)cursor->x, (int)cursor->y);
|
(int)cursor->x, (int)cursor->y);
|
||||||
}
|
}
|
||||||
if (cursor->output->impl->set_cursor(cursor->output, texture,
|
if (cursor->output->impl->set_cursor(cursor->output, texture,
|
||||||
cursor->hotspot_x, cursor->hotspot_y, true)) {
|
scale, transform, cursor->hotspot_x, cursor->hotspot_y, true)) {
|
||||||
cursor->output->hardware_cursor = cursor;
|
cursor->output->hardware_cursor = cursor;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -810,7 +814,7 @@ void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
|
||||||
} else {
|
} else {
|
||||||
assert(cursor->output->impl->set_cursor);
|
assert(cursor->output->impl->set_cursor);
|
||||||
cursor->output->impl->set_cursor(cursor->output, NULL,
|
cursor->output->impl->set_cursor(cursor->output, NULL,
|
||||||
hotspot_x, hotspot_y, false);
|
1, WL_OUTPUT_TRANSFORM_NORMAL, hotspot_x, hotspot_y, false);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -835,7 +839,8 @@ void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
|
||||||
|
|
||||||
if (cursor->output->hardware_cursor == cursor) {
|
if (cursor->output->hardware_cursor == cursor) {
|
||||||
assert(cursor->output->impl->set_cursor);
|
assert(cursor->output->impl->set_cursor);
|
||||||
cursor->output->impl->set_cursor(cursor->output, NULL, 0, 0, true);
|
cursor->output->impl->set_cursor(cursor->output, NULL, 1,
|
||||||
|
WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -897,7 +902,8 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
|
||||||
if (cursor->output->hardware_cursor == cursor) {
|
if (cursor->output->hardware_cursor == cursor) {
|
||||||
// If this cursor was the hardware cursor, disable it
|
// If this cursor was the hardware cursor, disable it
|
||||||
if (cursor->output->impl->set_cursor) {
|
if (cursor->output->impl->set_cursor) {
|
||||||
cursor->output->impl->set_cursor(cursor->output, NULL, 0, 0, true);
|
cursor->output->impl->set_cursor(cursor->output, NULL, 1,
|
||||||
|
WL_OUTPUT_TRANSFORM_NORMAL, 0, 0, true);
|
||||||
}
|
}
|
||||||
cursor->output->hardware_cursor = NULL;
|
cursor->output->hardware_cursor = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue