Skip to content

Commit

Permalink
screencast: report correct position/size using xdg-output
Browse files Browse the repository at this point in the history
Previously the position reported was hardcoded as (0, 0). This is
incorrect; it should be the coordinates of the output being shared.
Additionally, the size reported was the buffer size, when it should
really be the logical size.

Use the xdg-output protocol (where supported) to determine the position
and size of the output and return them in the response. If it is not
supported by the compositor, omit the position/size.
  • Loading branch information
cptpcrd authored Jan 6, 2024
1 parent e8406fd commit 1eaa02e
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 6 deletions.
4 changes: 4 additions & 0 deletions include/screencast_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ struct xdpw_screencast_context {
struct wl_shm *shm;
struct zwp_linux_dmabuf_v1 *linux_dmabuf;
struct zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct xdpw_dmabuf_feedback_data feedback_data;
struct wl_array format_modifier_pairs;

Expand Down Expand Up @@ -194,9 +195,12 @@ struct xdpw_wlr_output {
struct wl_list link;
uint32_t id;
struct wl_output *output;
struct zxdg_output_v1 *xdg_output;
char *make;
char *model;
char *name;
int x;
int y;
int width;
int height;
float framerate;
Expand Down
3 changes: 3 additions & 0 deletions include/wlr_screencast.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#define LINUX_DMABUF_VERSION 4
#define LINUX_DMABUF_VERSION_MIN 3

#define XDG_OUTPUT_VERSION 3
#define XDG_OUTPUT_VERSION_MIN 1

struct xdpw_state;

int xdpw_wlr_screencopy_init(struct xdpw_state *state);
Expand Down
67 changes: 61 additions & 6 deletions src/screencast/screencast.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,12 +585,67 @@ static int method_screencast_start(sd_bus_message *msg, void *data,
if (ret < 0) {
return ret;
}
ret = sd_bus_message_append(reply, "{sv}",
"streams", "a(ua{sv})", 1,
cast->node_id, 3,
"position", "(ii)", 0, 0,
"size", "(ii)", cast->screencopy_frame_info[WL_SHM].width, cast->screencopy_frame_info[WL_SHM].height,
"source_type", "u", MONITOR);
ret = sd_bus_message_open_container(reply, 'e', "sv");
if (ret < 0) {
return ret;
}
ret = sd_bus_message_append(reply, "s", "streams");
if (ret < 0) {
return ret;
}
ret = sd_bus_message_open_container(reply, 'v', "a(ua{sv})");
if (ret < 0) {
return ret;
}
ret = sd_bus_message_open_container(reply, 'a', "(ua{sv})");
if (ret < 0) {
return ret;
}
ret = sd_bus_message_open_container(reply, 'r', "ua{sv}");
if (ret < 0) {
return ret;
}
ret = sd_bus_message_append(reply, "u", cast->node_id);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_open_container(reply, 'a', "{sv}");
if (ret < 0) {
return ret;
}
if (cast->target->output->xdg_output) {
ret = sd_bus_message_append(reply, "{sv}",
"position", "(ii)", cast->target->output->x, cast->target->output->y);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_append(reply, "{sv}",
"size", "(ii)", cast->target->output->width, cast->target->output->height);
if (ret < 0) {
return ret;
}
}
ret = sd_bus_message_append(reply, "{sv}", "source_type", "u", MONITOR);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_close_container(reply);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_close_container(reply);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_close_container(reply);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_close_container(reply);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_close_container(reply);
if (ret < 0) {
return ret;
}
Expand Down
76 changes: 76 additions & 0 deletions src/screencast/wlr_screencast.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "wlr-screencopy-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
Expand Down Expand Up @@ -306,6 +307,42 @@ static const struct wl_output_listener wlr_output_listener = {
.description = wlr_output_handle_description,
};

static void xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output_v1,
int32_t x, int32_t y) {
struct xdpw_wlr_output *output = data;
output->x = x;
output->y = y;
}

static void xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output_v1,
int32_t width, int32_t height) {
struct xdpw_wlr_output *output = data;
output->width = width;
output->height = height;
}

static void xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output_v1) {
/* Nothing to do */
}

