From 5b064f2e7bbc28e17bff1699ec370cb57e52652b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 12 Jul 2024 15:17:42 +0800 Subject: [PATCH] Display (Linux); improve display type detection 1. assume `DP-x` is external (false possitive alert); 2. detect display type for X11 --- .../displayserver/linux/displayserver_linux.c | 18 ++++++++++++--- .../displayserver/linux/displayserver_linux.h | 2 ++ src/detection/displayserver/linux/drm.c | 4 ++-- .../displayserver/linux/wayland/kde-output.c | 5 +--- .../displayserver/linux/wayland/wayland.c | 5 +--- src/detection/displayserver/linux/xcb.c | 23 ++++++++++--------- src/detection/displayserver/linux/xlib.c | 13 ++++++----- 7 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index 14a4fd9aa..e864bdc07 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -68,7 +68,7 @@ bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName) // However I can't find a better method to get the edid data const char* drmDirPath = "/sys/class/drm/"; - DIR* dirp = opendir(drmDirPath); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); if(dirp == NULL) return false; @@ -90,13 +90,25 @@ bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName) { ffStrbufClear(edidName); ffEdidGetName(edidData, edidName); - closedir(dirp); return true; } break; } } ffStrbufClear(edidName); - closedir(dirp); return false; } + +FFDisplayType ffdsGetDisplayType(const char* name) +{ + if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-")) + return FF_DISPLAY_TYPE_BUILTIN; + else if(ffStrStartsWith(name, "HDMI-") || + ffStrStartsWith(name, "DP-") || + ffStrStartsWith(name, "DisplayPort-") || + ffStrStartsWith(name, "DVI-") || + ffStrStartsWith(name, "VGA-")) + return FF_DISPLAY_TYPE_EXTERNAL; + + return FF_DISPLAY_TYPE_UNKNOWN; +} diff --git a/src/detection/displayserver/linux/displayserver_linux.h b/src/detection/displayserver/linux/displayserver_linux.h index 4ad1928e6..c4937ee22 100644 --- a/src/detection/displayserver/linux/displayserver_linux.h +++ b/src/detection/displayserver/linux/displayserver_linux.h @@ -20,4 +20,6 @@ void ffdsConnectDrm(FFDisplayServerResult* result); void ffdsDetectWMDE(FFDisplayServerResult* result); +FFDisplayType ffdsGetDisplayType(const char* drmConnectorName); + #endif diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 8fe92c5b8..f2b7108fd 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -342,9 +342,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) 0, 0, &name, - conn->connector_type == DRM_MODE_CONNECTOR_eDP + conn->connector_type == DRM_MODE_CONNECTOR_eDP || conn->connector_type == DRM_MODE_CONNECTOR_LVDS ? FF_DISPLAY_TYPE_BUILTIN - : conn->connector_type == DRM_MODE_CONNECTOR_HDMIA || conn->connector_type == DRM_MODE_CONNECTOR_HDMIB + : conn->connector_type == DRM_MODE_CONNECTOR_HDMIA || conn->connector_type == DRM_MODE_CONNECTOR_HDMIB || conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort ? FF_DISPLAY_TYPE_EXTERNAL : FF_DISPLAY_TYPE_UNKNOWN, false, conn->connector_id, diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index 951b3aa36..558bcc433 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -108,10 +108,7 @@ static void waylandKdeGeometryListener(void *data, void waylandOutputNameListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* output, const char *name) { WaylandDisplay* display = data; - if(ffStrStartsWith(name, "eDP-")) - display->type = FF_DISPLAY_TYPE_BUILTIN; - else if(ffStrStartsWith(name, "HDMI-")) - display->type = FF_DISPLAY_TYPE_EXTERNAL; + display->type = ffdsGetDisplayType(name); strncpy((char*) &display->id, name, sizeof(display->id)); ffStrbufAppendS(&display->name, name); } diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index bfb8d366a..cbb3703e1 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -201,10 +201,7 @@ void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const WaylandDisplay* display = data; if (display->id) return; - if(ffStrStartsWith(name, "eDP-")) - display->type = FF_DISPLAY_TYPE_BUILTIN; - else if(ffStrStartsWith(name, "HDMI-")) - display->type = FF_DISPLAY_TYPE_EXTERNAL; + display->type = ffdsGetDisplayType(name); if (!display->edidName.length) ffdsMatchDrmConnector(name, &display->edidName); display->id = ffWaylandGenerateIdFromName(name); diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 2cd7f349b..6eb2bcdfb 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -177,7 +177,7 @@ typedef struct XcbRandrData xcb_randr_get_screen_resources_current_reply_t* screenResources; } XcbRandrData; -static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output) +static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) { double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); @@ -190,7 +190,7 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo (uint32_t) modeInfo->height, rotation, name, - FF_DISPLAY_TYPE_UNKNOWN, + displayType, primary, 0, (uint32_t) output->mm_width, @@ -198,7 +198,7 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo ); } -static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output) +static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) @@ -209,7 +209,7 @@ static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrb while(modesIterator.rem > 0) { if(modesIterator.data->id == mode) - return xcbRandrHandleModeInfo(data, modesIterator.data, name, rotation, primary, output); + return xcbRandrHandleModeInfo(data, modesIterator.data, name, rotation, primary, output, displayType); data->ffxcb_randr_mode_info_next(&modesIterator); } @@ -217,7 +217,7 @@ static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrb return false; } -static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output) +static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) { xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME); FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL); @@ -240,7 +240,7 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb rotation = 0; break; } - bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation, primary, output); + bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation, primary, output, displayType); res = res ? true : ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, @@ -250,7 +250,7 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb (uint32_t) crtcInfoReply->height, rotation, name, - FF_DISPLAY_TYPE_UNKNOWN, + displayType, primary, 0, (uint32_t) output->mm_width, @@ -260,7 +260,7 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb return res; } -static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary) +static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType) { xcb_randr_get_output_info_cookie_t outputInfoCookie = data->ffxcb_randr_get_output_info(data->connection, output, XCB_CURRENT_TIME); FF_AUTO_FREE xcb_randr_get_output_info_reply_t* outputInfoReply = data->ffxcb_randr_get_output_info_reply(data->connection, outputInfoCookie, NULL); @@ -283,7 +283,7 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, } } - bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply); + bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType); return res; } @@ -306,12 +306,13 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* (uint32_t) data->propData.ffxcb_get_atom_name_name_length(nameReply), data->propData.ffxcb_get_atom_name_name(nameReply) ); + const FFDisplayType displayType = ffdsGetDisplayType(name.chars); bool foundOutput = false; while(outputIterator.rem > 0) { - if(xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary)) + if(xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary, displayType)) foundOutput = true; data->ffxcb_randr_output_next(&outputIterator); }; @@ -325,7 +326,7 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* (uint32_t) monitor->height, 0, &name, - FF_DISPLAY_TYPE_UNKNOWN, + displayType, !!monitor->primary, 0, (uint32_t) monitor->width_in_millimeters, diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 10e428e95..cebbbf358 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -151,7 +151,7 @@ static double xrandrHandleMode(XrandrData* data, RRMode mode) return 0; } -static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool primary, XRROutputInfo* output) +static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool primary, XRROutputInfo* output, FFDisplayType displayType) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) @@ -187,7 +187,7 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool (uint32_t) crtcInfo->height, rotation, name, - FF_DISPLAY_TYPE_UNKNOWN, + displayType, primary, 0, (uint32_t) output->mm_width, @@ -198,7 +198,7 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool return res; } -static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary) +static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType) { XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output); if(outputInfo == NULL) @@ -222,7 +222,7 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name if (edidData) data->ffXFree(edidData); } - bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary, outputInfo); + bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary, outputInfo, displayType); data->ffXRRFreeOutputInfo(outputInfo); @@ -235,9 +235,10 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) char* xname = data->ffXGetAtomName(data->display, monitorInfo->name); FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(xname); data->ffXFree(xname); + FFDisplayType displayType = ffdsGetDisplayType(name.chars); for(int i = 0; i < monitorInfo->noutput; i++) { - if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary)) + if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary, displayType)) foundOutput = true; } @@ -250,7 +251,7 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) (uint32_t) monitorInfo->height, 0, &name, - FF_DISPLAY_TYPE_UNKNOWN, + displayType, !!monitorInfo->primary, 0, (uint32_t) monitorInfo->mwidth,