mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-29 16:05:59 +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,
|
||||
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_backend *drm = conn->drm;
|
||||
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_plane *plane = crtc->cursor;
|
||||
|
||||
if (!buf) {
|
||||
if (!buf && update_pixels) {
|
||||
// Hide the cursor
|
||||
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;
|
||||
}
|
||||
|
||||
if (!update_pixels) {
|
||||
// Only update the cursor hotspot
|
||||
return true;
|
||||
}
|
||||
|
||||
struct gbm_bo *bo = plane->cursor_bo;
|
||||
uint32_t bo_width = gbm_bo_get_width(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,
|
||||
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 *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) {
|
||||
wl_pointer_set_cursor(output->backend->pointer, output->enter_serial,
|
||||
NULL, 0, 0);
|
||||
// Hide cursor
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
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,
|
||||
output->cursor_surface, hotspot_x, hotspot_y);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ struct roots_input {
|
|||
struct wlr_xcursor_theme *theme;
|
||||
struct wlr_xcursor *xcursor;
|
||||
struct wlr_seat *wl_seat;
|
||||
struct roots_view *client_cursor_view;
|
||||
struct wl_client *cursor_client;
|
||||
|
||||
enum roots_cursor_mode mode;
|
||||
struct roots_view *active_view, *last_active_view;
|
||||
|
|
|
@ -8,16 +8,16 @@ struct wlr_output_impl {
|
|||
void (*enable)(struct wlr_output *output, bool enable);
|
||||
bool (*set_mode)(struct wlr_output *output, struct wlr_output_mode *mode);
|
||||
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,
|
||||
int32_t stride, uint32_t width, uint32_t height,
|
||||
int32_t hotspot_x, int32_t hotspot_y);
|
||||
int32_t stride, uint32_t width, uint32_t height,
|
||||
int32_t hotspot_x, int32_t hotspot_y, bool update_pixels);
|
||||
bool (*move_cursor)(struct wlr_output *output, int x, int y);
|
||||
void (*destroy)(struct wlr_output *output);
|
||||
void (*make_current)(struct wlr_output *output);
|
||||
void (*swap_buffers)(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);
|
||||
};
|
||||
|
||||
|
@ -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_update_matrix(struct wlr_output *output);
|
||||
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
|
||||
|
|
|
@ -83,10 +83,16 @@ void cursor_update_position(struct roots_input *input, uint32_t time) {
|
|||
case ROOTS_CURSOR_PASSTHROUGH:
|
||||
view = view_at(desktop, input->cursor->x, input->cursor->y, &surface,
|
||||
&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");
|
||||
cursor_set_xcursor_image(input, input->xcursor->images[0]);
|
||||
input->client_cursor_view = NULL;
|
||||
input->cursor_client = NULL;
|
||||
}
|
||||
if (view) {
|
||||
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);
|
||||
struct wlr_seat_pointer_request_set_cursor_event *event = data;
|
||||
|
||||
struct wlr_surface *focused_surface = NULL;
|
||||
double sx, sy;
|
||||
struct roots_view *focused_view = view_at(input->server->desktop,
|
||||
input->cursor->x, input->cursor->y, &focused_surface, &sx, &sy);
|
||||
bool ok = focused_surface != NULL;
|
||||
if (focused_surface != NULL) {
|
||||
struct wlr_surface *focused_surface =
|
||||
event->seat_handle->wlr_seat->pointer_state.focused_surface;
|
||||
bool ok = focused_surface != NULL && focused_surface->resource != NULL;
|
||||
if (ok) {
|
||||
struct wl_client *focused_client =
|
||||
wl_resource_get_client(focused_surface->resource);
|
||||
ok = event->client == focused_client;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -324,7 +328,7 @@ static void handle_request_set_cursor(struct wl_listener *listener,
|
|||
event->hotspot_x, event->hotspot_y);
|
||||
}
|
||||
|
||||
input->client_cursor_view = focused_view;
|
||||
input->cursor_client = event->client;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (output->impl->set_cursor
|
||||
&& output->impl->set_cursor(output, buf, stride, width, height,
|
||||
hotspot_x, hotspot_y)) {
|
||||
hotspot_x, hotspot_y, true)) {
|
||||
output->cursor.is_sw = false;
|
||||
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,
|
||||
struct wlr_surface *surface) {
|
||||
if (output->cursor.is_sw) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer);
|
||||
if (buffer == NULL) {
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
output->cursor.hotspot_x = hotspot_x;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -248,11 +257,22 @@ void wlr_output_set_cursor_surface(struct wlr_output *output,
|
|||
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;
|
||||
|
||||
if (surface != NULL) {
|
||||
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 {
|
||||
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);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
float matrix[16];
|
||||
wlr_texture_get_matrix(output->cursor.texture, &matrix, &output->transform_matrix,
|
||||
output->cursor.x, output->cursor.y);
|
||||
wlr_render_with_matrix(output->cursor.renderer, output->cursor.texture, &matrix);
|
||||
|
||||
struct wlr_texture *texture = output->cursor.texture;
|
||||
struct wlr_renderer *renderer = output->cursor.renderer;
|
||||
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);
|
||||
|
|
|
@ -28,7 +28,7 @@ static void wl_pointer_set_cursor(struct wl_client *client,
|
|||
if (surface_resource != NULL) {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue