Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit eaf5b69

Browse files
committed
Work on cursor capturing
1 parent 1a89d0d commit eaf5b69

3 files changed

Lines changed: 126 additions & 45 deletions

File tree

include/wlr/types/wlr_zext_screencopy_v1.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct wlr_zext_screencopy_manager_v1 {
2828
};
2929

3030
enum wlr_zext_screencopy_surface_v1_state {
31-
WLR_ZEXT_SCREENCOPY_SURFACE_V1_STATE_WAITING_FOR_BUFFER_FORMATS,
31+
WLR_ZEXT_SCREENCOPY_SURFACE_V1_STATE_WAITING_FOR_BUFFER_FORMATS = 0,
3232
WLR_ZEXT_SCREENCOPY_SURFACE_V1_STATE_READY,
3333
};
3434

@@ -43,6 +43,8 @@ struct wlr_zext_screencopy_surface_v1 {
4343

4444
enum wlr_zext_screencopy_surface_v1_state state;
4545

46+
struct wlr_buffer *buffer;
47+
4648
uint32_t wl_shm_format;
4749
int wl_shm_stride;
4850
uint32_t dmabuf_format;
@@ -51,6 +53,10 @@ struct wlr_zext_screencopy_surface_v1 {
5153
int cursor_wl_shm_stride;
5254
uint32_t cursor_dmabuf_format;
5355

56+
int cursor_width;
57+
int cursor_height;
58+
bool have_cursor;
59+
5460
uint32_t options;
5561
struct wlr_zext_screencopy_surface_v1_buffer staged_buffer;
5662
struct wlr_zext_screencopy_surface_v1_buffer current_buffer;

protocol/screencopy-unstable-v1.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@
135135
</description>
136136
</event>
137137

138+
<event name="reconfig">
139+
<description summary="buffer attributes changed">
140+
Signals that some buffer attributes have changed. This event will be
141+
followed by buffer info events and "init_done".
142+
</description>
143+
</event>
144+
138145
<request name="attach_buffer">
139146
<description summary="attach buffer to surface">
140147
Attach a buffer to the surface.
@@ -225,6 +232,23 @@
225232
<arg name="height" type="uint" summary="current height"/>
226233
</event>
227234

235+
<event name="cursor_enter">
236+
<description summary="cursor entered surface">
237+
Sent when a cursor enters the captured surface. It shall be generated
238+
before the "cursor_info" event when and only when a cursor enters the
239+
surface.
240+
</description>
241+
<arg name="seat_name" type="string" summary="seat name"/>
242+
</event>
243+
244+
<event name="cursor_leave">
245+
<description summary="cursor left surface">
246+
Sent when a cursor leaves the captured surface. No "cursor_info" event
247+
is generated for for the given cursor.
248+
</description>
249+
<arg name="seat_name" type="string" summary="seat name"/>
250+
</event>
251+
228252
<event name="cursor_info">
229253
<description summary="cursor specific information">
230254
This event is generated for each cursor buffer that was attached to the

types/wlr_zext_screencopy_v1.c

Lines changed: 95 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -370,63 +370,47 @@ static void surface_handle_output_precommit(struct wl_listener *listener,
370370
}
371371
}
372372

373-
static void surface_handle_output_commit_formats(
374-
struct wlr_zext_screencopy_surface_v1 *surface,
375-
struct wlr_output_event_commit *event) {
373+
static bool surface_check_cursor_formats(
374+
struct wlr_zext_screencopy_surface_v1 *surface) {
376375
struct wlr_output *output = surface_check_output(surface);
377376
if (!output) {
378-
return;
377+
return false;
379378
}
380379

381-
struct wlr_renderer *renderer = output->renderer;
382-
383-
struct wlr_buffer *buffer = event->buffer;
384-
assert(buffer);
385-
386-
surface->wl_shm_format =
387-
get_buffer_preferred_read_format(buffer, renderer);
388-
surface->wl_shm_stride = buffer->width * 4; // TODO: This assumes things...
380+
struct wlr_buffer *buffer = output->cursor_front_buffer;
381+
if (!buffer) {
382+
return false;
383+
}
389384

390-
surface->dmabuf_format = get_dmabuf_format(buffer);
385+
uint32_t dmabuf_format = get_dmabuf_format(buffer);
391386

392-
if (surface->wl_shm_format != DRM_FORMAT_INVALID) {
393-
assert(surface->wl_shm_stride);
387+
return buffer->width != surface->cursor_width ||
388+
buffer->height != surface->cursor_height ||
389+
surface->cursor_dmabuf_format != dmabuf_format;
390+
}
394391

395-
zext_screencopy_surface_v1_send_buffer_info(surface->resource,
396-
ZEXT_SCREENCOPY_SURFACE_V1_BUFFER_TYPE_WL_SHM,
397-
surface->wl_shm_format, output->width,
398-
output->height, surface->wl_shm_stride);
392+
static void surface_advertise_cursor_formats(
393+
struct wlr_zext_screencopy_surface_v1 *surface) {
394+
struct wlr_output *output = surface_check_output(surface);
395+
if (!output) {
396+
return;
399397
}
400398

401-
if (surface->dmabuf_format != DRM_FORMAT_INVALID) {
402-
zext_screencopy_surface_v1_send_buffer_info(surface->resource,
403-
ZEXT_SCREENCOPY_SURFACE_V1_BUFFER_TYPE_DMABUF,
404-
surface->dmabuf_format, output->width,
405-
output->height, 0);
399+
struct wlr_buffer *buffer = output->cursor_front_buffer;
400+
if (!buffer) {
401+
return;
406402
}
407403

408-
// TODO: If hardware cursors are not enabled, don't advertise cursor
409-
// formats.
410-
bool have_dummy_buffer = false;
411-
struct wlr_buffer *cursor_buffer = output->cursor_front_buffer;
412-
if (!cursor_buffer) {
413-
// This is a hack so that we can get a cursor buffer when no
414-
// cursor is set.
415-
cursor_buffer = wlr_swapchain_acquire(output->cursor_swapchain,
416-
NULL);
417-
have_dummy_buffer = true;
418-
}
404+
struct wlr_renderer *renderer = output->renderer;
419405

420406
surface->cursor_wl_shm_format =
421-
get_buffer_preferred_read_format(cursor_buffer, renderer);
407+
get_buffer_preferred_read_format(buffer, renderer);
422408
surface->cursor_wl_shm_stride =
423-
cursor_buffer->width * 4; // TODO: This assumes things...
424-
425-
surface->cursor_dmabuf_format = get_dmabuf_format(cursor_buffer);
409+
buffer->width * 4; // TODO: This assumes things...
410+
surface->cursor_dmabuf_format = get_dmabuf_format(buffer);
426411

427-
if (have_dummy_buffer) {
428-
wlr_buffer_unlock(cursor_buffer);
429-
}
412+
surface->cursor_width = buffer->width;
413+
surface->cursor_height = buffer->height;
430414

431415
if (surface->cursor_wl_shm_format != DRM_FORMAT_INVALID) {
432416
assert(surface->cursor_wl_shm_stride);
@@ -435,7 +419,7 @@ static void surface_handle_output_commit_formats(
435419
surface->resource, "default",
436420
ZEXT_SCREENCOPY_SURFACE_V1_BUFFER_TYPE_WL_SHM,
437421
surface->cursor_wl_shm_format,
438-
cursor_buffer->width, cursor_buffer->height,
422+
buffer->width, buffer->height,
439423
surface->cursor_wl_shm_stride);
440424
}
441425

@@ -444,10 +428,57 @@ static void surface_handle_output_commit_formats(
444428
surface->resource, "default",
445429
ZEXT_SCREENCOPY_SURFACE_V1_BUFFER_TYPE_DMABUF,
446430
surface->cursor_dmabuf_format,
447-
cursor_buffer->width, cursor_buffer->height, 0);
431+
buffer->width, buffer->height, 0);
448432
}
449433

450434
zext_screencopy_surface_v1_send_init_done(surface->resource);
435+
436+
if (output->cursor_front_buffer) {
437+
zext_screencopy_surface_v1_send_cursor_enter(surface->resource,
438+
"default");
439+
surface->have_cursor = true;
440+
}
441+
}
442+
443+
static void surface_advertise_buffer_formats(
444+
struct wlr_zext_screencopy_surface_v1 *surface,
445+
struct wlr_buffer *buffer) {
446+
struct wlr_output *output = surface_check_output(surface);
447+
if (!output) {
448+
return;
449+
}
450+
451+
struct wlr_renderer *renderer = output->renderer;
452+
453+
surface->wl_shm_format =
454+
get_buffer_preferred_read_format(buffer, renderer);
455+
surface->wl_shm_stride = buffer->width * 4; // TODO: This assumes things...
456+
457+
surface->dmabuf_format = get_dmabuf_format(buffer);
458+
459+
if (surface->wl_shm_format != DRM_FORMAT_INVALID) {
460+
assert(surface->wl_shm_stride);
461+
462+
zext_screencopy_surface_v1_send_buffer_info(surface->resource,
463+
ZEXT_SCREENCOPY_SURFACE_V1_BUFFER_TYPE_WL_SHM,
464+
surface->wl_shm_format, output->width,
465+
output->height, surface->wl_shm_stride);
466+
}
467+
468+
if (surface->dmabuf_format != DRM_FORMAT_INVALID) {
469+
zext_screencopy_surface_v1_send_buffer_info(surface->resource,
470+
ZEXT_SCREENCOPY_SURFACE_V1_BUFFER_TYPE_DMABUF,
471+
surface->dmabuf_format, output->width,
472+
output->height, 0);
473+
}
474+
475+
surface_advertise_cursor_formats(surface);
476+
}
477+
478+
static void surface_handle_output_commit_formats(
479+
struct wlr_zext_screencopy_surface_v1 *surface,
480+
struct wlr_output_event_commit *event) {
481+
surface_advertise_buffer_formats(surface, event->buffer);
451482
surface->state = WLR_ZEXT_SCREENCOPY_SURFACE_V1_STATE_READY;
452483
}
453484

@@ -656,6 +687,26 @@ static void surface_handle_output_commit_ready(
656687
return;
657688
}
658689

690+
if (surface_check_cursor_formats(surface)) {
691+
zext_screencopy_surface_v1_send_cursor_leave(surface->resource,
692+
"default");
693+
zext_screencopy_surface_v1_send_reconfig(surface->resource);
694+
surface_advertise_buffer_formats(surface, event->buffer);
695+
// TODO: Reset staged buffers?
696+
return;
697+
}
698+
699+
if (surface->have_cursor && !output->cursor_front_buffer) {
700+
zext_screencopy_surface_v1_send_cursor_leave(surface->resource,
701+
"default");
702+
surface->have_cursor = false;
703+
} else if (!surface->have_cursor && output->cursor_front_buffer) {
704+
zext_screencopy_surface_v1_send_cursor_enter(surface->resource,
705+
"default");
706+
surface->have_cursor = true;
707+
}
708+
709+
659710
if (!surface->current_buffer.resource) {
660711
return;
661712
}

0 commit comments

Comments
 (0)