From fa9290088d4d34b55f9520bc296c8852aec6ebe7 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 20 Nov 2024 14:33:47 +0800 Subject: [PATCH] Display (Linux): detect preferred resolution and refresh rate --- src/detection/displayserver/displayserver.c | 6 ++ src/detection/displayserver/displayserver.h | 20 ++++--- src/detection/displayserver/linux/drm.c | 39 ++++++++----- .../linux/wayland/global-output.c | 25 +++++--- .../displayserver/linux/wayland/kde-output.c | 43 +++++++++----- .../displayserver/linux/wayland/wayland.h | 5 +- .../displayserver/linux/wayland/zwlr-output.c | 57 +++++++++++++------ src/detection/displayserver/linux/xcb.c | 51 +++++++++-------- src/detection/displayserver/linux/xlib.c | 35 +++++++----- src/modules/display/display.c | 7 ++- 10 files changed, 187 insertions(+), 101 deletions(-) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index c2ba3e593..6ae9efbc4 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -7,6 +7,9 @@ FFDisplayResult* ffdsAppendDisplay( double refreshRate, uint32_t scaledWidth, uint32_t scaledHeight, + uint32_t preferredWidth, + uint32_t preferredHeight, + double preferredRefreshRate, uint32_t rotation, FFstrbuf* name, FFDisplayType type, @@ -25,6 +28,9 @@ FFDisplayResult* ffdsAppendDisplay( display->refreshRate = refreshRate; display->scaledWidth = scaledWidth; display->scaledHeight = scaledHeight; + display->preferredWidth = preferredWidth; + display->preferredHeight = preferredHeight; + display->preferredRefreshRate = preferredRefreshRate; display->rotation = rotation; ffStrbufInitMove(&display->name, name); display->type = type; diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 4de3bdd4d..dd4fd9651 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -58,17 +58,20 @@ typedef enum __attribute__((__packed__)) FFDisplayHdrStatus typedef struct FFDisplayResult { - uint32_t width; - uint32_t height; - double refreshRate; - uint32_t scaledWidth; - uint32_t scaledHeight; + uint32_t width; // in px + uint32_t height; // in px + double refreshRate; // in Hz + uint32_t scaledWidth; // in px + uint32_t scaledHeight; // in px + uint32_t preferredWidth; // in px + uint32_t preferredHeight; // in px + double preferredRefreshRate; // in Hz FFstrbuf name; FFDisplayType type; uint32_t rotation; uint64_t id; // platform dependent - uint32_t physicalWidth; - uint32_t physicalHeight; + uint32_t physicalWidth; // in mm + uint32_t physicalHeight; // in mm bool primary; const char* platformApi; uint8_t bitDepth; @@ -97,6 +100,9 @@ FFDisplayResult* ffdsAppendDisplay( double refreshRate, uint32_t scaledWidth, uint32_t scaledHeight, + uint32_t preferredWidth, + uint32_t preferredHeight, + double preferredRefreshRate, uint32_t rotation, FFstrbuf* name, FFDisplayType type, diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index fb837e4a8..959358a16 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -84,6 +84,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) width, height, refreshRate, 0, 0, + 0, 0, + 0, 0, &name, ffdsGetDisplayType(plainName), @@ -298,22 +300,28 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffdrmModeFreeEncoder(encoder); } + uint32_t preferredWidth = 0, preferredHeight = 0, preferredRefreshRate = 0; + + for (int iMode = 0; iMode < conn->count_modes; ++iMode) + { + drmModeModeInfo* mode = &conn->modes[iMode]; + + if (mode->type & DRM_MODE_TYPE_PREFERRED) + { + preferredWidth = mode->hdisplay; + preferredHeight = mode->vdisplay; + preferredRefreshRate = mode->vrefresh; + break; + } + } + + // NVIDIA DRM driver seems incomplete and conn->encoder_id == 0 + // Assume preferred resolution is used as what we do in drmParseSys if (width == 0 || height == 0) { - // NVIDIA DRM driver seems incomplete and conn->encoder_id == 0 - // Assume preferred resolution is used as what we do in drmParseSys - for (int iMode = 0; iMode < conn->count_modes; ++iMode) - { - drmModeModeInfo* mode = &conn->modes[iMode]; - - if (mode->type & DRM_MODE_TYPE_PREFERRED) - { - width = mode->hdisplay; - height = mode->vdisplay; - refreshRate = mode->vrefresh; - break; - } - } + width = preferredWidth; + height = preferredHeight; + refreshRate = preferredRefreshRate; } @@ -382,6 +390,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) refreshRate, 0, 0, + preferredWidth, + preferredHeight, + preferredRefreshRate, 0, &name, conn->connector_type == DRM_MODE_CONNECTOR_eDP || conn->connector_type == DRM_MODE_CONNECTOR_LVDS diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index ab9fc5c2f..8b3671d16 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -6,13 +6,20 @@ static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate) { - if(!(flags & WL_OUTPUT_MODE_CURRENT)) - return; - WaylandDisplay* display = data; - display->width = width; - display->height = height; - display->refreshRate = refreshRate; + + if (flags & WL_OUTPUT_MODE_CURRENT) + { + display->width = width; + display->height = height; + display->refreshRate = refreshRate; + } + if (flags & WL_OUTPUT_MODE_PREFERRED) + { + display->preferredWidth = width; + display->preferredHeight = height; + display->preferredRefreshRate = refreshRate; + } } static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale) @@ -79,9 +86,6 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist WaylandDisplay display = { .parent = wldata, - .width = 0, - .height = 0, - .refreshRate = 0, .scale = 1, .transform = WL_OUTPUT_TRANSFORM_NORMAL, .type = FF_DISPLAY_TYPE_UNKNOWN, @@ -118,6 +122,9 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist display.refreshRate / 1000.0, (uint32_t) (display.width / display.scale), (uint32_t) (display.height / display.scale), + (uint32_t) display.preferredWidth, + (uint32_t) display.preferredHeight, + display.preferredRefreshRate / 1000.0, rotation, display.edidName.length ? &display.edidName diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index beac7b635..2b903bc55 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -11,26 +11,33 @@ typedef struct WaylandKdeMode int32_t width; int32_t height; int32_t refreshRate; + bool preferred; struct kde_output_device_mode_v2* pMode; } WaylandKdeMode; -static void waylandKdeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height) +static void waylandKdeModeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height) { WaylandKdeMode* mode = (WaylandKdeMode*) data; mode->width = width; mode->height = height; } -static void waylandKdeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate) +static void waylandKdeModeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate) { WaylandKdeMode* mode = (WaylandKdeMode*) data; mode->refreshRate = rate; } +static void waylandKdeModePreferredListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_) +{ + WaylandKdeMode* mode = (WaylandKdeMode*) data; + mode->preferred = true; +} + static const struct kde_output_device_mode_v2_listener modeListener = { - .size = waylandKdeSizeListener, - .refresh = waylandKdeRefreshListener, - .preferred = (void*) stubListener, + .size = waylandKdeModeSizeListener, + .refresh = waylandKdeModeRefreshListener, + .preferred = waylandKdeModePreferredListener, .removed = (void*) stubListener, }; @@ -40,7 +47,7 @@ static void waylandKdeModeListener(void* data, FF_MAYBE_UNUSED struct kde_output if (!wldata->internal) return; WaylandKdeMode* newMode = ffListAdd((FFlist*) wldata->internal); - newMode->pMode = mode; + *newMode = (WaylandKdeMode) { .pMode = mode }; // Strangely, the listener is called only in this function, but not in `waylandKdeCurrentModeListener` wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode); @@ -52,18 +59,24 @@ static void waylandKdeCurrentModeListener(void* data, FF_MAYBE_UNUSED struct kde WaylandDisplay* wldata = (WaylandDisplay*) data; if (!wldata->internal) return; - WaylandKdeMode* current = NULL; + int set = 0; FF_LIST_FOR_EACH(WaylandKdeMode, m, *(FFlist*) wldata->internal) { if (m->pMode == mode) { - current = m; - break; + wldata->width = m->width; + wldata->height = m->height; + wldata->refreshRate = m->refreshRate; + if (++set == 2) break; + } + else if (m->preferred) + { + wldata->preferredWidth = m->width; + wldata->preferredHeight = m->height; + wldata->preferredRefreshRate = m->refreshRate; + if (++set == 2) break; } } - wldata->width = current->width; - wldata->height = current->height; - wldata->refreshRate = current->refreshRate; } static void waylandKdeScaleListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, wl_fixed_t scale) @@ -164,9 +177,6 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandKdeMode)); WaylandDisplay display = { .parent = wldata, - .width = 0, - .height = 0, - .refreshRate = 0, .scale = 1, .transform = WL_OUTPUT_TRANSFORM_NORMAL, .type = FF_DISPLAY_TYPE_UNKNOWN, @@ -191,6 +201,9 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, display.refreshRate / 1000.0, (uint32_t) (display.width / display.scale), (uint32_t) (display.height / display.scale), + (uint32_t) display.preferredWidth, + (uint32_t) display.preferredHeight, + display.preferredRefreshRate / 1000.0, rotation, display.edidName.length ? &display.edidName diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index c19d88199..ab11d0538 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -36,9 +36,12 @@ typedef struct WaylandDisplay WaylandData* parent; int32_t width; int32_t height; + int32_t refreshRate; + int32_t preferredWidth; + int32_t preferredHeight; + int32_t preferredRefreshRate; int32_t physicalWidth; int32_t physicalHeight; - int32_t refreshRate; double scale; enum wl_output_transform transform; FFDisplayType type; diff --git a/src/detection/displayserver/linux/wayland/zwlr-output.c b/src/detection/displayserver/linux/wayland/zwlr-output.c index c54818a64..65825bb62 100644 --- a/src/detection/displayserver/linux/wayland/zwlr-output.c +++ b/src/detection/displayserver/linux/wayland/zwlr-output.c @@ -20,34 +20,43 @@ typedef struct WaylandZwlrMode int32_t width; int32_t height; int32_t refreshRate; + bool preferred; struct zwlr_output_mode_v1* pMode; } WaylandZwlrMode; -static void waylandZwlrSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t width, int32_t height) +static void waylandZwlrModeSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t width, int32_t height) { WaylandZwlrMode* mode = (WaylandZwlrMode*) data; mode->width = width; mode->height = height; } -static void waylandZwlrRefreshListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t rate) +static void waylandZwlrModeRefreshListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t rate) { WaylandZwlrMode* mode = (WaylandZwlrMode*) data; mode->refreshRate = rate; } +static void waylandZwlrModePreferredListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1) +{ + WaylandZwlrMode* mode = (WaylandZwlrMode*) data; + mode->preferred = true; +} + static const struct zwlr_output_mode_v1_listener modeListener = { - .size = waylandZwlrSizeListener, - .refresh = waylandZwlrRefreshListener, - .preferred = (void*) stubListener, + .size = waylandZwlrModeSizeListener, + .refresh = waylandZwlrModeRefreshListener, + .preferred = waylandZwlrModePreferredListener, .finished = (void*) stubListener, }; static void waylandZwlrModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, struct zwlr_output_mode_v1 *mode) { WaylandDisplay* wldata = (WaylandDisplay*) data; + if (!wldata->internal) return; + WaylandZwlrMode* newMode = ffListAdd((FFlist*) wldata->internal); - newMode->pMode = mode; + *newMode = (WaylandZwlrMode) { .pMode = mode }; // Strangely, the listener is called only in this function, but not in `waylandZwlrCurrentModeListener` wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode); @@ -57,18 +66,26 @@ static void waylandZwlrCurrentModeListener(void* data, FF_MAYBE_UNUSED struct zw { // waylandZwlrModeListener is always run before this WaylandDisplay* wldata = (WaylandDisplay*) data; - WaylandZwlrMode* current = NULL; + if (!wldata->internal) return; + + int set = 0; FF_LIST_FOR_EACH(WaylandZwlrMode, m, *(FFlist*) wldata->internal) { if (m->pMode == mode) { - current = m; - break; + wldata->width = m->width; + wldata->height = m->height; + wldata->refreshRate = m->refreshRate; + if (++set == 2) break; + } + else if (m->preferred) + { + wldata->preferredWidth = m->width; + wldata->preferredHeight = m->height; + wldata->preferredRefreshRate = m->refreshRate; + if (++set == 2) break; } } - wldata->width = current->width; - wldata->height = current->height; - wldata->refreshRate = current->refreshRate; } static void waylandZwlrPhysicalSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, int32_t width, int32_t height) @@ -78,12 +95,18 @@ static void waylandZwlrPhysicalSizeListener(void* data, FF_MAYBE_UNUSED struct z wldata->physicalHeight = height; } +static void waylandZwlrEnabledListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, bool enabled) +{ + WaylandDisplay* wldata = (WaylandDisplay*) data; + if (!enabled) wldata->internal = NULL; +} + static const struct zwlr_output_head_v1_listener headListener = { .name = (void*) ffWaylandOutputNameListener, .description = (void*) ffWaylandOutputDescriptionListener, .physical_size = waylandZwlrPhysicalSizeListener, .mode = waylandZwlrModeListener, - .enabled = (void*) stubListener, + .enabled = (void*) waylandZwlrEnabledListener, .current_mode = waylandZwlrCurrentModeListener, .position = (void*) stubListener, .transform = waylandZwlrTransformListener, @@ -102,9 +125,6 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandZwlrMode)); WaylandDisplay display = { .parent = wldata, - .width = 0, - .height = 0, - .refreshRate = 0, .scale = 1, .transform = WL_OUTPUT_TRANSFORM_NORMAL, .type = FF_DISPLAY_TYPE_UNKNOWN, @@ -117,7 +137,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output wldata->ffwl_proxy_add_listener((struct wl_proxy*) head, (void(**)(void)) &headListener, &display); wldata->ffwl_display_roundtrip(wldata->display); - if(display.width <= 0 || display.height <= 0) + if(display.width <= 0 || display.height <= 0 || !display.internal) return; uint32_t rotation = ffWaylandHandleRotation(&display); @@ -128,6 +148,9 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output display.refreshRate / 1000.0, (uint32_t) (display.width / display.scale + 0.5), (uint32_t) (display.height / display.scale + 0.5), + (uint32_t) display.preferredWidth, + (uint32_t) display.preferredHeight, + display.preferredRefreshRate / 1000.0, rotation, display.edidName.length ? &display.edidName diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 47508a242..b3eab2dec 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -119,28 +119,6 @@ typedef struct XcbRandrData xcb_randr_get_screen_resources_current_reply_t* screenResources; } XcbRandrData; -static double xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode) -{ - //We do the check here, because we want the best fallback display if this call failed - if(data->screenResources == NULL) - return 0; - - xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources); - - while(modesIterator.rem > 0) - { - if(modesIterator.data->id == mode) - { - xcb_randr_mode_info_t* modeInfo = modesIterator.data; - return (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); - } - - data->ffxcb_randr_mode_info_next(&modesIterator); - } - - return 0; -} - static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength) { xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME); @@ -165,13 +143,38 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb break; } + xcb_randr_mode_info_t* currentMode = NULL; + xcb_randr_mode_info_t* preferredMode = NULL; + + if(data->screenResources) + { + xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources); + + if (output->num_preferred > 0) + preferredMode = modesIterator.data; + + while (modesIterator.rem > 0) + { + if (modesIterator.data->id == crtcInfoReply->mode) + { + currentMode = modesIterator.data; + break; + } + + data->ffxcb_randr_mode_info_next(&modesIterator); + } + } + FFDisplayResult* item = ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, - xcbRandrHandleMode(data, crtcInfoReply->mode), + currentMode ? (double) currentMode->dot_clock / (double) ((uint32_t) currentMode->htotal * currentMode->vtotal) : 0, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, + preferredMode ? (uint32_t) preferredMode->width : 0, + preferredMode ? (uint32_t) preferredMode->height : 0, + preferredMode ? (double) preferredMode->dot_clock / (double) ((uint32_t) preferredMode->htotal * preferredMode->vtotal) : 0, rotation, name, displayType, @@ -261,6 +264,7 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* 0, (uint32_t) monitor->width, (uint32_t) monitor->height, + 0, 0, 0, 0, &name, displayType, @@ -316,6 +320,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) 0, (uint32_t) screen->width_in_pixels, (uint32_t) screen->height_in_pixels, + 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index ef190c84a..d2a1d1f24 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -85,19 +85,6 @@ typedef struct XrandrData XRRScreenResources* screenResources; } XrandrData; -static double xrandrHandleMode(XrandrData* data, RRMode mode) -{ - for(int i = 0; i < data->screenResources->nmode; i++) - { - if(data->screenResources->modes[i].id == mode) - { - XRRModeInfo* modeInfo = &data->screenResources->modes[i]; - return (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); - } - } - return 0; -} - static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength) { //We do the check here, because we want the best fallback display if this call failed @@ -125,13 +112,31 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* break; } + XRRModeInfo* currentMode = NULL; + if (data->screenResources) + { + for(int i = 0; i < data->screenResources->nmode; i++) + { + if(data->screenResources->modes[i].id == crtcInfo->mode) + { + currentMode = &data->screenResources->modes[i]; + break; + } + } + } + + XRRModeInfo* preferredMode = data->screenResources && output->npreferred > 0 ? &data->screenResources->modes[0] : NULL; + FFDisplayResult* item = ffdsAppendDisplay( data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, - xrandrHandleMode(data, crtcInfo->mode), + currentMode ? (double) currentMode->dotClock / (double) ((uint32_t) currentMode->hTotal * currentMode->vTotal) : 0, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, + preferredMode ? (uint32_t) preferredMode->width : 0, + preferredMode ? (uint32_t) preferredMode->height : 0, + preferredMode ? (double) preferredMode->dotClock / (double) ((uint32_t) preferredMode->hTotal * preferredMode->vTotal) : 0, rotation, name, displayType, @@ -208,6 +213,7 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) 0, (uint32_t) monitorInfo->width, (uint32_t) monitorInfo->height, + 0, 0, 0, 0, &name, displayType, @@ -259,6 +265,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) 0, (uint32_t) WidthOfScreen(screen), (uint32_t) HeightOfScreen(screen), + 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 6c720f31b..ea81030b6 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -350,16 +350,21 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_val* output = yyjson_mut_obj_add_obj(doc, obj, "output"); yyjson_mut_obj_add_uint(doc, output, "width", item->width); yyjson_mut_obj_add_uint(doc, output, "height", item->height); + yyjson_mut_obj_add_real(doc, output, "refreshRate", item->refreshRate); yyjson_mut_val* scaled = yyjson_mut_obj_add_obj(doc, obj, "scaled"); yyjson_mut_obj_add_uint(doc, scaled, "width", item->scaledWidth); yyjson_mut_obj_add_uint(doc, scaled, "height", item->scaledHeight); + yyjson_mut_val* preferred = yyjson_mut_obj_add_obj(doc, obj, "preferred"); + yyjson_mut_obj_add_uint(doc, preferred, "width", item->preferredWidth); + yyjson_mut_obj_add_uint(doc, preferred, "height", item->preferredHeight); + yyjson_mut_obj_add_real(doc, preferred, "refreshRate", item->preferredRefreshRate); + yyjson_mut_val* physical = yyjson_mut_obj_add_obj(doc, obj, "physical"); yyjson_mut_obj_add_uint(doc, physical, "width", item->physicalWidth); yyjson_mut_obj_add_uint(doc, physical, "height", item->physicalHeight); - yyjson_mut_obj_add_real(doc, obj, "refreshRate", item->refreshRate); yyjson_mut_obj_add_uint(doc, obj, "rotation", item->rotation); yyjson_mut_obj_add_uint(doc, obj, "bitDepth", item->bitDepth); if (item->hdrStatus == FF_DISPLAY_HDR_STATUS_UNKNOWN)