From 6f1e972115abdd33b1adb41bcf301b2383a74677 Mon Sep 17 00:00:00 2001 From: columbarius Date: Sun, 14 Nov 2021 15:29:13 +0100 Subject: [PATCH] screencast: add option to select cropping region --- include/config.h | 2 ++ include/screencast_common.h | 1 + src/core/config.c | 36 ++++++++++++++++++++++++++++++ src/screencast/screencast.c | 10 +++++++++ src/screencast/screencast_common.c | 13 +++++++++++ xdg-desktop-portal-wlr.5.scd | 11 +++++++++ 6 files changed, 73 insertions(+) diff --git a/include/config.h b/include/config.h index f856dc1a..7dcd01ef 100644 --- a/include/config.h +++ b/include/config.h @@ -12,6 +12,8 @@ struct config_screencast { char *chooser_cmd; enum xdpw_chooser_types chooser_type; bool force_mod_linear; + enum xdpw_cropmode cropmode; + struct xdpw_frame_crop region; }; struct xdpw_config { diff --git a/include/screencast_common.h b/include/screencast_common.h index 81fb55bc..688b8b70 100644 --- a/include/screencast_common.h +++ b/include/screencast_common.h @@ -210,4 +210,5 @@ enum spa_video_format xdpw_format_pw_strip_alpha(enum spa_video_format format); enum xdpw_chooser_types get_chooser_type(const char *chooser_type); const char *chooser_type_str(enum xdpw_chooser_types chooser_type); +const char *cropmode_str(enum xdpw_cropmode cropmode); #endif /* SCREENCAST_COMMON_H */ diff --git a/src/core/config.c b/src/core/config.c index 693cc89e..8cbac840 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -17,6 +17,11 @@ void print_config(enum LOGLEVEL loglevel, struct xdpw_config *config) { logprint(loglevel, "config: chooser_cmd: %s", config->screencast_conf.chooser_cmd); logprint(loglevel, "config: chooser_type: %s", chooser_type_str(config->screencast_conf.chooser_type)); logprint(loglevel, "config: force_mod_linear: %d", config->screencast_conf.force_mod_linear); + logprint(loglevel, "config: cropmode: %s", cropmode_str(config->screencast_conf.cropmode)); + logprint(loglevel, "config: cropping_region x: %u", config->screencast_conf.region.x); + logprint(loglevel, "config: cropping_region y: %u", config->screencast_conf.region.y); + logprint(loglevel, "config: cropping_region width: %u", config->screencast_conf.region.width); + logprint(loglevel, "config: cropping_region height: %u", config->screencast_conf.region.height); } // NOTE: calling finish_config won't prepare the config to be read again from config file @@ -60,6 +65,28 @@ static void parse_bool(bool *dest, const char* value) { } } +static void parse_region(struct xdpw_frame_crop *dest, const char* value) { + if (value == NULL || *value == '\0') { + logprint(TRACE, "config: skipping empty value in config file"); + return; + } + sscanf(value, "%u,%u:%ux%u", &dest->x, &dest->y, &dest->width, &dest->height); +} + +static void parse_cropmode(enum xdpw_cropmode *dest, const char* value) { + if (value == NULL || *value == '\0') { + logprint(TRACE, "config: skipping empty value in config file"); + return; + } + if (strcmp(value, "none") == 0) { + *dest = XDPW_CROP_NONE; + } else if (strcmp(value, "wlroots") == 0) { + *dest = XDPW_CROP_WLROOTS; + } else if (strcmp(value, "pipewire") == 0) { + *dest = XDPW_CROP_PIPEWIRE; + } +} + static int handle_ini_screencast(struct config_screencast *screencast_conf, const char *key, const char *value) { if (strcmp(key, "output_name") == 0) { parse_string(&screencast_conf->output_name, value); @@ -78,6 +105,10 @@ static int handle_ini_screencast(struct config_screencast *screencast_conf, cons free(chooser_type); } else if (strcmp(key, "force_mod_linear") == 0) { parse_bool(&screencast_conf->force_mod_linear, value); + } else if (strcmp(key, "cropmode") == 0) { + parse_cropmode(&screencast_conf->cropmode, value); + } else if (strcmp(key, "region") == 0) { + parse_region(&screencast_conf->region, value); } else { logprint(TRACE, "config: skipping invalid key in config file"); return 0; @@ -100,6 +131,11 @@ static int handle_ini_config(void *data, const char* section, const char *key, c static void default_config(struct xdpw_config *config) { config->screencast_conf.max_fps = 0; config->screencast_conf.chooser_type = XDPW_CHOOSER_DEFAULT; + config->screencast_conf.cropmode = XDPW_CROP_NONE; + config->screencast_conf.region.x = 0; + config->screencast_conf.region.y = 0; + config->screencast_conf.region.width = 0; + config->screencast_conf.region.height = 0; } static bool file_exists(const char *path) { diff --git a/src/screencast/screencast.c b/src/screencast/screencast.c index 0a38bbd3..e8380407 100644 --- a/src/screencast/screencast.c +++ b/src/screencast/screencast.c @@ -73,6 +73,16 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx, cast->avoid_dmabufs = false; cast->teardown = false; wl_list_init(&cast->buffer_list); + if (ctx->state->config->screencast_conf.chooser_type == XDPW_CHOOSER_NONE && + ctx->state->config->screencast_conf.cropmode != XDPW_CROP_NONE && + ctx->state->config->screencast_conf.region.width != 0 && + ctx->state->config->screencast_conf.region.height != 0) { + cast->cropmode = ctx->state->config->screencast_conf.cropmode; + cast->current_frame.crop.x = ctx->state->config->screencast_conf.region.x; + cast->current_frame.crop.y = ctx->state->config->screencast_conf.region.y; + cast->current_frame.crop.width = ctx->state->config->screencast_conf.region.width; + cast->current_frame.crop.height = ctx->state->config->screencast_conf.region.height; + } logprint(INFO, "xdpw: screencast instance %p has %d references", cast, cast->refcount); wl_list_insert(&ctx->screencast_instances, &cast->link); logprint(INFO, "xdpw: %d active screencast instances", diff --git a/src/screencast/screencast_common.c b/src/screencast/screencast_common.c index 8c00c507..e0579f63 100644 --- a/src/screencast/screencast_common.c +++ b/src/screencast/screencast_common.c @@ -404,3 +404,16 @@ const char *chooser_type_str(enum xdpw_chooser_types chooser_type) { fprintf(stderr, "Could not find chooser type %d\n", chooser_type); abort(); } + +const char *cropmode_str(enum xdpw_cropmode cropmode) { + switch (cropmode) { + case XDPW_CROP_NONE: + return "none"; + case XDPW_CROP_WLROOTS: + return "wlroots"; + case XDPW_CROP_PIPEWIRE: + return "pipewire"; + } + fprintf(stderr, "Could not find chooser type %d\n", cropmode); + abort(); +} diff --git a/xdg-desktop-portal-wlr.5.scd b/xdg-desktop-portal-wlr.5.scd index 6cec9686..3159f0f4 100644 --- a/xdg-desktop-portal-wlr.5.scd +++ b/xdg-desktop-portal-wlr.5.scd @@ -80,6 +80,17 @@ These options need to be placed under the **[screencast]** section. This option is experimental and can be removed or replaced in future versions. +**cropmode** = _type_ + Specifies the mode to crop the output to the defined region. + + The supported types are: + - none: No cropping, ignore region. + - wlroots: Crop inside the compositor. Better performance. + - pipewire: Send cropping information via PipeWire. + +**region** = _offset_x_,_offset_y_:_width_x_height_ + Specifies the region the output is cropped to. Only works with **chooser_type** = none. + ## OUTPUT CHOOSER The chooser can be any program or script with the following behaviour: