diff options
author | dec05eba <dec05eba@protonmail.com> | 2024-11-08 20:52:08 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2024-11-08 20:52:08 +0100 |
commit | 70fced3889b4c15044041b960ab9d6be9b697f5e (patch) | |
tree | ecf6c4d2119e1c1d723baff00c5a371271247a3c /src/utils.c | |
parent | 0686b924def291323c94f8d26d96fd0ef9d854c4 (diff) |
x11: fix correct monitor capture size when output is scaled
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/src/utils.c b/src/utils.c index bad16d9..a312b0d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -71,6 +71,27 @@ static uint32_t x11_output_get_connector_id(Display *dpy, RROutput output, Atom return result; } +static const XRRModeInfo* get_current_mode_info(const XRRScreenResources *screen_res, const XRROutputInfo *out_info, const RRMode current_mode) { + for(int i = 0; i < out_info->nmode; ++i) { + if(out_info->modes[i] == current_mode) { + const XRRModeInfo *mode_info = get_mode_info(screen_res, out_info->modes[i]); + if(mode_info) + return mode_info; + } + } + return NULL; +} + +static vec2i get_monitor_size_rotated(int width, int height, gsr_monitor_rotation rotation) { + vec2i size = { .x = width, .y = height }; + if(rotation == GSR_MONITOR_ROT_90 || rotation == GSR_MONITOR_ROT_270) { + int tmp_x = size.x; + size.x = size.y; + size.y = tmp_x; + } + return size; +} + void for_each_active_monitor_output_x11_not_cached(Display *display, active_monitor_callback callback, void *userdata) { XRRScreenResources *screen_res = XRRGetScreenResources(display, DefaultRootWindow(display)); if(!screen_res) @@ -84,16 +105,26 @@ void for_each_active_monitor_output_x11_not_cached(Display *display, active_moni if(out_info && out_info->crtc && out_info->connection == RR_Connected) { XRRCrtcInfo *crt_info = XRRGetCrtcInfo(display, screen_res, out_info->crtc); if(crt_info && crt_info->mode) { - const XRRModeInfo *mode_info = get_mode_info(screen_res, crt_info->mode); - if(mode_info && out_info->nameLen < (int)sizeof(display_name)) { + // We want to use the current mode info width/height instead of crtc info width/height becuase crtc info is scaled if the monitor is scaled + // (xrandr --output DP-1 --scale 1.5). Normally this is not an issue for x11 applications, but gpu screen recorder captures the drm framebuffer + // instead of x11 api. This drm framebuffer which doesn't increase in size when using xrandr scaling. + // Maybe a better option would be to get the drm crtc size instead. + const XRRModeInfo *current_mode_info = get_current_mode_info(screen_res, out_info, crt_info->mode); + if(!current_mode_info) + current_mode_info = get_mode_info(screen_res, crt_info->mode); + + if(current_mode_info && out_info->nameLen < (int)sizeof(display_name)) { snprintf(display_name, sizeof(display_name), "%.*s", (int)out_info->nameLen, out_info->name); + const gsr_monitor_rotation rotation = x11_rotation_to_gsr_rotation(crt_info->rotation); + const vec2i monitor_size = get_monitor_size_rotated(current_mode_info->width, current_mode_info->height, rotation); + const gsr_monitor monitor = { .name = display_name, .name_len = out_info->nameLen, .pos = { .x = crt_info->x, .y = crt_info->y }, - .size = { .x = (int)crt_info->width, .y = (int)crt_info->height }, + .size = monitor_size, .connector_id = x11_output_get_connector_id(display, screen_res->outputs[i], randr_connector_id_atom), - .rotation = x11_rotation_to_gsr_rotation(crt_info->rotation), + .rotation = rotation, .monitor_identifier = out_info->crtc }; callback(&monitor, userdata); |