mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-26 06:35:58 +01:00
Merge pull request #257 from emersion/fix-client-cursors
[WIP] Fix client cursors
This commit is contained in:
commit
62371a9974
7 changed files with 82 additions and 31 deletions
|
@ -470,7 +470,7 @@ static void wlr_drm_connector_transform(struct wlr_output *output,
|
||||||
|
|
||||||
static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
|
static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
|
||||||
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height,
|
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height,
|
||||||
int32_t hotspot_x, int32_t hotspot_y) {
|
int32_t hotspot_x, int32_t hotspot_y, bool update_pixels) {
|
||||||
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 = conn->drm;
|
struct wlr_drm_backend *drm = conn->drm;
|
||||||
struct wlr_drm_renderer *renderer = &drm->renderer;
|
struct wlr_drm_renderer *renderer = &drm->renderer;
|
||||||
|
@ -478,7 +478,8 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
|
||||||
struct wlr_drm_crtc *crtc = conn->crtc;
|
struct wlr_drm_crtc *crtc = conn->crtc;
|
||||||
struct wlr_drm_plane *plane = crtc->cursor;
|
struct wlr_drm_plane *plane = crtc->cursor;
|
||||||
|
|
||||||
if (!buf) {
|
if (!buf && update_pixels) {
|
||||||
|
// Hide the cursor
|
||||||
return drm->iface->crtc_set_cursor(drm, crtc, NULL);
|
return drm->iface->crtc_set_cursor(drm, crtc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,6 +567,11 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!update_pixels) {
|
||||||
|
// Only update the cursor hotspot
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
struct gbm_bo *bo = plane->cursor_bo;
|
struct gbm_bo *bo = plane->cursor_bo;
|
||||||
uint32_t bo_width = gbm_bo_get_width(bo);
|
uint32_t bo_width = gbm_bo_get_width(bo);
|
||||||
uint32_t bo_height = gbm_bo_get_height(bo);
|
uint32_t bo_height = gbm_bo_get_height(bo);
|
||||||
|
|
|
@ -54,13 +54,24 @@ static void wlr_wl_output_transform(struct wlr_output *_output,
|
||||||
|
|
||||||
static bool wlr_wl_output_set_cursor(struct wlr_output *_output,
|
static bool wlr_wl_output_set_cursor(struct wlr_output *_output,
|
||||||
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height,
|
const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height,
|
||||||
int32_t hotspot_x, int32_t hotspot_y) {
|
int32_t hotspot_x, int32_t hotspot_y, bool update_pixels) {
|
||||||
struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output;
|
struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output;
|
||||||
struct wlr_wl_backend *backend = output->backend;
|
struct wlr_wl_backend *backend = output->backend;
|
||||||
|
|
||||||
|
if (!update_pixels) {
|
||||||
|
// Update hotspot without changing cursor image
|
||||||
|
wlr_wl_output_update_cursor(output, output->enter_serial, hotspot_x,
|
||||||
|
hotspot_y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
wl_pointer_set_cursor(output->backend->pointer, output->enter_serial,
|
// Hide cursor
|
||||||
NULL, 0, 0);
|
wl_surface_destroy(output->cursor_surface);
|
||||||
|
munmap(output->cursor_data, output->cursor_buf_size);
|
||||||
|
output->cursor_surface = NULL;
|
||||||
|
output->cursor_buf_size = 0;
|
||||||
|
wlr_wl_output_update_cursor(output, output->enter_serial, hotspot_x,
|
||||||
|
hotspot_y);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +164,7 @@ static void wlr_wl_output_destroy(struct wlr_output *_output) {
|
||||||
|
|
||||||
void wlr_wl_output_update_cursor(struct wlr_wl_backend_output *output,
|
void wlr_wl_output_update_cursor(struct wlr_wl_backend_output *output,
|
||||||
uint32_t serial, int32_t hotspot_x, int32_t hotspot_y) {
|
uint32_t serial, int32_t hotspot_x, int32_t hotspot_y) {
|
||||||
if (output->cursor_surface && output->backend->pointer && serial) {
|
if (output->backend->pointer && serial) {
|
||||||
wl_pointer_set_cursor(output->backend->pointer, serial,
|
wl_pointer_set_cursor(output->backend->pointer, serial,
|
||||||
output->cursor_surface, hotspot_x, hotspot_y);
|
output->cursor_surface, hotspot_x, hotspot_y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ struct roots_input {
|
||||||
struct wlr_xcursor_theme *theme;
|
struct wlr_xcursor_theme *theme;
|
||||||
struct wlr_xcursor *xcursor;
|
struct wlr_xcursor *xcursor;
|
||||||
struct wlr_seat *wl_seat;
|
struct wlr_seat *wl_seat;
|
||||||
struct roots_view *client_cursor_view;
|
struct wl_client *cursor_client;
|
||||||
|
|
||||||
enum roots_cursor_mode mode;
|
enum roots_cursor_mode mode;
|
||||||
struct roots_view *active_view, *last_active_view;
|
struct roots_view *active_view, *last_active_view;
|
||||||
|
|
|
@ -8,16 +8,16 @@ struct wlr_output_impl {
|
||||||
void (*enable)(struct wlr_output *output, bool enable);
|
void (*enable)(struct wlr_output *output, bool enable);
|
||||||
bool (*set_mode)(struct wlr_output *output, struct wlr_output_mode *mode);
|
bool (*set_mode)(struct wlr_output *output, struct wlr_output_mode *mode);
|
||||||
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, const uint8_t *buf,
|
bool (*set_cursor)(struct wlr_output *output, const uint8_t *buf,
|
||||||
int32_t stride, uint32_t width, uint32_t height,
|
int32_t stride, uint32_t width, uint32_t height,
|
||||||
int32_t hotspot_x, int32_t hotspot_y);
|
int32_t hotspot_x, int32_t hotspot_y, bool update_pixels);
|
||||||
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);
|
||||||
void (*make_current)(struct wlr_output *output);
|
void (*make_current)(struct wlr_output *output);
|
||||||
void (*swap_buffers)(struct wlr_output *output);
|
void (*swap_buffers)(struct wlr_output *output);
|
||||||
void (*set_gamma)(struct wlr_output *output,
|
void (*set_gamma)(struct wlr_output *output,
|
||||||
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
|
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
|
||||||
uint16_t (*get_gamma_size)(struct wlr_output *output);
|
uint16_t (*get_gamma_size)(struct wlr_output *output);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +25,6 @@ void wlr_output_init(struct wlr_output *output, const struct wlr_output_impl *im
|
||||||
void wlr_output_free(struct wlr_output *output);
|
void wlr_output_free(struct wlr_output *output);
|
||||||
void wlr_output_update_matrix(struct wlr_output *output);
|
void wlr_output_update_matrix(struct wlr_output *output);
|
||||||
struct wl_global *wlr_output_create_global(
|
struct wl_global *wlr_output_create_global(
|
||||||
struct wlr_output *wlr_output, struct wl_display *display);
|
struct wlr_output *wlr_output, struct wl_display *display);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -83,10 +83,16 @@ void cursor_update_position(struct roots_input *input, uint32_t time) {
|
||||||
case ROOTS_CURSOR_PASSTHROUGH:
|
case ROOTS_CURSOR_PASSTHROUGH:
|
||||||
view = view_at(desktop, input->cursor->x, input->cursor->y, &surface,
|
view = view_at(desktop, input->cursor->x, input->cursor->y, &surface,
|
||||||
&sx, &sy);
|
&sx, &sy);
|
||||||
if (view != input->client_cursor_view) {
|
bool set_compositor_cursor = !view && input->cursor_client;
|
||||||
|
if (view) {
|
||||||
|
struct wl_client *view_client =
|
||||||
|
wl_resource_get_client(view->wlr_surface->resource);
|
||||||
|
set_compositor_cursor = view_client != input->cursor_client;
|
||||||
|
}
|
||||||
|
if (set_compositor_cursor) {
|
||||||
wlr_log(L_DEBUG, "Switching to compositor cursor");
|
wlr_log(L_DEBUG, "Switching to compositor cursor");
|
||||||
cursor_set_xcursor_image(input, input->xcursor->images[0]);
|
cursor_set_xcursor_image(input, input->xcursor->images[0]);
|
||||||
input->client_cursor_view = NULL;
|
input->cursor_client = NULL;
|
||||||
}
|
}
|
||||||
if (view) {
|
if (view) {
|
||||||
wlr_seat_pointer_notify_enter(input->wl_seat, surface, sx, sy);
|
wlr_seat_pointer_notify_enter(input->wl_seat, surface, sx, sy);
|
||||||
|
@ -301,18 +307,16 @@ static void handle_request_set_cursor(struct wl_listener *listener,
|
||||||
request_set_cursor);
|
request_set_cursor);
|
||||||
struct wlr_seat_pointer_request_set_cursor_event *event = data;
|
struct wlr_seat_pointer_request_set_cursor_event *event = data;
|
||||||
|
|
||||||
struct wlr_surface *focused_surface = NULL;
|
struct wlr_surface *focused_surface =
|
||||||
double sx, sy;
|
event->seat_handle->wlr_seat->pointer_state.focused_surface;
|
||||||
struct roots_view *focused_view = view_at(input->server->desktop,
|
bool ok = focused_surface != NULL && focused_surface->resource != NULL;
|
||||||
input->cursor->x, input->cursor->y, &focused_surface, &sx, &sy);
|
if (ok) {
|
||||||
bool ok = focused_surface != NULL;
|
|
||||||
if (focused_surface != NULL) {
|
|
||||||
struct wl_client *focused_client =
|
struct wl_client *focused_client =
|
||||||
wl_resource_get_client(focused_surface->resource);
|
wl_resource_get_client(focused_surface->resource);
|
||||||
ok = event->client == focused_client;
|
ok = event->client == focused_client;
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
wlr_log(L_DEBUG, "Denying request to set cursor outside view");
|
wlr_log(L_DEBUG, "Denying request to set cursor from unfocused client");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +328,7 @@ static void handle_request_set_cursor(struct wl_listener *listener,
|
||||||
event->hotspot_x, event->hotspot_y);
|
event->hotspot_x, event->hotspot_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
input->client_cursor_view = focused_view;
|
input->cursor_client = event->client;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cursor_initialize(struct roots_input *input) {
|
void cursor_initialize(struct roots_input *input) {
|
||||||
|
|
|
@ -127,7 +127,7 @@ static bool set_cursor(struct wlr_output *output, const uint8_t *buf,
|
||||||
int32_t hotspot_y) {
|
int32_t hotspot_y) {
|
||||||
if (output->impl->set_cursor
|
if (output->impl->set_cursor
|
||||||
&& output->impl->set_cursor(output, buf, stride, width, height,
|
&& output->impl->set_cursor(output, buf, stride, width, height,
|
||||||
hotspot_x, hotspot_y)) {
|
hotspot_x, hotspot_y, true)) {
|
||||||
output->cursor.is_sw = false;
|
output->cursor.is_sw = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -179,6 +179,10 @@ static inline int64_t timespec_to_msec(const struct timespec *a) {
|
||||||
|
|
||||||
static void commit_cursor_surface(struct wlr_output *output,
|
static void commit_cursor_surface(struct wlr_output *output,
|
||||||
struct wlr_surface *surface) {
|
struct wlr_surface *surface) {
|
||||||
|
if (output->cursor.is_sw) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer);
|
struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return;
|
return;
|
||||||
|
@ -231,14 +235,19 @@ static void handle_cursor_surface_destroy(struct wl_listener *listener,
|
||||||
|
|
||||||
void wlr_output_set_cursor_surface(struct wlr_output *output,
|
void wlr_output_set_cursor_surface(struct wlr_output *output,
|
||||||
struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y) {
|
struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y) {
|
||||||
if (surface && strcmp(surface->role, "cursor") != 0) {
|
if (surface && strcmp(surface->role, "wl_pointer-cursor") != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (surface && output->cursor.surface == surface) {
|
if (surface && surface == output->cursor.surface) {
|
||||||
|
if (output->impl->set_cursor && !output->cursor.is_sw) {
|
||||||
|
// Only update the hotspot
|
||||||
|
output->impl->set_cursor(output, NULL, 0, 0, 0, hotspot_x,
|
||||||
|
hotspot_y, false);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,11 +257,22 @@ void wlr_output_set_cursor_surface(struct wlr_output *output,
|
||||||
output->cursor.surface = NULL;
|
output->cursor.surface = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable hardware cursor
|
||||||
|
// TODO: support hardware cursors
|
||||||
|
output->cursor.is_sw = true;
|
||||||
|
if (output->impl->set_cursor) {
|
||||||
|
output->impl->set_cursor(output, NULL, 0, 0, 0, hotspot_x, hotspot_y,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//output->cursor.is_sw = output->impl->set_cursor == NULL;
|
||||||
output->cursor.surface = surface;
|
output->cursor.surface = surface;
|
||||||
|
|
||||||
if (surface != NULL) {
|
if (surface != NULL) {
|
||||||
wl_signal_add(&surface->events.commit, &output->cursor.surface_commit);
|
wl_signal_add(&surface->events.commit, &output->cursor.surface_commit);
|
||||||
wl_signal_add(&surface->events.destroy, &output->cursor.surface_destroy);
|
wl_signal_add(&surface->events.destroy,
|
||||||
|
&output->cursor.surface_destroy);
|
||||||
|
commit_cursor_surface(output, surface);
|
||||||
} else {
|
} else {
|
||||||
set_cursor(output, NULL, 0, 0, 0, hotspot_x, hotspot_y);
|
set_cursor(output, NULL, 0, 0, 0, hotspot_x, hotspot_y);
|
||||||
}
|
}
|
||||||
|
@ -333,10 +353,20 @@ void wlr_output_swap_buffers(struct wlr_output *output) {
|
||||||
glViewport(0, 0, output->width, output->height);
|
glViewport(0, 0, output->width, output->height);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
float matrix[16];
|
|
||||||
wlr_texture_get_matrix(output->cursor.texture, &matrix, &output->transform_matrix,
|
struct wlr_texture *texture = output->cursor.texture;
|
||||||
output->cursor.x, output->cursor.y);
|
struct wlr_renderer *renderer = output->cursor.renderer;
|
||||||
wlr_render_with_matrix(output->cursor.renderer, output->cursor.texture, &matrix);
|
if (output->cursor.surface) {
|
||||||
|
texture = output->cursor.surface->texture;
|
||||||
|
renderer = output->cursor.surface->renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture && renderer) {
|
||||||
|
float matrix[16];
|
||||||
|
wlr_texture_get_matrix(texture, &matrix, &output->transform_matrix,
|
||||||
|
output->cursor.x, output->cursor.y);
|
||||||
|
wlr_render_with_matrix(renderer, texture, &matrix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_signal_emit(&output->events.swap_buffers, &output);
|
wl_signal_emit(&output->events.swap_buffers, &output);
|
||||||
|
|
|
@ -28,7 +28,7 @@ static void wl_pointer_set_cursor(struct wl_client *client,
|
||||||
if (surface_resource != NULL) {
|
if (surface_resource != NULL) {
|
||||||
surface = wl_resource_get_user_data(surface_resource);
|
surface = wl_resource_get_user_data(surface_resource);
|
||||||
|
|
||||||
if (wlr_surface_set_role(surface, "cursor", resource,
|
if (wlr_surface_set_role(surface, "wl_pointer-cursor", resource,
|
||||||
WL_POINTER_ERROR_ROLE) < 0) {
|
WL_POINTER_ERROR_ROLE) < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue