aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/drm.c10
-rw-r--r--backend/wayland/output.c19
-rw-r--r--include/rootston/input.h2
-rw-r--r--include/wlr/interfaces/wlr_output.h10
-rw-r--r--rootston/cursor.c24
-rw-r--r--types/wlr_output.c46
-rw-r--r--types/wlr_seat.c2
7 files changed, 82 insertions, 31 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 9e5346a1..ff4dc7f6 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -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);
diff --git a/backend/wayland/output.c b/backend/wayland/output.c
index 03b43b35..d308b907 100644
--- a/backend/wayland/output.c
+++ b/backend/wayland/output.c
@@ -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);
}
diff --git a/include/rootston/input.h b/include/rootston/input.h
index fbabbdb6..516104a7 100644
--- a/include/rootston/input.h
+++ b/include/rootston/input.h
@@ -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;
diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h
index 7d2821e0..b7927569 100644
--- a/include/wlr/interfaces/wlr_output.h
+++ b/include/wlr/interfaces/wlr_output.h
@@ -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
diff --git a/rootston/cursor.c b/rootston/cursor.c
index 8790934c..65109534 100644
--- a/rootston/cursor.c
+++ b/rootston/cursor.c
@@ -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) {
diff --git a/types/wlr_output.c b/types/wlr_output.c
index 723dd00b..4c9814ef 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -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);
diff --git a/types/wlr_seat.c b/types/wlr_seat.c
index bbb66142..ce055520 100644
--- a/types/wlr_seat.c
+++ b/types/wlr_seat.c
@@ -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;
}