static void xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output_v1,
const char *name) {
/* Nothing to do */
}

static void xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output_v1,
const char *description) {
/* Nothing to do */
}

static const struct zxdg_output_v1_listener xdg_output_listener = {
.logical_position = xdg_output_handle_logical_position,
.logical_size = xdg_output_handle_logical_size,
.done = xdg_output_handle_done,
.name = xdg_output_handle_name,
.description = xdg_output_handle_description,
};

static struct xdpw_wlr_output *xdpw_wlr_output_first(struct wl_list *output_list) {
struct xdpw_wlr_output *output, *tmp;
wl_list_for_each_safe(output, tmp, output_list, link) {
Expand Down Expand Up @@ -555,6 +592,9 @@ static void wlr_remove_output(struct xdpw_wlr_output *out) {
free(out->name);
free(out->make);
free(out->model);
if (out->xdg_output) {
zxdg_output_v1_destroy(out->xdg_output);
}
wl_output_destroy(out->output);
wl_list_remove(&out->link);
free(out);
Expand Down Expand Up @@ -737,6 +777,12 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg,
logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, WL_OUTPUT_VERSION);
output->output = wl_registry_bind(reg, id, &wl_output_interface, WL_OUTPUT_VERSION);

if (ctx->xdg_output_manager) {
output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
ctx->xdg_output_manager, output->output);
zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
}

wl_output_add_listener(output->output, &wlr_output_listener, output);
wl_list_insert(&ctx->output_list, &output->link);
}
Expand Down Expand Up @@ -776,6 +822,17 @@ static void wlr_registry_handle_add(void *data, struct wl_registry *reg,
zwp_linux_dmabuf_v1_add_listener(ctx->linux_dmabuf, &linux_dmabuf_listener, ctx);
}
}

if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0
&& ver >= XDG_OUTPUT_VERSION_MIN) {
uint32_t version = ver;
if (XDG_OUTPUT_VERSION < ver) {
version = XDG_OUTPUT_VERSION;
}
logprint(DEBUG, "wlroots: |-- registered to interface %s (Version %u)", interface, version);
ctx->xdg_output_manager = wl_registry_bind(
reg, id, &zxdg_output_manager_v1_interface, version);
}
}

static void wlr_registry_handle_remove(void *data, struct wl_registry *reg,
Expand Down Expand Up @@ -856,6 +913,19 @@ int xdpw_wlr_screencopy_init(struct xdpw_state *state) {
}
}

if (ctx->xdg_output_manager) {
struct xdpw_wlr_output *output;
wl_list_for_each(output, &ctx->output_list, link) {
if (!output->xdg_output) {
output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
ctx->xdg_output_manager, output->output);
zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
}
}
wl_display_roundtrip(state->wl_display);
logprint(DEBUG, "wayland: xdg_output listeners run");
}

return 0;
}

Expand All @@ -865,6 +935,9 @@ void xdpw_wlr_screencopy_finish(struct xdpw_screencast_context *ctx) {
struct xdpw_wlr_output *output, *tmp_o;
wl_list_for_each_safe(output, tmp_o, &ctx->output_list, link) {
wl_list_remove(&output->link);
if (output->xdg_output) {
zxdg_output_v1_destroy(output->xdg_output);
}
wl_output_destroy(output->output);
}

Expand All @@ -890,6 +963,9 @@ void xdpw_wlr_screencopy_finish(struct xdpw_screencast_context *ctx) {
if (ctx->linux_dmabuf) {
zwp_linux_dmabuf_v1_destroy(ctx->linux_dmabuf);
}
if (ctx->xdg_output_manager) {
zxdg_output_manager_v1_destroy(ctx->xdg_output_manager);
}
if (ctx->registry) {
wl_registry_destroy(ctx->registry);
}
Expand Down

0 comments on commit 1eaa02e

Please sign in to comment.