From 6c7efea2fd457afb239cb0e5c9277e55018eb61a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 11 Jul 2024 14:33:28 +0800 Subject: [PATCH 01/58] Packaging: update debian stuff [ci skip] --- debian/changelog | 12 ++++++++++++ debian/files | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index c2f63e90d2..a2f71f0e66 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +fastfetch (2.18.1) jammy; urgency=medium + + * Update to 2.18.1 + + -- Carter Li Thu, 11 Jul 2024 14:32:15 +0800 + +fastfetch (2.18.0) jammy; urgency=medium + + * Update to 2.18.0 + + -- Carter Li Wed, 10 Jul 2024 16:46:32 +0800 + fastfetch (2.17.2) jammy; urgency=medium * Update to 2.17.2 diff --git a/debian/files b/debian/files index abd2babea3..f119ff8c41 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.17.2_source.buildinfo universe/utils optional +fastfetch_2.18.1_source.buildinfo universe/utils optional From e786cd5d334ea418f7c1959407336b5042582571 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 11 Jul 2024 14:05:34 +0800 Subject: [PATCH 02/58] Display: detect physical width and height --- src/detection/displayserver/displayserver.c | 6 +- src/detection/displayserver/displayserver.h | 6 +- .../displayserver/displayserver_android.c | 11 ++- .../displayserver/displayserver_apple.c | 8 +- .../displayserver/displayserver_windows.c | 60 ++++++++++----- .../displayserver/linux/displayserver_linux.c | 2 +- src/detection/displayserver/linux/drm.c | 11 ++- .../linux/wayland/global-output.c | 10 ++- .../displayserver/linux/wayland/kde-output.c | 10 ++- .../displayserver/linux/wayland/wayland.h | 2 + .../displayserver/linux/wayland/zwlr-output.c | 13 +++- src/detection/displayserver/linux/xcb.c | 75 ++++++++----------- src/detection/displayserver/linux/xlib.c | 20 +++-- src/detection/monitor/monitor_apple.m | 7 +- src/modules/display/display.c | 11 ++- 15 files changed, 162 insertions(+), 90 deletions(-) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 12e273dc5b..d2499e3492 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -11,7 +11,9 @@ bool ffdsAppendDisplay( FFstrbuf* name, FFDisplayType type, bool primary, - uint64_t id) + uint64_t id, + uint32_t physicalWidth, + uint32_t physicalHeight) { if(width == 0 || height == 0) return false; @@ -27,6 +29,8 @@ bool ffdsAppendDisplay( display->type = type; display->primary = primary; display->id = id; + display->physicalWidth = physicalWidth; + display->physicalHeight = physicalHeight; return true; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 13c6452f63..7467ef56a7 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -60,6 +60,8 @@ typedef struct FFDisplayResult uint32_t rotation; bool primary; uint64_t id; // platform dependent + uint32_t physicalWidth; + uint32_t physicalHeight; } FFDisplayResult; typedef struct FFDisplayServerResult @@ -85,4 +87,6 @@ bool ffdsAppendDisplay( FFstrbuf* name, FFDisplayType type, bool primary, - uint64_t id); + uint64_t id, + uint32_t physicalWidth, + uint32_t physicalHeight); diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index 8d3aa20a35..a81f763b21 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -1,8 +1,9 @@ #include "displayserver.h" #include "common/settings.h" - #include "common/processing.h" +#include + static void detectWithDumpsys(FFDisplayServerResult* ds) { FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); @@ -63,6 +64,8 @@ static void detectWithDumpsys(FFDisplayServerResult* ds) &name, FF_DISPLAY_TYPE_UNKNOWN, false, + 0, + 0, 0 ); } @@ -83,6 +86,8 @@ static bool detectWithGetprop(FFDisplayServerResult* ds) uint32_t width = (uint32_t) ffStrbufToUInt(&buffer, 0); ffStrbufSubstrAfterFirstC(&buffer, ','); uint32_t height = (uint32_t) ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrAfterFirstC(&buffer, ','); + uint32_t ppi = (uint32_t) ffStrbufToUInt(&buffer, 0); return ffdsAppendDisplay(ds, width, height, @@ -93,7 +98,9 @@ static bool detectWithGetprop(FFDisplayServerResult* ds) 0, FF_DISPLAY_TYPE_BUILTIN, false, - 0 + 0, + (uint32_t) (width / ppi * 25.4), + (uint32_t) (height / ppi * 25.4) ); } diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 964a6981fe..a668ce9613 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -57,7 +57,7 @@ static void detectDisplays(FFDisplayServerResult* ds) if(CoreDisplay_IODisplayCreateInfoDictionary) { io_service_t servicePort = CGDisplayIOServicePort(screen); - CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName); + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName); if(displayInfo) { CFDictionaryRef productNames; @@ -67,6 +67,8 @@ static void detectDisplays(FFDisplayServerResult* ds) } #endif + CGSize size = CGDisplayScreenSize(screen); + ffdsAppendDisplay(ds, (uint32_t)CGDisplayModeGetPixelWidth(mode), (uint32_t)CGDisplayModeGetPixelHeight(mode), @@ -77,7 +79,9 @@ static void detectDisplays(FFDisplayServerResult* ds) &name, CGDisplayIsBuiltin(screen) ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL, CGDisplayIsMain(screen), - (uint64_t)screen + (uint64_t)screen, + (uint32_t) (size.width + 0.5), + (uint32_t) (size.height + 0.5) ); CGDisplayModeRelease(mode); } diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index c57c039921..a7774b162e 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -1,6 +1,9 @@ #include "displayserver.h" #include "detection/os/os.h" #include "util/windows/unicode.h" +#include "util/windows/registry.h" +#include "util/mallocHelper.h" +#include "util/edidHelper.h" #include #include @@ -73,6 +76,7 @@ static void detectDisplays(FFDisplayServerResult* ds) if (!monitorInfo) continue; FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + uint32_t physicalWidth = 0, physicalHeight = 0; DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = { .header = { @@ -84,13 +88,39 @@ static void detectDisplays(FFDisplayServerResult* ds) }; if(DisplayConfigGetDeviceInfo(&targetName.header) == ERROR_SUCCESS) { - if (targetName.flags.friendlyNameFromEdid) - ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName); + wchar_t regPath[256] = L"SYSTEM\\CurrentControlSet\\Enum"; + wchar_t* pRegPath = regPath + strlen("SYSTEM\\CurrentControlSet\\Enum"); + wchar_t* pDevPath = targetName.monitorDevicePath + strlen("\\\\?"); + while (*pDevPath && *pDevPath != L'{') + { + if (*pDevPath == L'#') + *pRegPath = L'\\'; + else + *pRegPath = *pDevPath; + ++pRegPath; + ++pDevPath; + assert(pRegPath < regPath + sizeof(regPath) / sizeof(wchar_t) + strlen("Device Parameters")); + } + wcscpy(pRegPath, L"Device Parameters"); + + uint8_t edidData[1024]; + DWORD edidLength = sizeof(edidData); + if (RegGetValueW(HKEY_LOCAL_MACHINE, regPath, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidLength) == ERROR_SUCCESS && + edidLength > 0 && edidLength % 128 == 0) + { + ffEdidGetName(edidData, &name); + ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); + } else { - ffStrbufSetWS(&name, targetName.monitorDevicePath); - ffStrbufSubstrAfterFirstC(&name, '#'); - ffStrbufSubstrBeforeFirstC(&name, '#'); + if (targetName.flags.friendlyNameFromEdid) + ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName); + else + { + ffStrbufSetWS(&name, targetName.monitorDevicePath); + ffStrbufSubstrAfterFirstC(&name, '#'); + ffStrbufSubstrBeforeFirstC(&name, '#'); + } } } @@ -107,18 +137,10 @@ static void detectDisplays(FFDisplayServerResult* ds) uint32_t rotation; switch (path->targetInfo.rotation) { - case DISPLAYCONFIG_ROTATION_ROTATE90: - rotation = 90; - break; - case DISPLAYCONFIG_ROTATION_ROTATE180: - rotation = 180; - break; - case DISPLAYCONFIG_ROTATION_ROTATE270: - rotation = 270; - break; - default: - rotation = 0; - break; + case DISPLAYCONFIG_ROTATION_ROTATE90: rotation = 90; break; + case DISPLAYCONFIG_ROTATION_ROTATE180: rotation = 180; break; + case DISPLAYCONFIG_ROTATION_ROTATE270: rotation = 270; break; + default: rotation = 0; break; } ffdsAppendDisplay(ds, @@ -135,7 +157,9 @@ static void detectDisplays(FFDisplayServerResult* ds) path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL, !!(monitorInfo->info.dwFlags & MONITORINFOF_PRIMARY), - (uint64_t)(uintptr_t) monitorInfo->handle + (uint64_t)(uintptr_t) monitorInfo->handle, + physicalWidth, + physicalHeight ); } } diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index 807facd9ec..14a4fd9aa8 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -50,7 +50,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) if (ffSettingsGetFreeBSDKenv("screen.height", &buf)) { uint32_t height = (uint32_t) ffStrbufToUInt(&buf, 0); - ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0); + ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0, 0, 0); } } } diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index eb8d09847a..8fe92c5b86 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -37,7 +37,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) continue; } - unsigned width = 0, height = 0; + unsigned width = 0, height = 0, physicalWidth = 0, physicalHeight = 0; double refreshRate = 0; FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); @@ -49,6 +49,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) { ffEdidGetName(edidData, &name); ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate); + ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); } else { @@ -78,7 +79,9 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) &name, FF_DISPLAY_TYPE_UNKNOWN, false, - 0 + 0, + physicalWidth, + physicalHeight ); ffStrbufSubstrBefore(&drmDir, drmDirLength); @@ -344,7 +347,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) : conn->connector_type == DRM_MODE_CONNECTOR_HDMIA || conn->connector_type == DRM_MODE_CONNECTOR_HDMIB ? FF_DISPLAY_TYPE_EXTERNAL : FF_DISPLAY_TYPE_UNKNOWN, false, - conn->connector_id + conn->connector_id, + conn->mmWidth, + conn->mmHeight ); } diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index 8d868ea756..e318fc0db1 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -25,14 +25,16 @@ static void waylandOutputGeometryListener(void *data, FF_MAYBE_UNUSED struct wl_output *output, FF_MAYBE_UNUSED int32_t x, FF_MAYBE_UNUSED int32_t y, - FF_MAYBE_UNUSED int32_t physical_width, - FF_MAYBE_UNUSED int32_t physical_height, + int32_t physical_width, + int32_t physical_height, FF_MAYBE_UNUSED int32_t subpixel, FF_MAYBE_UNUSED const char *make, FF_MAYBE_UNUSED const char *model, int32_t transform) { WaylandDisplay* display = data; + display->physicalWidth = physical_width; + display->physicalHeight = physical_height; display->transform = (enum wl_output_transform) transform; } @@ -156,7 +158,9 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist : &display.name, display.type, false, - display.id + display.id, + (uint32_t) display.physicalWidth, + (uint32_t) display.physicalHeight ); ffStrbufDestroy(&display.description); diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index 8d7ab51abe..951b3aa367 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -92,14 +92,16 @@ static void waylandKdeGeometryListener(void *data, FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2, FF_MAYBE_UNUSED int32_t x, FF_MAYBE_UNUSED int32_t y, - FF_MAYBE_UNUSED int32_t physical_width, - FF_MAYBE_UNUSED int32_t physical_height, + int32_t physical_width, + int32_t physical_height, FF_MAYBE_UNUSED int32_t subpixel, FF_MAYBE_UNUSED const char *make, FF_MAYBE_UNUSED const char *model, int32_t transform) { WaylandDisplay* display = data; + display->physicalWidth = physical_width; + display->physicalHeight = physical_height; display->transform = (enum wl_output_transform) transform; } @@ -215,7 +217,9 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, : &display.name, display.type, false, - display.id + display.id, + (uint32_t) display.physicalWidth, + (uint32_t) display.physicalHeight ); ffStrbufDestroy(&display.description); diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index 21f1979c39..025b0b299b 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -36,6 +36,8 @@ typedef struct WaylandDisplay WaylandData* parent; int32_t width; int32_t height; + int32_t physicalWidth; + int32_t physicalHeight; int32_t refreshRate; double scale; enum wl_output_transform transform; diff --git a/src/detection/displayserver/linux/wayland/zwlr-output.c b/src/detection/displayserver/linux/wayland/zwlr-output.c index 861d7dc2ec..dd9b832892 100644 --- a/src/detection/displayserver/linux/wayland/zwlr-output.c +++ b/src/detection/displayserver/linux/wayland/zwlr-output.c @@ -71,10 +71,17 @@ static void waylandZwlrCurrentModeListener(void* data, FF_MAYBE_UNUSED struct zw 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) +{ + WaylandDisplay* wldata = (WaylandDisplay*) data; + wldata->physicalWidth = width; + wldata->physicalHeight = height; +} + static const struct zwlr_output_head_v1_listener headListener = { .name = (void*) ffWaylandOutputNameListener, .description = (void*) ffWaylandOutputDescriptionListener, - .physical_size = (void*) stubListener, + .physical_size = waylandZwlrPhysicalSizeListener, .mode = waylandZwlrModeListener, .enabled = (void*) stubListener, .current_mode = waylandZwlrCurrentModeListener, @@ -160,7 +167,9 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output : &display.name, display.type, false, - display.id + display.id, + (uint32_t) display.physicalWidth, + (uint32_t) display.physicalHeight ); ffStrbufDestroy(&display.description); diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index c4c4b1551b..2cd7f349b1 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -41,32 +41,25 @@ static bool xcbInitPropertyData(void* libraryHandle, XcbPropertyData* propertyDa static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t window, const char* request) { xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(connection, true, (uint16_t) strlen(request), request); - xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(connection, requestAtomCookie, NULL); + FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(connection, requestAtomCookie, NULL); if(requestAtomReply == NULL) return NULL; xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 64); - free(requestAtomReply); - - xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(connection, propertyCookie, NULL); + FF_AUTO_FREE xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(connection, propertyCookie, NULL); if(propertyReply == NULL) return NULL; int length = data->ffxcb_get_property_value_length(propertyReply); if(length <= 0) - { - free(propertyReply); return NULL; - } //Why are xcb property strings not null terminated??? void* replyValue = malloc((size_t)length + 1); memcpy(replyValue, data->ffxcb_get_property_value(propertyReply), (size_t) length); ((char*) replyValue)[length] = '\0'; - free(propertyReply); - return replyValue; } @@ -75,28 +68,18 @@ static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connect if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0) return; - xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK"); + FF_AUTO_FREE xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK"); if(wmWindow == NULL) return; - char* wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "_NET_WM_NAME"); + FF_AUTO_FREE char* wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "_NET_WM_NAME"); if(wmName == NULL) wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "WM_NAME"); - free(wmWindow); - - if(wmName == NULL) + if(wmName == NULL || *wmName == '\0') return; - if(*wmName == '\0') - { - free(wmName); - return; - } - ffStrbufSetS(&result->wmProcessName, wmName); - - free(wmName); } void ffdsConnectXcb(FFDisplayServerResult* result) @@ -122,17 +105,20 @@ void ffdsConnectXcb(FFDisplayServerResult* result) while(iterator.rem > 0) { + xcb_screen_t* screen = iterator.data; ffdsAppendDisplay(result, - (uint32_t) iterator.data->width_in_pixels, - (uint32_t) iterator.data->height_in_pixels, + (uint32_t) screen->width_in_pixels, + (uint32_t) screen->height_in_pixels, 0, - (uint32_t) iterator.data->width_in_pixels, - (uint32_t) iterator.data->height_in_pixels, + (uint32_t) screen->width_in_pixels, + (uint32_t) screen->height_in_pixels, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, - 0 + 0, + (uint32_t) screen->width_in_millimeters, + (uint32_t) screen->height_in_millimeters ); ffxcb_screen_next(&iterator); } @@ -191,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) +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) { double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); @@ -206,11 +192,13 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo name, FF_DISPLAY_TYPE_UNKNOWN, primary, - 0 + 0, + (uint32_t) output->mm_width, + (uint32_t) output->mm_height ); } -static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrbuf* name, uint32_t rotation, bool primary) +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) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) @@ -221,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); + return xcbRandrHandleModeInfo(data, modesIterator.data, name, rotation, primary, output); data->ffxcb_randr_mode_info_next(&modesIterator); } @@ -229,10 +217,10 @@ 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) +static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output) { xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME); - xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL); + FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL); if(crtcInfoReply == NULL) return false; @@ -252,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); + bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation, primary, output); res = res ? true : ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, @@ -264,10 +252,11 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb name, FF_DISPLAY_TYPE_UNKNOWN, primary, - 0 + 0, + (uint32_t) output->mm_width, + (uint32_t) output->mm_height ); - free(crtcInfoReply); return res; } @@ -294,7 +283,7 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, } } - bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary); + bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply); return res; } @@ -338,14 +327,16 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* &name, FF_DISPLAY_TYPE_UNKNOWN, !!monitor->primary, - 0 + 0, + (uint32_t) monitor->width_in_millimeters, + (uint32_t) monitor->height_in_millimeters ); } static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen) { xcb_randr_get_monitors_cookie_t monitorsCookie = data->ffxcb_randr_get_monitors(data->connection, screen->root, true); - xcb_randr_get_monitors_reply_t* monitorsReply = data->ffxcb_randr_get_monitors_reply(data->connection, monitorsCookie, NULL); + FF_AUTO_FREE xcb_randr_get_monitors_reply_t* monitorsReply = data->ffxcb_randr_get_monitors_reply(data->connection, monitorsCookie, NULL); if(monitorsReply == NULL) return false; @@ -360,8 +351,6 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen) data->ffxcb_randr_monitor_info_next(&monitorInfoIterator); } - free(monitorsReply); - return foundMonitor; } @@ -392,7 +381,9 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) NULL, FF_DISPLAY_TYPE_UNKNOWN, false, - 0 + 0, + (uint32_t) screen->width_in_millimeters, + (uint32_t) screen->height_in_millimeters ); } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 567cdd25be..10e428e95c 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -87,7 +87,9 @@ void ffdsConnectXlib(FFDisplayServerResult* result) NULL, FF_DISPLAY_TYPE_UNKNOWN, false, - 0 + 0, + (uint32_t) WidthMMOfScreen(screen), + (uint32_t) HeightMMOfScreen(screen) ); } @@ -149,7 +151,7 @@ static double xrandrHandleMode(XrandrData* data, RRMode mode) return 0; } -static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool primary) +static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool primary, XRROutputInfo* output) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) @@ -187,7 +189,9 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool name, FF_DISPLAY_TYPE_UNKNOWN, primary, - 0 + 0, + (uint32_t) output->mm_width, + (uint32_t) output->mm_height ); data->ffXRRFreeCrtcInfo(crtcInfo); @@ -218,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); + bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary, outputInfo); data->ffXRRFreeOutputInfo(outputInfo); @@ -248,7 +252,9 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) &name, FF_DISPLAY_TYPE_UNKNOWN, !!monitorInfo->primary, - 0 + 0, + (uint32_t) monitorInfo->mwidth, + (uint32_t) monitorInfo->mheight ); } @@ -296,7 +302,9 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) NULL, FF_DISPLAY_TYPE_UNKNOWN, false, - 0 + 0, + (uint32_t) WidthMMOfScreen(screen), + (uint32_t) HeightMMOfScreen(screen) ); } diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 31b7ab9e32..8d99e5c11a 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -19,7 +19,7 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) NSScreen* mainScreen = NSScreen.mainScreen; if (display->primary) { - #ifdef MAC_OS_X_VERSION_10_15 + #ifdef MAC_OS_X_VERSION_10_15 return mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; #else return mainScreen.maximumExtendedDynamicRangeColorComponentValue > 1; @@ -100,10 +100,9 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) monitor->physicalHeight = (uint32_t) (size.height + 0.5); monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || detectHdrSupportWithNSScreen(display); + monitor->serial = CGDisplaySerialNumber((CGDirectDisplayID) display->id); - int64_t serial, year, week; - if (ffCfDictGetInt64(displayInfo, CFSTR("DisplaySerialNumber"), &serial) == NULL) - monitor->serial = (uint32_t) (uint64_t) serial; + int64_t year, week; if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayYearManufacture"), &year) == NULL) monitor->manufactureYear = (uint16_t) year; if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayWeekManufacture"), &week) == NULL) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 008f4ce666..dcfc6fad88 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -4,7 +4,7 @@ #include "modules/display/display.h" #include "util/stringUtils.h" -#define FF_DISPLAY_NUM_FORMAT_ARGS 9 +#define FF_DISPLAY_NUM_FORMAT_ARGS 11 static int sortByNameAsc(FFDisplayResult* a, FFDisplayResult* b) { @@ -135,6 +135,8 @@ void ffPrintDisplay(FFDisplayOptions* options) {FF_FORMAT_ARG_TYPE_STRING, displayType, "type"}, {FF_FORMAT_ARG_TYPE_UINT, &result->rotation, "rotation"}, {FF_FORMAT_ARG_TYPE_BOOL, &result->primary, "is-primary"}, + {FF_FORMAT_ARG_TYPE_UINT, &result->physicalWidth, "physical-width"}, + {FF_FORMAT_ARG_TYPE_UINT, &result->physicalHeight, "physical-height"}, })); } } @@ -291,8 +293,11 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_bool(doc, obj, "primary", item->primary); 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, "scaledHeight", item->scaledHeight); yyjson_mut_obj_add_uint(doc, obj, "scaledWidth", item->scaledWidth); + yyjson_mut_obj_add_uint(doc, obj, "scaledHeight", item->scaledHeight); + yyjson_mut_obj_add_uint(doc, obj, "physicalWidth", item->physicalWidth); + yyjson_mut_obj_add_uint(doc, obj, "physicalHeight", item->physicalHeight); + switch (item->type) { case FF_DISPLAY_TYPE_BUILTIN: @@ -320,6 +325,8 @@ void ffPrintDisplayHelpFormat(void) "Screen type (builtin, external or unknown) - type", "Screen rotation (in degrees) - rotation", "True if being the primary screen - is-primary", + "Screen physical width (in millimeters) - physical-width", + "Screen physical height (in millimeters) - physical-height", })); } From 5b064f2e7bbc28e17bff1699ec370cb57e52652b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 12 Jul 2024 15:17:42 +0800 Subject: [PATCH 03/58] 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 14a4fd9aa8..e864bdc07a 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 4ad1928e60..c4937ee227 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 8fe92c5b86..f2b7108fd7 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 951b3aa367..558bcc433e 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 bfb8d366a8..cbb3703e13 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 2cd7f349b1..6eb2bcdfbd 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 10e428e95c..cebbbf358e 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, From 7d452cc4602a1add9709c85b3ef1f5cfebd0cd7c Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 12 Jul 2024 18:47:00 +0800 Subject: [PATCH 04/58] Presets: fix examples/19.jsonc Fix #1090 --- presets/examples/19.jsonc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presets/examples/19.jsonc b/presets/examples/19.jsonc index a84a24f326..17db60c262 100644 --- a/presets/examples/19.jsonc +++ b/presets/examples/19.jsonc @@ -12,7 +12,7 @@ "logo": { "source": " _____ _____ _____ _____ _____ _____ _____ _____ _____\n| __| _ | __|_ _| __| __|_ _| | | |\n| __| |__ | | | | __| __| | | | --| |\n|__| |__|__|_____| |_| |__| |_____| |_| |_____|__|__|", "type": "data", - "separate": true, + "position": "top", "padding": { "right": 2 } From 2f42d64dc9bf16870b378d61964e3e42f381ff7a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 12 Jul 2024 19:24:55 +0800 Subject: [PATCH 05/58] GPU (Linux): support intel xe driver --- src/detection/gpu/gpu_linux.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 33759a8ca1..e27a3e3cec 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -133,17 +133,24 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* ffStrbufSubstrAfter(&gpu->name, (uint32_t) strlen("Intel ")); gpu->type = ffStrbufStartsWithIgnCaseS(&gpu->name, "Arc ") ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - ffStrbufAppendS(pciDir, "/drm/"); - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars); - if (!dirp) return; - struct dirent* entry; - while ((entry = readdir(dirp)) != NULL) + if (ffStrbufEqualS(&gpu->driver, "xe")) { - if (ffStrStartsWith(entry->d_name, "card")) break; + ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq"); + } + else + { + ffStrbufAppendS(pciDir, "/drm/"); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars); + if (!dirp) return; + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (ffStrStartsWith(entry->d_name, "card")) break; + } + if (!entry) return; + ffStrbufAppendS(pciDir, entry->d_name); + ffStrbufAppendS(pciDir, "/gt_max_freq_mhz"); } - if (!entry) return; - ffStrbufAppendS(pciDir, entry->d_name); - ffStrbufAppendS(pciDir, "/gt_max_freq_mhz"); if (ffReadFileBuffer(pciDir->chars, buffer)) gpu->frequency = ffStrbufToDouble(buffer) / 1000.0; } From beabaa90f13e7b95c7f6facab2dfc0a5766d6f67 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 12 Jul 2024 19:44:15 +0800 Subject: [PATCH 06/58] InitSystem (Android): fix detection --- src/detection/initsystem/initsystem_linux.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/detection/initsystem/initsystem_linux.c b/src/detection/initsystem/initsystem_linux.c index 9a6023a1cb..d5fa8452ab 100644 --- a/src/detection/initsystem/initsystem_linux.c +++ b/src/detection/initsystem/initsystem_linux.c @@ -1,10 +1,22 @@ #include "initsystem.h" #include "common/processing.h" +#include const char* ffDetectInitSystem(FFInitSystemResult* result) { const char* error = ffProcessGetBasicInfoLinux((int) result->pid, &result->name, NULL, NULL); - if (error) return error; + if (error) + { + #ifdef __ANDROID__ + if (access("/system/bin/init", F_OK) == 0) + { + ffStrbufSetStatic(&result->exe, "/system/bin/init"); + ffStrbufSetStatic(&result->name, "init"); + return NULL; + } + #endif + return error; + } const char* _; // In linux /proc/1/exe is not readable From 7eaefe163a8a617eafc2beefc31ebea347375ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 15 Jul 2024 10:05:35 +0800 Subject: [PATCH 07/58] TerminalFont (Linux): improve detection for xterm Fix #1095 --- src/common/properties.c | 12 ++++-------- src/common/properties.h | 8 +++++++- src/detection/terminalshell/terminalshell.c | 14 +++++++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/common/properties.c b/src/common/properties.c index f45c9928c2..fbf11416ef 100644 --- a/src/common/properties.c +++ b/src/common/properties.c @@ -4,11 +4,12 @@ #include "util/mallocHelper.h" #include +#include #ifdef _WIN32 #include "util/windows/getline.h" #endif -static bool parsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer) +bool ffParsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer) { if(**line == '\0') return false; @@ -32,7 +33,7 @@ static bool parsePropLinePointer(const char** line, const char* start, FFstrbuf* } //Line doesn't match start, skip it - if(**line != *start || **line == '\0') + if(tolower(**line) != tolower(*start) || **line == '\0') return false; //Line and start match, continue testing @@ -69,14 +70,9 @@ static bool parsePropLinePointer(const char** line, const char* start, FFstrbuf* return true; } -bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer) -{ - return parsePropLinePointer(&line, start, buffer); -} - bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer) { - while(!parsePropLinePointer(&lines, start, buffer)) + while(!ffParsePropLinePointer(&lines, start, buffer)) { while(*lines != '\0' && *lines != '\n') ++lines; diff --git a/src/common/properties.h b/src/common/properties.h index 69ea5ddf4f..9cc9ff34ff 100644 --- a/src/common/properties.h +++ b/src/common/properties.h @@ -8,12 +8,18 @@ typedef struct FFpropquery FFstrbuf* buffer; } FFpropquery; -bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer); bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer); bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries); bool ffParsePropFileHomeValues(const char* relativeFile, uint32_t numQueries, FFpropquery* queries); bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries); +bool ffParsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer); + +static inline bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer) +{ + return ffParsePropLinePointer(&line, start, buffer); +} + static inline bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer) { return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}}); diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index f125523ec2..2bc80b56b5 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -352,11 +352,15 @@ FF_MAYBE_UNUSED static bool getTerminalVersionCockpit(FFstrbuf* exe, FFstrbuf* v FF_MAYBE_UNUSED static bool getTerminalVersionXterm(FFstrbuf* exe, FFstrbuf* version) { - if(ffProcessAppendStdOut(version, (char* const[]){ - exe->chars, - "-v", - NULL - })) return false; + ffStrbufSetS(version, getenv("XTERM_VERSION")); + if (!version->length) + { + if(ffProcessAppendStdOut(version, (char* const[]){ + exe->chars, + "-v", + NULL + })) return false; + } //xterm(273) ffStrbufTrimRight(version, ')'); From 64c53e2cdc5e3a6c96f9fcf268fee0c5412182d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 15 Jul 2024 10:05:35 +0800 Subject: [PATCH 08/58] TerminalFont (Linux): improve detection for xterm Fix #1095 --- src/common/properties.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/properties.c b/src/common/properties.c index fbf11416ef..dd717c0a84 100644 --- a/src/common/properties.c +++ b/src/common/properties.c @@ -59,7 +59,7 @@ bool ffParsePropLinePointer(const char** line, const char* start, FFstrbuf* buff } //Copy the value to the buffer - while(**line != valueEnd && **line != '\n' && **line != '\0') + while(tolower(**line) != tolower(valueEnd) && **line != '\n' && **line != '\0') { ffStrbufAppendC(buffer, **line); ++(*line); From 1947aa2b0e402b2200da9628436dd95c78f9203c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 15 Jul 2024 11:00:15 +0800 Subject: [PATCH 09/58] Formating: support specifying costant strings --- doc/json_schema.json | 7 +++++++ src/common/format.c | 21 +++++++++++++++++++++ src/options/display.c | 14 ++++++++++++++ src/options/display.h | 1 + 4 files changed, 43 insertions(+) diff --git a/doc/json_schema.json b/doc/json_schema.json index df76141ece..870bea4218 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -578,6 +578,13 @@ "type": "boolean", "description": "Whether to disable the stdout application buffer", "default": false + }, + "constants": { + "type": "array", + "description": "List of strings to be used in custom format of modules", + "items": { + "type": "string" + } } } }, diff --git a/src/common/format.c b/src/common/format.c index 5d1938a0d6..f6b9b562f5 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -244,6 +244,27 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n continue; } + //test for constant, if so evaluate it + if (firstChar == '$') + { + char* pend = NULL; + int32_t indexSigned = (int32_t) strtol(placeholderValue.chars + 1, &pend, 10); + uint32_t index = (uint32_t) indexSigned; + bool backward = indexSigned < 0; + + if (indexSigned == 0 || *pend != '\0' || instance.config.display.constants.length < index) + { + appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length); + continue; + } + + FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, backward + ? instance.config.display.constants.length - index + : index - 1); + ffStrbufAppend(buffer, item); + continue; + } + int32_t truncLength = INT32_MAX; char* pColon = memchr(placeholderValue.chars, ':', placeholderValue.length); if (pColon != NULL) diff --git a/src/options/display.c b/src/options/display.c index 23fb3273ce..c0917b1151 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -199,6 +199,15 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va options->noBuffer = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "keyWidth")) options->keyWidth = (uint32_t) yyjson_get_uint(val); + else if (ffStrEqualsIgnCase(key, "constants")) + { + if (!yyjson_is_arr(val)) + return "display.constants must be an array"; + yyjson_val* item; + size_t idx, max; + yyjson_arr_foreach(val, idx, max, item) + ffStrbufInitS(ffListAdd(&options->constants), yyjson_get_str(item)); + } else if (ffStrEqualsIgnCase(key, "tsVersion")) return "display.tsVersion has been renamed to general.detectVersion"; else @@ -404,6 +413,8 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) ffStrbufInitStatic(&options->percentColorGreen, FF_COLOR_FG_GREEN); ffStrbufInitStatic(&options->percentColorYellow, instance.state.terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW); ffStrbufInitStatic(&options->percentColorRed, instance.state.terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED); + + ffListInit(&options->constants, sizeof(FFstrbuf)); } void ffOptionsDestroyDisplay(FFOptionsDisplay* options) @@ -415,6 +426,9 @@ void ffOptionsDestroyDisplay(FFOptionsDisplay* options) ffStrbufDestroy(&options->keyValueSeparator); ffStrbufDestroy(&options->barCharElapsed); ffStrbufDestroy(&options->barCharTotal); + FF_LIST_FOR_EACH(FFstrbuf, item, options->constants) + ffStrbufDestroy(item); + ffListDestroy(&options->constants); } void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_doc* doc) diff --git a/src/options/display.h b/src/options/display.h index a3be9baf83..ba0707e907 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -53,6 +53,7 @@ typedef struct FFOptionsDisplay FFstrbuf percentColorRed; bool noBuffer; uint32_t keyWidth; + FFlist constants; // list of FFstrbuf } FFOptionsDisplay; const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root); From 179341c30ce92395f87389dc01dee1319d31ebd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 15 Jul 2024 14:01:35 +0800 Subject: [PATCH 10/58] Presets: clean up examples --- presets/examples/10.jsonc | 13 ++++++++----- presets/examples/12.jsonc | 9 ++++++--- presets/examples/13.jsonc | 27 +++++++++++++------------- presets/examples/15.jsonc | 27 +++++++++++++------------- presets/examples/17.jsonc | 36 +++++++++++++++++++--------------- presets/examples/18.jsonc | 36 +++++++++++++++++++--------------- presets/examples/2.jsonc | 13 ++++++++----- presets/examples/20.jsonc | 41 +++++++++++++++++++++------------------ presets/examples/21.jsonc | 19 +++++++++++------- presets/examples/22.jsonc | 11 +++++++---- presets/examples/3.jsonc | 4 +++- presets/examples/4.jsonc | 2 +- presets/examples/5.jsonc | 2 +- presets/examples/6.jsonc | 8 +------- 14 files changed, 135 insertions(+), 113 deletions(-) diff --git a/presets/examples/10.jsonc b/presets/examples/10.jsonc index 50da238899..14f92079d0 100644 --- a/presets/examples/10.jsonc +++ b/presets/examples/10.jsonc @@ -9,12 +9,15 @@ } }, "display": { - "separator": " -> " + "separator": " -> ", + "constants": [ + "──────────────────────────────" + ] }, "modules": [ { "type": "custom", - "format": "┌────────────────────────────────────────────────────────────┐", + "format": "┌{$1}{$1}┐", "outputColor": "90" }, { @@ -23,7 +26,7 @@ }, { "type": "custom", - "format": "└────────────────────────────────────────────────────────────┘", + "format": "└{$1}{$1}┘", "outputColor": "90" }, { @@ -32,7 +35,7 @@ }, { "type": "custom", - "format": "┌────────────────────────────────────────────────────────────┐", + "format": "┌{$1}{$1}┐", "outputColor": "90" }, { @@ -142,7 +145,7 @@ }, { "type": "custom", - "format": "└────────────────────────────────────────────────────────────┘", + "format": "└{$1}{$1}┘", "outputColor": "90" }, "break", diff --git a/presets/examples/12.jsonc b/presets/examples/12.jsonc index 4851597318..5cc705b9d9 100644 --- a/presets/examples/12.jsonc +++ b/presets/examples/12.jsonc @@ -7,7 +7,10 @@ "separator": "-> ", "color": { "separator": "1" - } + }, + "constants": [ + "─────────────────────────────" + ] }, "modules": [ { @@ -17,7 +20,7 @@ "break", { "type": "custom", - "format": "┌───────────────────────────── {#1}System Information{#} ─────────────────────────────┐" + "format": "┌{$1} {#1}System Information{#} {$1}┐" }, "break", { @@ -95,7 +98,7 @@ "break", { "type": "custom", - "format": "└──────────────────────────────────────────────────────────────────────────────┘" + "format": "└{$1}────────────────────{$1}┘" }, "break", { diff --git a/presets/examples/13.jsonc b/presets/examples/13.jsonc index 84b115be51..e4f7c534ff 100644 --- a/presets/examples/13.jsonc +++ b/presets/examples/13.jsonc @@ -17,56 +17,55 @@ "type": "custom" }, { - // draw borders first to make colors of left and right border consistant - "key": "│ │\u001b[11D{#31} user", + "key": "│ {#31} user {#keys}│", "type": "title", "format": "{1}" }, { - "key": "│ │\u001b[11D{#32}󰇅 hname", + "key": "│ {#32}󰇅 hname {#keys}│", "type": "title", "format": "{2}" }, { - "key": "│ │\u001b[11D{#33}󰅐 uptime", + "key": "│ {#33}󰅐 uptime {#keys}│", "type": "uptime" }, { - "key": "│ │\u001b[11D{#34}󰟾 distro", + "key": "│ {#34}󰟾 distro {#keys}│", "type": "os" }, { - "key": "│ │\u001b[11D{#35} kernel", + "key": "│ {#35} kernel {#keys}│", "type": "kernel" }, { - "key": "│ │\u001b[11D{#36}󰇄 desktop", + "key": "│ {#36}󰇄 desktop {#keys}│", "type": "de" }, { - "key": "│ │\u001b[11D{#31} term", + "key": "│ {#31} term {#keys}│", "type": "terminal" }, { - "key": "│ │\u001b[11D{#32} shell", + "key": "│ {#32} shell {#keys}│", "type": "shell" }, { - "key": "│ │\u001b[11D{#33}󰍛 cpu", + "key": "│ {#33}󰍛 cpu {#keys}│", "type": "cpu", "showPeCoreCount": true }, { - "key": "│ │\u001b[11D{#34}󰉉 disk", + "key": "│ {#34}󰉉 disk {#keys}│", "type": "disk", "folders": "/" }, { - "key": "│ │\u001b[11D{#35} memory", + "key": "│ {#35} memory {#keys}│", "type": "memory" }, { - "key": "│ │\u001b[11D{#36}󰩟 network", + "key": "│ {#36}󰩟 network {#keys}│", "type": "localip", "format": "{1} ({4})" }, @@ -75,7 +74,7 @@ "type": "custom" }, { - "key": "│ │\u001b[11D{#39} colors", + "key": "│ {#39} colors {#keys}│", "type": "colors", "symbol": "circle" }, diff --git a/presets/examples/15.jsonc b/presets/examples/15.jsonc index 1c849cec88..665f048a31 100644 --- a/presets/examples/15.jsonc +++ b/presets/examples/15.jsonc @@ -17,56 +17,55 @@ "type": "custom" }, { - // draw borders first to make colors of left and right border consistant - "key": "• •\u001b[11D{#31} user", + "key": "• {#31} user {#keys}•", "type": "title", "format": "{1}" }, { - "key": "• •\u001b[11D{#32}󰇅 hname", + "key": "• {#32}󰇅 hname {#keys}•", "type": "title", "format": "{2}" }, { - "key": "• •\u001b[11D{#33}󰅐 uptime", + "key": "• {#33}󰅐 uptime {#keys}•", "type": "uptime" }, { - "key": "• •\u001b[11D{#34}󰟾 distro", + "key": "• {#34}󰟾 distro {#keys}•", "type": "os" }, { - "key": "• •\u001b[11D{#35} kernel", + "key": "• {#35} kernel {#keys}•", "type": "kernel" }, { - "key": "• •\u001b[11D{#36}󰇄 desktop", + "key": "• {#36}󰇄 desktop {#keys}•", "type": "de" }, { - "key": "• •\u001b[11D{#31} term", + "key": "• {#31} term {#keys}•", "type": "terminal" }, { - "key": "• •\u001b[11D{#32} shell", + "key": "• {#32} shell {#keys}•", "type": "shell" }, { - "key": "• •\u001b[11D{#33}󰍛 cpu", + "key": "• {#33}󰍛 cpu {#keys}•", "type": "cpu", "showPeCoreCount": true }, { - "key": "• •\u001b[11D{#34}󰉉 disk", + "key": "• {#34}󰉉 disk {#keys}•", "type": "disk", "folders": "/" }, { - "key": "• •\u001b[11D{#35} memory", + "key": "• {#35} memory {#keys}•", "type": "memory" }, { - "key": "• •\u001b[11D{#36}󰩟 network", + "key": "• {#36}󰩟 network {#keys}•", "type": "localip", "format": "{1} ({4})" }, @@ -75,7 +74,7 @@ "type": "custom" }, { - "key": "• •\u001b[11D{#39} colors", + "key": "• {#39} colors {#keys}•", "type": "colors", "symbol": "circle" }, diff --git a/presets/examples/17.jsonc b/presets/examples/17.jsonc index 13f8f22e43..b72d872809 100644 --- a/presets/examples/17.jsonc +++ b/presets/examples/17.jsonc @@ -11,72 +11,76 @@ "separator": "> ", "color": { "separator": "red" - } + }, + "constants": [ + "───────────────────────────────────────────────────────────────────────────", + "│\u001b[75C│\u001b[75D" + ] }, "modules": [ { - "format": "{#1}{#keys}╭───────────────────────────────────────────────────────────────────────────╮\u001b[76D {6}{7}{8} 🖥 ", + "format": "{#1}{#keys}╭{$1}╮\u001b[76D {6}{7}{8} 🖥 ", "type": "title" }, { - "key": "│\u001b[75C│\u001b[75D{#31} kernel ", + "key": "{$2}{#31} kernel ", "type": "kernel" }, { - "key": "│\u001b[75C│\u001b[75D{#32}󰅐 uptime ", + "key": "{$2}{#32}󰅐 uptime ", "type": "uptime" }, { - "key": "│\u001b[75C│\u001b[75D{#33}󰟾 distro ", + "key": "{$2}{#33}󰟾 distro ", "type": "os" }, { - "key": "│\u001b[75C│\u001b[75D{#34}󰇄 desktop ", + "key": "{$2}{#34}󰇄 desktop ", "type": "de" }, { - "key": "│\u001b[75C│\u001b[75D{#35} term ", + "key": "{$2}{#35} term ", "type": "terminal" }, { - "key": "│\u001b[75C│\u001b[75D{#36} shell ", + "key": "{$2}{#36} shell ", "type": "shell" }, { - "key": "│\u001b[75C│\u001b[75D{#35}󰍛 cpu ", + "key": "{$2}{#35}󰍛 cpu ", "type": "cpu", "showPeCoreCount": true, "temp": true }, { - "key": "│\u001b[75C│\u001b[75D{#34}󰍛 gpu ", + "key": "{$2}{#34}󰍛 gpu ", "type": "gpu" }, { - "key": "│\u001b[75C│\u001b[75D{#33}󰉉 disk ", + "key": "{$2}{#33}󰉉 disk ", "type": "disk", "folders": "/" }, { - "key": "│\u001b[75C│\u001b[75D{#32} memory ", + "key": "{$2}{#32} memory ", "type": "memory" }, { - "key": "│\u001b[75C│\u001b[75D{#31}󰩟 network ", + "key": "{$2}{#31}󰩟 network ", "type": "localip", "format": "{1} ({4})" }, { - "format": "{#1}{#keys}├───────────────────────────────────────────────────────────────────────────┤", + "format": "{#1}{#keys}├{$1}┤", "type": "custom" }, { - "key": "│\u001b[75C│\u001b[75D{#39} colors ", + "key": "{$2}{#39} colors ", "type": "colors", "symbol": "circle" }, { - "format": "{#1}{#keys}╰───────────────────────────────────────────────────────────────────────────╯", + "format": "{#1}{#keys}╰{$1}╯", "type": "custom" } ] diff --git a/presets/examples/18.jsonc b/presets/examples/18.jsonc index 28af28c2a8..9ee4c38545 100644 --- a/presets/examples/18.jsonc +++ b/presets/examples/18.jsonc @@ -11,72 +11,76 @@ "separator": "> ", "color": { "separator": "red" - } + }, + "constants": [ + "═══════════════════════════════════════════════════════════════════════════", + "║\u001b[75C║\u001b[75D" + ] }, "modules": [ { - "format": "{#1}{#keys}╔═══════════════════════════════════════════════════════════════════════════╗\u001b[76D {6}{7}{8} 💻 ", + "format": "{#1}{#keys}╔{$1}╗\u001b[76D {6}{7}{8} 💻 ", "type": "title" }, { - "key": "║\u001b[75C║\u001b[75D{#31} kernel ", + "key": "{$2}{#31} kernel ", "type": "kernel" }, { - "key": "║\u001b[75C║\u001b[75D{#32}󰅐 uptime ", + "key": "{$2}{#32}󰅐 uptime ", "type": "uptime" }, { - "key": "║\u001b[75C║\u001b[75D{#33}󰟾 distro ", + "key": "{$2}{#33}󰟾 distro ", "type": "os" }, { - "key": "║\u001b[75C║\u001b[75D{#34}󰇄 desktop ", + "key": "{$2}{#34}󰇄 desktop ", "type": "de" }, { - "key": "║\u001b[75C║\u001b[75D{#35} term ", + "key": "{$2}{#35} term ", "type": "terminal" }, { - "key": "║\u001b[75C║\u001b[75D{#36} shell ", + "key": "{$2}{#36} shell ", "type": "shell" }, { - "key": "║\u001b[75C║\u001b[75D{#35}󰍛 cpu ", + "key": "{$2}{#35}󰍛 cpu ", "type": "cpu", "showPeCoreCount": true, "temp": true }, { - "key": "║\u001b[75C║\u001b[75D{#34}󰍛 gpu ", + "key": "{$2}{#34}󰍛 gpu ", "type": "gpu" }, { - "key": "║\u001b[75C║\u001b[75D{#33}󰉉 disk ", + "key": "{$2}{#33}󰉉 disk ", "type": "disk", "folders": "/" }, { - "key": "║\u001b[75C║\u001b[75D{#32} memory ", + "key": "{$2}{#32} memory ", "type": "memory" }, { - "key": "║\u001b[75C║\u001b[75D{#31}󰩟 network ", + "key": "{$2}{#31}󰩟 network ", "type": "localip", "format": "{1} ({4})" }, { - "format": "{#1}{#keys}╠═══════════════════════════════════════════════════════════════════════════╣", + "format": "{#1}{#keys}╠{$1}╣", "type": "custom" }, { - "key": "║\u001b[75C║\u001b[75D{#39} colors ", + "key": "{$2}{#39} colors ", "type": "colors", "symbol": "circle" }, { - "format": "{#1}{#keys}╚═══════════════════════════════════════════════════════════════════════════╝", + "format": "{#1}{#keys}╚{$1}╝", "type": "custom" } ] diff --git a/presets/examples/2.jsonc b/presets/examples/2.jsonc index 439924905c..ba8fe4ee9b 100644 --- a/presets/examples/2.jsonc +++ b/presets/examples/2.jsonc @@ -10,13 +10,16 @@ // "height": 12 // }, "display": { - "separator": "  " + "separator": "  ", + "constants": [ + "───────────────" + ] }, "modules": [ { "type": "custom", // HardwareStart // {#1} is equivalent to `\u001b[1m`. {#} is equivalent to `\u001b[m` - "format": "┌─────────── {#1}Hardware Information{#} ───────────┐" + "format": "┌{$1} {#1}Hardware Information{#} {$1}┐" }, { "type": "host", @@ -72,12 +75,12 @@ }, { "type": "custom", // SoftwareStart - "format": "├─────────── {#1}Software Information{#} ───────────┤" + "format": "├{$1} {#1}Software Information{#} {$1}┤" }, { "type": "title", "key": " ", - "format": "{1}@{2}" + "format": "{1}${2}" }, { "type": "os", @@ -156,7 +159,7 @@ }, { "type": "custom", // InformationEnd - "format": "└────────────────────────────────────────────┘" + "format": "└{$1}──────────────────────{$1}┘" }, { "type": "colors", diff --git a/presets/examples/20.jsonc b/presets/examples/20.jsonc index 231d50b62c..feab271366 100644 --- a/presets/examples/20.jsonc +++ b/presets/examples/20.jsonc @@ -15,7 +15,10 @@ "charElapsed": "█", "charTotal": "░", "width": 40 - } + }, + "constants": [ + "\u001b[42C" + ] }, "modules": [ { @@ -41,11 +44,11 @@ }, { "type": "os", - "key": "│ OS │\u001b[42C" + "key": "│ OS │{$1}" }, { "type": "kernel", - "key": "│ KERNEL │\u001b[42C" + "key": "│ KERNEL │{$1}" }, { "type": "custom", @@ -53,34 +56,34 @@ }, { "type": "title", - "key": "│ HOSTNAME │\u001b[42C", + "key": "│ HOSTNAME │{$1}", "format": "{host-name}" }, { "type": "localip", - "key": "│ CLIENT IP │\u001b[42C", + "key": "│ CLIENT IP │{$1}", "format": "{ipv4}" }, { "type": "localip", - "key": "│ MAC ADDR │\u001b[42C", + "key": "│ MAC ADDR │{$1}", "format": "{mac} ({ifname})", "showIPv4": false, "showMac": true }, { "type": "dns", - "key": "│ DNS │\u001b[42C", + "key": "│ DNS │{$1}", "showType": "ipv4" }, { "type": "title", - "key": "│ USER │\u001b[42C", + "key": "│ USER │{$1}", "format": "{user-name}" }, { "type": "host", - "key": "│ MACHINE │\u001b[42C", + "key": "│ MACHINE │{$1}", "format": "{name}" }, { @@ -89,25 +92,25 @@ }, { "type": "cpu", - "key": "│ PROCESSOR │\u001b[42C", + "key": "│ PROCESSOR │{$1}", "format": "{name}" }, { "type": "cpu", - "key": "│ CORES │\u001b[42C", + "key": "│ CORES │{$1}", "format": "{cores-physical} PHYSICAL CORES / {cores-logical} THREADS", "showPeCoreCount": false }, { "type": "cpu", - "key": "│ CPU FREQ │\u001b[42C", + "key": "│ CPU FREQ │{$1}", "format": "{freq-max}{/freq-max}{freq-base}{/} GHz" }, { "type": "loadavg", "compact": false, // {duration} is not fixed length, hack it - "key": "│ LOAD \u001b[s{duration}m\u001b[u\u001b[6C│\u001b[42C" + "key": "│ LOAD \u001b[s{duration}m\u001b[u\u001b[6C│{$1}" }, { "type": "custom", @@ -115,12 +118,12 @@ }, { "type": "memory", - "key": "│ MEMORY │\u001b[42C", + "key": "│ MEMORY │{$1}", "format": "{used} / {total} [{percentage}]" }, { "type": "memory", - "key": "│ USAGE │\u001b[42C", + "key": "│ USAGE │{$1}", "format": "" }, { @@ -129,13 +132,13 @@ }, { "type": "disk", - "key": "│ VOLUME │\u001b[42C", + "key": "│ VOLUME │{$1}", "format": "{size-used} / {size-total} [{size-percentage}]", "folders": "/" }, { "type": "disk", - "key": "│ DISK USAGE │\u001b[42C", + "key": "│ DISK USAGE │{$1}", "format": "" }, { @@ -144,13 +147,13 @@ }, { "type": "users", - "key": "│ LAST LOGIN │\u001b[42C", + "key": "│ LAST LOGIN │{$1}", "format": "{login-time}{?client-ip} ({client-ip})", "myselfOnly": true }, { "type": "uptime", - "key": "│ UPTIME │\u001b[42C" + "key": "│ UPTIME │{$1}" }, { "type": "custom", diff --git a/presets/examples/21.jsonc b/presets/examples/21.jsonc index 69f867ef95..6f59778323 100644 --- a/presets/examples/21.jsonc +++ b/presets/examples/21.jsonc @@ -3,39 +3,44 @@ "logo": { "type": "small" }, + "display": { + "constants": [ + "██ " + ] + }, "modules": [ { - "key": "██ Distro", + "key": "{$1}Distro", "keyColor": "38;5;210", "type": "os" }, { - "key": "██ Kernel", + "key": "{$1}Kernel", "keyColor": "38;5;84", "type": "kernel" }, { - "key": "██ Shell", + "key": "{$1}Shell", "keyColor": "38;5;147", "type": "shell" }, { - "key": "██ Packages", + "key": "{$1}Packages", "keyColor": "38;5;200", "type": "packages" }, { - "key": "██ WM", + "key": "{$1}WM", "keyColor": "38;5;44", "type": "wm" }, { - "key": "██ CPU", + "key": "{$1}CPU", "keyColor": "38;5;75", "type": "cpu" }, { - "key": "██ Memory", + "key": "{$1}Memory", "keyColor": "38;5;123", "type": "memory" } diff --git a/presets/examples/22.jsonc b/presets/examples/22.jsonc index 5ccb863f44..43c495e592 100644 --- a/presets/examples/22.jsonc +++ b/presets/examples/22.jsonc @@ -12,7 +12,10 @@ "color": { "separator": "blue" }, - "separator": " | " + "separator": " | ", + "constants": [ + ">-----------<+>---------------------------------------------<" + ] }, "modules": [ { @@ -22,7 +25,7 @@ }, { "type": "custom", - "format": ">-----------<+>------------------------------------------<", + "format": "{$1}", "outputColor": "separator" }, { @@ -57,7 +60,7 @@ }, { "type": "custom", - "format": ">-----------<+>------------------------------------------<", + "format": "{$1}", "outputColor": "separator" }, { @@ -97,7 +100,7 @@ }, { "type": "custom", - "format": ">-----------<+>------------------------------------------<", + "format": "{$1}", "outputColor": "separator" }, "break", diff --git a/presets/examples/3.jsonc b/presets/examples/3.jsonc index 89fc93198c..670a942a82 100644 --- a/presets/examples/3.jsonc +++ b/presets/examples/3.jsonc @@ -2,7 +2,9 @@ { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", - "logo": "debian_small", + "logo": { + "type": "small" + }, "display": { "binaryPrefix": "si" }, diff --git a/presets/examples/4.jsonc b/presets/examples/4.jsonc index 81040c0d86..fafeb892a1 100644 --- a/presets/examples/4.jsonc +++ b/presets/examples/4.jsonc @@ -3,7 +3,7 @@ { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", "logo": { - "source": "arch_small", + "type": "small", "padding": { "right": 1 } diff --git a/presets/examples/5.jsonc b/presets/examples/5.jsonc index 064d70be38..11b9c05e63 100644 --- a/presets/examples/5.jsonc +++ b/presets/examples/5.jsonc @@ -4,7 +4,7 @@ "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", "logo": null, "display": { - "color": "reset_magenta" + "color": "magenta" }, "modules": [ { diff --git a/presets/examples/6.jsonc b/presets/examples/6.jsonc index 0e9e626fa5..96c5365d7f 100644 --- a/presets/examples/6.jsonc +++ b/presets/examples/6.jsonc @@ -3,12 +3,6 @@ { "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", - // "logo": { - // "type": "iterm", - // "source": "/Users/carter/Desktop/apple1.png", - // "width": 28, - // "height": 12 - // }, "display": { "separator": " " }, @@ -125,8 +119,8 @@ "key": "╰─󰸉", "keyColor": "yellow" }, - "break", + { "type": "title", "key": "╭─", From 9268d8449e11c69dd817addee32466c55435bca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 15 Jul 2024 16:01:19 +0800 Subject: [PATCH 11/58] IO (Windows): remove debug output Fix #1097 --- src/common/io/io_windows.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index ce7cde96a7..0af70bd0b6 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -229,7 +229,6 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...) hConout = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL); hOutput = hConout; } - WriteFile(hOutput, "TEST\n", 5, &bytes, NULL); WriteFile(hOutput, request, (DWORD) strlen(request), &bytes, NULL); } From 89ce5988004d9074346c2966dc303d92dfcf6749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 15 Jul 2024 16:19:39 +0800 Subject: [PATCH 12/58] Revert "TerminalFont (Linux): improve detection for xterm" Committed by accident This reverts commit 64c53e2cdc5e3a6c96f9fcf268fee0c5412182d7. --- src/common/properties.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/properties.c b/src/common/properties.c index dd717c0a84..fbf11416ef 100644 --- a/src/common/properties.c +++ b/src/common/properties.c @@ -59,7 +59,7 @@ bool ffParsePropLinePointer(const char** line, const char* start, FFstrbuf* buff } //Copy the value to the buffer - while(tolower(**line) != tolower(valueEnd) && **line != '\n' && **line != '\0') + while(**line != valueEnd && **line != '\n' && **line != '\0') { ffStrbufAppendC(buffer, **line); ++(*line); From 801bd7c8793eb5124cd829a6768c25f54bafe423 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 15 Jul 2024 18:34:43 +0800 Subject: [PATCH 13/58] GPU: fix `--gpu-hide-type` doesn't work Fix #1098 --- src/modules/gpu/gpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index ddcfe7e06a..d7cecf5163 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -177,6 +177,7 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char { "discrete", FF_GPU_TYPE_DISCRETE }, {}, }); + return true; } if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) From 25577a6e58a046ee8290d90fd4daca5988509429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 15 Jul 2024 22:55:52 +0800 Subject: [PATCH 14/58] Disk (Android): ignore `/apex/*` --- src/detection/disk/disk_linux.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 812cb58846..31b90adcaf 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -71,6 +71,10 @@ static bool isPhysicalDevice(const struct mntent* device) ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices ) return false; + // https://source.android.com/docs/core/ota/apex?hl=zh-cn + if(ffStrStartsWith(device->mnt_dir, "/apex/")) + return false; + #endif // __ANDROID__ return true; From e4f0efd58c23c6019625436c45fa5cfa064e1235 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 16 Jul 2024 09:13:44 +0800 Subject: [PATCH 15/58] Logo (Builtin): update void logo --- src/logo/ascii/void2_small.txt | 7 +++++++ src/logo/ascii/void_small.txt | 14 +++++++------- src/logo/builtin.c | 11 +++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 src/logo/ascii/void2_small.txt diff --git a/src/logo/ascii/void2_small.txt b/src/logo/ascii/void2_small.txt new file mode 100644 index 0000000000..e9602b027a --- /dev/null +++ b/src/logo/ascii/void2_small.txt @@ -0,0 +1,7 @@ + _______ + _ \______ - +| \ ___ \ | +| | / \ | | +| | \___/ | | +| \______ \_| + -_______\ \ No newline at end of file diff --git a/src/logo/ascii/void_small.txt b/src/logo/ascii/void_small.txt index e9602b027a..070f154a57 100644 --- a/src/logo/ascii/void_small.txt +++ b/src/logo/ascii/void_small.txt @@ -1,7 +1,7 @@ - _______ - _ \______ - -| \ ___ \ | -| | / \ | | -| | \___/ | | -| \______ \_| - -_______\ \ No newline at end of file + ____ + 'pfPfp.% +// _._ \\ +UU |===| UU +\\ ^~^ // + `0PpppP' + ````` diff --git a/src/logo/builtin.c b/src/logo/builtin.c index c7f33adc03..f4ac869ec4 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -4480,6 +4480,17 @@ static const FFlogo V[] = { .colorKeys = FF_COLOR_FG_WHITE, .colorTitle = FF_COLOR_FG_GREEN, }, + // Void2Small + { + .names = {"void2_small", "void-linux2-small"}, + .type = FF_LOGO_LINE_TYPE_SMALL_BIT | FF_LOGO_LINE_TYPE_ALTER_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_VOID2_SMALL, + .colors = { + FF_COLOR_FG_GREEN, + }, + .colorKeys = FF_COLOR_FG_WHITE, + .colorTitle = FF_COLOR_FG_GREEN, + }, // LAST {}, }; From 4f3649e96e5d09cc2ff58999811a48fdf8acfcf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 10:02:52 +0800 Subject: [PATCH 16/58] Doc: update README [ci skip] --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index eac500b00f..ffa0ab325a 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,10 @@ The p10k doc clearly states that you should NOT print anything to stdout after ` You can always use `fastfetch --pipe false` to force fastfetch running in colorful mode. +### Q: Why do fastfetch and neofetch show different memory usage result? + +See #1096 + ### Q: I want feature A / B / C. Will fastfetch support it? Fastfetch is a system information tool. We only accept hardware or system level software feature requests. For most personal uses, I recommend using `Command` module to detect it yourself, which can be used to grab output from a custom shell script: From 2a9f9d5a342c12c14f560ca12f6f428f2975f969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 11:07:26 +0800 Subject: [PATCH 17/58] Colors: add and default to `--colors-symbol background` --- doc/json_schema.json | 3 ++- src/data/help.json | 3 ++- src/modules/colors/colors.c | 41 +++++++++++++++++++++++++++---------- src/modules/colors/option.h | 1 + 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 870bea4218..7086ef4973 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1180,13 +1180,14 @@ "type": "string", "enum": [ "block", + "background", "circle", "diamond", "triangle", "square", "star" ], - "default": "block" + "default": "background" }, "paddingLeft": { "description": "Set the number of white spaces to print before the symbol", diff --git a/src/data/help.json b/src/data/help.json index 750b4bd8b6..bd919b01de 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1538,13 +1538,14 @@ "type": "enum", "enum": { "block": "\u2588\u2588\u2588", + "background": "(whitespaces with background)", "circle": "\u25cf", "diamond": "\u25c6", "triangle": "\u25b2", "square": "\u25a0", "star": "\u2605" }, - "default": "block" + "default": "background" } }, { diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index e7e133d688..cda51d354d 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -20,15 +20,24 @@ void ffPrintColors(FFColorsOptions* options) FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(128); - if (options->symbol == FF_COLORS_SYMBOL_BLOCK) + if (options->symbol == FF_COLORS_SYMBOL_BLOCK || options->symbol == FF_COLORS_SYMBOL_BACKGROUND) { // 3%d: Set the foreground color for(uint8_t i = options->block.range[0]; i <= min(options->block.range[1], 7); i++) { - if (!instance.config.display.pipe) - ffStrbufAppendF(&result, "\e[3%dm", i); - for (uint8_t j = 0; j < options->block.width; j++) - ffStrbufAppendS(&result, "█"); + if (options->symbol == FF_COLORS_SYMBOL_BLOCK) + { + if (!instance.config.display.pipe) + ffStrbufAppendF(&result, "\e[3%dm", i); + for (uint8_t j = 0; j < options->block.width; j++) + ffStrbufAppendS(&result, "█"); + } + else + { + if (!instance.config.display.pipe) + ffStrbufAppendF(&result, "\e[4%dm", i); + ffStrbufAppendNC(&result, options->block.width, ' '); + } } if (result.length > 0) { @@ -44,14 +53,22 @@ void ffPrintColors(FFColorsOptions* options) ffStrbufClear(&result); } - // 1: Set everything to bolt. This causes normal colors on some systems to be bright. // 9%d: Set the foreground to the bright color for(uint8_t i = max(options->block.range[0], 8); i <= options->block.range[1]; i++) { - if(!instance.config.display.pipe) - ffStrbufAppendF(&result, "\e[9%dm", i - 8); - for (uint8_t j = 0; j < options->block.width; j++) - ffStrbufAppendS(&result, "█"); + if (options->symbol == FF_COLORS_SYMBOL_BLOCK) + { + if(!instance.config.display.pipe) + ffStrbufAppendF(&result, "\e[9%dm", i - 8); + for (uint8_t j = 0; j < options->block.width; j++) + ffStrbufAppendS(&result, "█"); + } + else + { + if (!instance.config.display.pipe) + ffStrbufAppendF(&result, "\e[10%dm", i - 8); + ffStrbufAppendNC(&result, options->block.width, ' '); + } } } else @@ -109,6 +126,7 @@ bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, cons { options->symbol = (FFColorsSymbol) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { { "block", FF_COLORS_SYMBOL_BLOCK }, + { "background", FF_COLORS_SYMBOL_BACKGROUND }, { "circle", FF_COLORS_SYMBOL_CIRCLE }, { "diamond", FF_COLORS_SYMBOL_DIAMOND }, { "triangle", FF_COLORS_SYMBOL_TRIANGLE }, @@ -164,6 +182,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { { "block", FF_COLORS_SYMBOL_BLOCK }, + { "background", FF_COLORS_SYMBOL_BACKGROUND }, { "circle", FF_COLORS_SYMBOL_CIRCLE }, { "diamond", FF_COLORS_SYMBOL_DIAMOND }, { "triangle", FF_COLORS_SYMBOL_TRIANGLE }, @@ -278,7 +297,7 @@ void ffInitColorsOptions(FFColorsOptions* options) ); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufSetStatic(&options->moduleArgs.key, " "); - options->symbol = FF_COLORS_SYMBOL_BLOCK; + options->symbol = FF_COLORS_SYMBOL_BACKGROUND; options->paddingLeft = 0; options->block = (FFBlockConfig) { .width = 3, diff --git a/src/modules/colors/option.h b/src/modules/colors/option.h index 24b93b7c74..54a8e496d7 100644 --- a/src/modules/colors/option.h +++ b/src/modules/colors/option.h @@ -7,6 +7,7 @@ typedef enum FFColorsSymbol { FF_COLORS_SYMBOL_BLOCK, + FF_COLORS_SYMBOL_BACKGROUND, FF_COLORS_SYMBOL_CIRCLE, FF_COLORS_SYMBOL_DIAMOND, FF_COLORS_SYMBOL_SQUARE, From bd0b108c0493053a29138595440a33bd1edd577c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 14:32:51 +0800 Subject: [PATCH 18/58] Colors: don't disable color if `--color-symbol background` is set in `--pipe` mode --- src/modules/colors/colors.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index cda51d354d..8d28405f7d 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -34,8 +34,7 @@ void ffPrintColors(FFColorsOptions* options) } else { - if (!instance.config.display.pipe) - ffStrbufAppendF(&result, "\e[4%dm", i); + ffStrbufAppendF(&result, "\e[4%dm", i); ffStrbufAppendNC(&result, options->block.width, ' '); } } @@ -65,8 +64,7 @@ void ffPrintColors(FFColorsOptions* options) } else { - if (!instance.config.display.pipe) - ffStrbufAppendF(&result, "\e[10%dm", i - 8); + ffStrbufAppendF(&result, "\e[10%dm", i - 8); ffStrbufAppendNC(&result, options->block.width, ' '); } } From 3433043604b3051042910fd77111dd94082e0b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 14:53:14 +0800 Subject: [PATCH 19/58] Terminal: support zed version detection --- src/detection/terminalshell/terminalshell.c | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 2bc80b56b5..dfb4fbbd9a 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -481,6 +481,29 @@ static bool getTerminalVersionZellij(FFstrbuf* exe, FFstrbuf* version) return version->length > 0; } +static bool getTerminalVersionZed(FFstrbuf* exe, FFstrbuf* version) +{ + FF_STRBUF_AUTO_DESTROY cli = ffStrbufCreateCopy(exe); + ffStrbufSubstrBeforeLastC(&cli, '/'); + ffStrbufAppendS(&cli, "/cli" + #ifdef _WIN32 + ".exe" + #endif + ); + + if(ffProcessAppendStdOut(version, (char* const[]) { + cli.chars, + "--version", + NULL + }) != NULL) + return false; + + // Zed 0.142.6 – /Applications/Zed.app + ffStrbufSubstrAfterFirstC(version, ' '); + ffStrbufSubstrBeforeFirstC(version, ' '); + return true; +} + #ifndef _WIN32 static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { @@ -650,6 +673,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufStartsWithIgnCaseS(processName, "zellij")) return getTerminalVersionZellij(exe, version); + if(ffStrbufStartsWithIgnCaseS(processName, "zed")) + return getTerminalVersionZed(exe, version); + const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION"); if(termProgramVersion) { From 0776dac95bf3b46e4f52735ec0defe008fcfff7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 15:06:25 +0800 Subject: [PATCH 20/58] TerminalFont: improve wezterm detection --- src/detection/terminalfont/terminalfont.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 63e0a6fc04..bac06c6d1e 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -350,12 +350,19 @@ static void detectTerminator(FFTerminalFontResult* result) ffFontInitPango(&result->font, fontName.chars); } -static bool detectWezterm(FFTerminalFontResult* result) +static bool detectWezterm(const FFstrbuf* exe, FFTerminalFontResult* result) { + FF_STRBUF_AUTO_DESTROY cli = ffStrbufCreateCopy(exe); + ffStrbufSubstrBeforeLastC(&cli, '-'); + + #ifdef _WIN32 + ffStrbufAppendS(&cli, ".exe"); + #endif + FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate(); ffStrbufSetS(&result->error, ffProcessAppendStdOut(&fontName, (char* const[]){ - "wezterm", + cli.chars, "ls-fonts", "--text", "a", @@ -438,7 +445,7 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "terminator")) detectTerminator(terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "wezterm-gui")) - detectWezterm(terminalFont); + detectWezterm(&terminal->exe, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "tabby")) detectTabby(terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "contour")) From c795c207231750d95011ff7b557828d3ee435879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 15:39:06 +0800 Subject: [PATCH 21/58] FFstrbuf: improve ffStrbufSubstr* --- src/util/FFstrbuf.c | 58 ++++++++++++++++++++++++++++----------------- src/util/FFstrbuf.h | 23 +++++++++--------- tests/strbuf.c | 26 +++++++++++++++----- 3 files changed, 68 insertions(+), 39 deletions(-) diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 37f5cf2d39..c4a01592e8 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -292,21 +292,22 @@ void ffStrbufTrimRightSpace(FFstrbuf* strbuf) strbuf->chars[strbuf->length] = '\0'; } -void ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex) +bool ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex) { if(startIndex > strbuf->length || startIndex >= endIndex) - return; + return false; if(endIndex > strbuf->length) { ffStrbufSubstrBefore(strbuf, startIndex); - return; + return true; } ffStrbufEnsureFree(strbuf, 0); memmove(strbuf->chars + startIndex, strbuf->chars + endIndex, strbuf->length - endIndex); strbuf->length -= (endIndex - startIndex); strbuf->chars[strbuf->length] = '\0'; + return true; } void ffStrbufRemoveS(FFstrbuf* strbuf, const char* str) @@ -362,28 +363,29 @@ void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace) *current_pos = replace; } -void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index) +bool ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index) { if(strbuf->length <= index) - return; + return false; if(strbuf->allocated == 0) { //static string ffStrbufInitNS(strbuf, strbuf->length, strbuf->chars); - return; + return true; } strbuf->length = index; strbuf->chars[strbuf->length] = '\0'; + return true; } -void ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index) +bool ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index) { if(index >= strbuf->length) { ffStrbufClear(strbuf); - return; + return true; } if(strbuf->allocated == 0) @@ -391,36 +393,45 @@ void ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index) //static string strbuf->length -= index + 1; strbuf->chars += index + 1; - return; + return true; } memmove(strbuf->chars, strbuf->chars + index + 1, strbuf->length - index - 1); strbuf->length -= (index + 1); strbuf->chars[strbuf->length] = '\0'; + return true; } -void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c) +bool ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c) { uint32_t index = ffStrbufFirstIndexC(strbuf, c); - if(index < strbuf->length) - ffStrbufSubstrAfter(strbuf, index); + if(index >= strbuf->length) + return false; + ffStrbufSubstrAfter(strbuf, index); + return true; } -void ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str) +bool ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str) { if(*str == '\0') - return; + return false; uint32_t index = ffStrbufFirstIndexS(strbuf, str) + (uint32_t) strlen(str) - 1; // -1, because firstIndexS is already pointing to str[0], we want to add only the remaining length - if(index < strbuf->length) - ffStrbufSubstrAfter(strbuf, index); + if(index >= strbuf->length) + return false; + + ffStrbufSubstrAfter(strbuf, index); + return true; } -void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c) +bool ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c) { uint32_t index = ffStrbufLastIndexC(strbuf, c); - if(index < strbuf->length) - ffStrbufSubstrAfter(strbuf, index); + if(index >= strbuf->length) + return false; + + ffStrbufSubstrAfter(strbuf, index); + return true; } uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c) @@ -448,10 +459,13 @@ bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end) return false; } -void ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c) +bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c) { - if(!ffStrbufEndsWithC(strbuf, c)) - ffStrbufAppendC(strbuf, c); + if(ffStrbufEndsWithC(strbuf, c)) + return false; + + ffStrbufAppendC(strbuf, c); + return true; } void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 92ea2da1f1..a3b7179a44 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -56,7 +56,7 @@ void ffStrbufTrimLeft(FFstrbuf* strbuf, char c); void ffStrbufTrimRight(FFstrbuf* strbuf, char c); void ffStrbufTrimRightSpace(FFstrbuf* strbuf); -void ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex); +bool ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex); void ffStrbufRemoveS(FFstrbuf* strbuf, const char* str); void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, const char* strings[]); @@ -67,17 +67,18 @@ FF_C_NODISCARD uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace); -void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index); -void ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index); // Not including the index -void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c); -void ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str); -void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c); +// Returns true if the strbuf is modified +bool ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index); +bool ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index); // Not including the index +bool ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c); +bool ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str); +bool ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c); FF_C_NODISCARD uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c); bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end); -void ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c); +bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c); void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file); void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file); @@ -383,14 +384,14 @@ static inline FF_C_NODISCARD uint32_t ffStrbufLastIndexC(const FFstrbuf* strbuf, return ffStrbufPreviousIndexC(strbuf, strbuf->length - 1, c); } -static inline void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c) +static inline bool ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c) { - ffStrbufSubstrBefore(strbuf, ffStrbufFirstIndexC(strbuf, c)); + return ffStrbufSubstrBefore(strbuf, ffStrbufFirstIndexC(strbuf, c)); } -static inline void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c) +static inline bool ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c) { - ffStrbufSubstrBefore(strbuf, ffStrbufLastIndexC(strbuf, c)); + return ffStrbufSubstrBefore(strbuf, ffStrbufLastIndexC(strbuf, c)); } static inline FF_C_NODISCARD bool ffStrbufStartsWithC(const FFstrbuf* strbuf, char c) diff --git a/tests/strbuf.c b/tests/strbuf.c index 0a35012d23..01db4e0940 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -93,12 +93,26 @@ int main(void) //substr - ffStrbufSubstrBefore(&strbuf, 9); + VERIFY(ffStrbufSubstrBefore(&strbuf, 9)); VERIFY(strbuf.length == 9); VERIFY(strbuf.allocated >= 110); VERIFY(strbuf.chars[strbuf.length] == 0); VERIFY(ffStrbufEqualS(&strbuf, "123456789")); + VERIFY(!ffStrbufSubstrBeforeFirstC(&strbuf, '0')); + VERIFY(!ffStrbufSubstrBeforeLastC(&strbuf, '0')); + VERIFY(!ffStrbufSubstrAfterFirstC(&strbuf, '0')); + VERIFY(!ffStrbufSubstrAfterLastC(&strbuf, '0')); + VERIFY(ffStrbufEqualS(&strbuf, "123456789")); + + VERIFY(ffStrbufSubstrBeforeFirstC(&strbuf, '9')); + VERIFY(ffStrbufSubstrBeforeLastC(&strbuf, '8')); + VERIFY(ffStrbufSubstrAfterFirstC(&strbuf, '1')); + VERIFY(ffStrbufSubstrAfterLastC(&strbuf, '2')); + VERIFY(ffStrbufEqualS(&strbuf, "34567")); + + ffStrbufSetS(&strbuf, "123456789"); + //startsWithC VERIFY(ffStrbufStartsWithC(&strbuf, '1')); @@ -313,7 +327,7 @@ int main(void) //ffStrbufCreateStatic / Substr ffStrbufInitStatic(&strbuf, "__TEST__"); - ffStrbufRemoveSubstr(&strbuf, 0, 6); + VERIFY(ffStrbufRemoveSubstr(&strbuf, 0, 6)); VERIFY(ffStrbufEqualS(&strbuf, "__")); VERIFY(strbuf.length == 2); VERIFY(strbuf.allocated > 0); @@ -321,7 +335,7 @@ int main(void) //ffStrbufCreateStatic / Substr ffStrbufInitStatic(&strbuf, "__TEST__"); - ffStrbufRemoveSubstr(&strbuf, 2, 8); + VERIFY(ffStrbufRemoveSubstr(&strbuf, 2, 8)); VERIFY(ffStrbufEqualS(&strbuf, "__")); VERIFY(strbuf.length == 2); VERIFY(strbuf.allocated > 0); @@ -329,13 +343,13 @@ int main(void) //ffStrbufCreateStatic / Substr ffStrbufInitStatic(&strbuf, "__TEST__"); - ffStrbufRemoveSubstr(&strbuf, 2, 6); + VERIFY(ffStrbufRemoveSubstr(&strbuf, 2, 6)); VERIFY(ffStrbufEqualS(&strbuf, "____")); VERIFY(strbuf.length == 4); VERIFY(strbuf.allocated > 0); ffStrbufDestroy(&strbuf); - //ffStrbufCreateStatic / Substr + //ffStrbufCreateStatic / ReplaceAllC ffStrbufInitStatic(&strbuf, "__TEST__"); ffStrbufReplaceAllC(&strbuf, '_', '-'); VERIFY(ffStrbufEqualS(&strbuf, "--TEST--")); @@ -403,5 +417,5 @@ int main(void) ffStrbufDestroy(&strbuf); //Success - puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); + puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); } From c0781dd5f893d6755ebf7bffef42b7ffd8726f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 16:11:26 +0800 Subject: [PATCH 22/58] Display: print physical size --- src/common/format.h | 2 ++ src/modules/display/display.c | 31 +++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/common/format.h b/src/common/format.h index af1b7ff417..f1b1aede0f 100644 --- a/src/common/format.h +++ b/src/common/format.h @@ -1,5 +1,7 @@ #pragma once +#include "util/FFstrbuf.h" + typedef enum FFformatargtype { FF_FORMAT_ARG_TYPE_NULL = 0, diff --git a/src/modules/display/display.c b/src/modules/display/display.c index dcfc6fad88..e902922d39 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -4,7 +4,9 @@ #include "modules/display/display.h" #include "util/stringUtils.h" -#define FF_DISPLAY_NUM_FORMAT_ARGS 11 +#include + +#define FF_DISPLAY_NUM_FORMAT_ARGS 13 static int sortByNameAsc(FFDisplayResult* a, FFDisplayResult* b) { @@ -96,35 +98,44 @@ void ffPrintDisplay(FFDisplayOptions* options) })); } + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); - printf("%ix%i", result->width, result->height); + ffStrbufAppendF(&buffer, "%ix%i", result->width, result->height); if(result->refreshRate > 0) { if(options->preciseRefreshRate) - printf(" @ %gHz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0); + ffStrbufAppendF(&buffer, " @ %gHz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0); else - printf(" @ %iHz", (uint32_t) (result->refreshRate + 0.5)); + ffStrbufAppendF(&buffer, " @ %iHz", (uint32_t) (result->refreshRate + 0.5)); } if( result->scaledWidth > 0 && result->scaledWidth != result->width && result->scaledHeight > 0 && result->scaledHeight != result->height) - printf(" (as %ix%i)", result->scaledWidth, result->scaledHeight); + ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight); + + if (result->physicalWidth > 0 && result->physicalHeight > 0) + ffStrbufAppendF(&buffer, " in %ix%i mm", result->physicalWidth, result->physicalHeight); if(result->type != FF_DISPLAY_TYPE_UNKNOWN) - fputs(result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]", stdout); + ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); if(moduleIndex > 0 && result->primary) - printf(" *"); + ffStrbufAppendS(&buffer, " *"); - putchar('\n'); + ffStrbufPutTo(&buffer, stdout); + ffStrbufClear(&buffer); } else { + double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4; + double ppi = sqrt(result->width * result->width + result->height * result->height) / inch; + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISPLAY_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_UINT, &result->width, "width"}, {FF_FORMAT_ARG_TYPE_UINT, &result->height, "height"}, @@ -137,6 +148,8 @@ void ffPrintDisplay(FFDisplayOptions* options) {FF_FORMAT_ARG_TYPE_BOOL, &result->primary, "is-primary"}, {FF_FORMAT_ARG_TYPE_UINT, &result->physicalWidth, "physical-width"}, {FF_FORMAT_ARG_TYPE_UINT, &result->physicalHeight, "physical-height"}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &inch, "inch"}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &ppi, "ppi"}, })); } } @@ -327,6 +340,8 @@ void ffPrintDisplayHelpFormat(void) "True if being the primary screen - is-primary", "Screen physical width (in millimeters) - physical-width", "Screen physical height (in millimeters) - physical-height", + "Physical diagonal length in inches - inch", + "Pixels per inch (PPI) - ppi", })); } From 5bc9a5dc4e3543634c5473c8f1c45a878fbaed80 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 16 Jul 2024 16:36:19 +0800 Subject: [PATCH 23/58] Display: rotate physical demensions --- .../displayserver/displayserver_windows.c | 3 ++ .../linux/wayland/global-output.c | 33 +-------------- .../displayserver/linux/wayland/kde-output.c | 33 +-------------- .../displayserver/linux/wayland/wayland.c | 41 +++++++++++++++++++ .../displayserver/linux/wayland/wayland.h | 2 + .../displayserver/linux/wayland/zwlr-output.c | 33 +-------------- 6 files changed, 49 insertions(+), 96 deletions(-) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index a7774b162e..3ccb212fde 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -132,6 +132,9 @@ static void detectDisplays(FFDisplayServerResult* ds) uint32_t temp = width; width = height; height = temp; + temp = physicalWidth; + physicalWidth = physicalHeight; + physicalHeight = temp; } uint32_t rotation; diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index e318fc0db1..7f815f42f0 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -110,38 +110,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist if(display.width <= 0 || display.height <= 0) return; - uint32_t rotation; - switch(display.transform) - { - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - case WL_OUTPUT_TRANSFORM_90: - rotation = 90; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - case WL_OUTPUT_TRANSFORM_180: - rotation = 180; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - case WL_OUTPUT_TRANSFORM_270: - rotation = 270; - break; - default: - rotation = 0; - break; - } - - switch(rotation) - { - case 90: - case 270: { - int32_t temp = display.width; - display.width = display.height; - display.height = temp; - break; - } - default: - break; - } + uint32_t rotation = ffWaylandHandleRotation(&display); ffdsAppendDisplay(wldata->result, (uint32_t) display.width, diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index 558bcc433e..c6f08f243d 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -169,38 +169,7 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, if(display.width <= 0 || display.height <= 0 || !display.internal) return; - uint32_t rotation; - switch(display.transform) - { - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - case WL_OUTPUT_TRANSFORM_90: - rotation = 90; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - case WL_OUTPUT_TRANSFORM_180: - rotation = 180; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - case WL_OUTPUT_TRANSFORM_270: - rotation = 270; - break; - default: - rotation = 0; - break; - } - - switch(rotation) - { - case 90: - case 270: { - int32_t temp = display.width; - display.width = display.height; - display.height = temp; - break; - } - default: - break; - } + uint32_t rotation = ffWaylandHandleRotation(&display); ffdsAppendDisplay(wldata->result, (uint32_t) display.width, diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index cbb3703e13..2bf03ebe7e 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -217,6 +217,47 @@ void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)")) ffStrbufAppendS(&display->description, description); } + +uint32_t ffWaylandHandleRotation(WaylandDisplay* display) +{ + uint32_t rotation; + switch(display->transform) + { + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_90: + rotation = 90; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + case WL_OUTPUT_TRANSFORM_180: + rotation = 180; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + case WL_OUTPUT_TRANSFORM_270: + rotation = 270; + break; + default: + rotation = 0; + break; + } + + switch(rotation) + { + case 90: + case 270: { + int32_t temp = display->width; + display->width = display->height; + display->height = temp; + + temp = display->physicalWidth; + display->physicalWidth = display->physicalHeight; + display->physicalHeight = temp; + break; + } + default: + break; + } + return rotation; +} #endif void ffdsConnectWayland(FFDisplayServerResult* result) diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index 025b0b299b..e78a3c6de4 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -67,6 +67,8 @@ inline static uint64_t ffWaylandGenerateIdFromName(const char* name) void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name); void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description); +// Modifies content of display. Don't call this function when calling ffdsAppendDisplay +uint32_t ffWaylandHandleRotation(WaylandDisplay* display); void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version); void ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version); diff --git a/src/detection/displayserver/linux/wayland/zwlr-output.c b/src/detection/displayserver/linux/wayland/zwlr-output.c index dd9b832892..76aee392a7 100644 --- a/src/detection/displayserver/linux/wayland/zwlr-output.c +++ b/src/detection/displayserver/linux/wayland/zwlr-output.c @@ -120,38 +120,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output if(display.width <= 0 || display.height <= 0) return; - uint32_t rotation; - switch(display.transform) - { - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - case WL_OUTPUT_TRANSFORM_90: - rotation = 90; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - case WL_OUTPUT_TRANSFORM_180: - rotation = 180; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - case WL_OUTPUT_TRANSFORM_270: - rotation = 270; - break; - default: - rotation = 0; - break; - } - - switch(rotation) - { - case 90: - case 270: { - int32_t temp = display.width; - display.width = display.height; - display.height = temp; - break; - } - default: - break; - } + uint32_t rotation = ffWaylandHandleRotation(&display); ffdsAppendDisplay(wldata->result, (uint32_t) display.width, From 3b361c663d863de336809caea9402c3443c3bf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 21:56:37 +0800 Subject: [PATCH 24/58] Logo (Builtin): add ALT Linux --- src/logo/ascii/altlinux.txt | 22 ++++++++++++++++++++++ src/logo/builtin.c | 12 ++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/logo/ascii/altlinux.txt diff --git a/src/logo/ascii/altlinux.txt b/src/logo/ascii/altlinux.txt new file mode 100644 index 0000000000..ab09b39547 --- /dev/null +++ b/src/logo/ascii/altlinux.txt @@ -0,0 +1,22 @@ + ############## + ###################### + ########################## + ##+$2###$1####################### + #####$2#$1*$2###%+$1###################### + ########$2%$1*#$2%#####$1################### + ##########$2##$1*#*$2#######%+$1############## +#############$2%#############%$1############ +#############$2+################$1########## +##############$2################*$1######### +##############$2+################+$1######## +###############$2##########$1###$2+##%$1######## +###############$2+########$1######$2###$1####### +#############$2*####$1############$2%#+$1####### +############$2+###$3####$1##########$2%#*$1####### + ##########$2###*$3######$2+#+$1#####$2+##*$1###### + #########$2##%$3#####$2:%#####$1###$2###*$1##### + ########$2%#+$3######$2#############$1#### + #####$2##%:$3######$2:############$1## + ##$2+##*$3########$2############$1 + $2###$3#########$2##########$1 + $3########$2###### diff --git a/src/logo/builtin.c b/src/logo/builtin.c index f4ac869ec4..b23d3c3e93 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -112,6 +112,18 @@ static const FFlogo A[] = { .colorKeys = FF_COLOR_FG_CYAN, .colorTitle = FF_COLOR_FG_CYAN, }, + // ALTLinux + { + .names = {"ALTLinux", "Sisyphus"}, + .lines = FASTFETCH_DATATEXT_LOGO_ALTLINUX, + .colors = { + FF_COLOR_FG_YELLOW, + FF_COLOR_FG_BLACK, + FF_COLOR_FG_WHITE, + }, + .colorKeys = FF_COLOR_FG_YELLOW, + .colorTitle = FF_COLOR_FG_YELLOW, + }, // Amazon { .names = {"Amazon"}, From d869164d6bf78fb09fe8d7c49365842d3e9eec79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 16 Jul 2024 22:10:05 +0800 Subject: [PATCH 25/58] Display: show inches instead of full size Which is shorter --- src/modules/display/display.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index e902922d39..e6b2104de2 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -99,6 +99,7 @@ void ffPrintDisplay(FFDisplayOptions* options) } FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4; if(options->moduleArgs.outputFormat.length == 0) { @@ -109,9 +110,9 @@ void ffPrintDisplay(FFDisplayOptions* options) if(result->refreshRate > 0) { if(options->preciseRefreshRate) - ffStrbufAppendF(&buffer, " @ %gHz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0); + ffStrbufAppendF(&buffer, " @ %g Hz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0); else - ffStrbufAppendF(&buffer, " @ %iHz", (uint32_t) (result->refreshRate + 0.5)); + ffStrbufAppendF(&buffer, " @ %i Hz", (uint32_t) (result->refreshRate + 0.5)); } if( @@ -119,8 +120,8 @@ void ffPrintDisplay(FFDisplayOptions* options) result->scaledHeight > 0 && result->scaledHeight != result->height) ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight); - if (result->physicalWidth > 0 && result->physicalHeight > 0) - ffStrbufAppendF(&buffer, " in %ix%i mm", result->physicalWidth, result->physicalHeight); + if (inch > 0) + ffStrbufAppendF(&buffer, " in %i″", (uint32_t) (inch + 0.5)); if(result->type != FF_DISPLAY_TYPE_UNKNOWN) ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); @@ -133,7 +134,6 @@ void ffPrintDisplay(FFDisplayOptions* options) } else { - double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4; double ppi = sqrt(result->width * result->width + result->height * result->height) / inch; FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISPLAY_NUM_FORMAT_ARGS, ((FFformatarg[]) { From d1609ea96b752ac0bf1a41be565e2cd39664b029 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 17 Jul 2024 09:16:25 +0800 Subject: [PATCH 26/58] Separator: add option `--separator-length` --- doc/json_schema.json | 9 ++++++++- src/data/help.json | 13 +++++++++++-- src/modules/separator/option.h | 1 + src/modules/separator/separator.c | 32 ++++++++++++++++++++++++++++++- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 7086ef4973..3de8047d94 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1948,12 +1948,19 @@ "const": "separator" }, "string": { - "description": "Set the string to be printed", + "description": "Set the string to be printed by the separator line", "type": "string", "default": "-" }, "outputColor": { + "description": "Set the color of the separator line", "$ref": "#/$defs/outputColor" + }, + "length": { + "description": "Set the length of the separator line, or 0 to auto-detect", + "type": "integer", + "minimum": 0, + "default": 0 } } }, diff --git a/src/data/help.json b/src/data/help.json index bd919b01de..5b1a8b848a 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -947,7 +947,7 @@ }, { "long": "separator-string", - "desc": "Set the string printed by the separator module", + "desc": "Set the string to be printed by the separator line", "arg": { "type": "str", "default": "-" @@ -955,12 +955,21 @@ }, { "long": "separator-output-color", - "desc": "Set the color of the separator module", + "desc": "Set the color of the separator line", "arg": { "type": "color", "default": "default" } }, + { + "long": "separator-length", + "desc": "Set the length of the separator line", + "remark": "Set to 0 to automatically calculate it with the title length", + "arg": { + "type": "num", + "default": "0" + } + }, { "long": "disk-folders", "desc": "A colon (semicolon on Windows) separated list of folder paths to be detected", diff --git a/src/modules/separator/option.h b/src/modules/separator/option.h index 6f4d499534..5f435e7f09 100644 --- a/src/modules/separator/option.h +++ b/src/modules/separator/option.h @@ -10,4 +10,5 @@ typedef struct FFSeparatorOptions FFstrbuf string; FFstrbuf outputColor; + uint32_t length; } FFSeparatorOptions; diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index f1b9ecc35e..90a4e20961 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -34,6 +34,23 @@ static inline uint32_t getWcsWidth(const FFstrbuf* mbstr, wchar_t* wstr, mbstate void ffPrintSeparator(FFSeparatorOptions* options) { + ffLogoPrintLine(); + + if (options->length > 0) + { + if(__builtin_expect(options->string.length == 1, 1)) + ffPrintCharTimes(options->string.chars[0], options->length); + else + { + for (uint32_t i = 0; i < options->length; i++) + { + fputs(options->string.chars, stdout); + } + } + putchar('\n'); + return; + } + setlocale(LC_CTYPE, ""); mbstate_t state = {}; bool fqdn = instance.config.modules.title.fqdn; @@ -45,7 +62,6 @@ void ffPrintSeparator(FFSeparatorOptions* options) uint32_t titleLength = 1 // @ + getWcsWidth(&platform->userName, wstr, &state) // user name + (fqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name - ffLogoPrintLine(); if(options->outputColor.length && !instance.config.display.pipe) ffPrintColor(&options->outputColor); @@ -112,6 +128,12 @@ bool ffParseSeparatorCommandOptions(FFSeparatorOptions* options, const char* key return true; } + if (ffStrEqualsIgnCase(subKey, "length")) + { + options->length = ffOptionParseUInt32(key, value); + return true; + } + return false; } @@ -137,6 +159,12 @@ void ffParseSeparatorJsonObject(FFSeparatorOptions* options, yyjson_val* module) continue; } + if (ffStrEndsWithIgnCase(key, "length")) + { + options->length = (uint32_t) yyjson_get_uint(val); + continue; + } + ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", key); } } @@ -164,6 +192,8 @@ void ffInitSeparatorOptions(FFSeparatorOptions* options) ffGenerateSeparatorJsonConfig ); ffStrbufInitStatic(&options->string, "-"); + ffStrbufInit(&options->outputColor); + options->length = 0; } void ffDestroySeparatorOptions(FFSeparatorOptions* options) From c0de618177c4ba9da37d0508da049263f922d7a4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 17 Jul 2024 09:29:18 +0800 Subject: [PATCH 27/58] CPU: remove support of min freq detection --- src/detection/cpu/cpu.h | 1 - src/detection/cpu/cpu_apple.c | 26 +++++++++++--------------- src/detection/cpu/cpu_bsd.c | 6 ------ src/detection/cpu/cpu_linux.c | 9 --------- src/modules/cpu/cpu.c | 3 --- src/modules/loadavg/loadavg.c | 1 - 6 files changed, 11 insertions(+), 35 deletions(-) diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index fc9b7e080b..c37fc19973 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -21,7 +21,6 @@ typedef struct FFCPUResult double frequencyBase; // GHz double frequencyMax; // GHz - double frequencyMin; // GHz double frequencyBiosLimit; // GHz FFCPUCore coreTypes[16]; // number of P cores, E cores, etc. diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index e339165589..398c0ca9e4 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -2,6 +2,7 @@ #include "common/sysctl.h" #include "detection/temps/temps_apple.h" #include "util/stringUtils.h" +#include "util/apple/cf_helpers.h" static double detectCpuTemp(const FFstrbuf* cpuName) { @@ -43,23 +44,19 @@ static const char* detectFrequency(FFCPUResult* cpu) if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) return "\"pmgr\" should conform to \"AppleARMIODevice\""; - FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL; - if (IORegistryEntryCreateCFProperties(entryDevice, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) - return "IORegistryEntryCreateCFProperties() failed"; - - uint32_t pMin, eMin, aMax, pCoreLength; - if (ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength) != NULL) // pCore + FF_CFTYPE_AUTO_RELEASE CFDataRef pFreqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, kNilOptions); + if (CFGetTypeID(pFreqProperty) != CFDataGetTypeID()) return "\"voltage-states5-sram\" in \"pmgr\" is not found"; - if (ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL) != NULL) // eCore - return "\"voltage-states1-sram\" in \"pmgr\" is not found"; - cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000); + // voltage-states5-sram stores supported frequencies of pcores from the lowest to the highest + CFIndex pCoreFreqLength = CFDataGetLength(pFreqProperty); + uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(pFreqProperty); + uint32_t pMax = 0; + for (CFIndex i = 0; i < pCoreFreqLength && pStart[i] > 0; i += 4) + pMax = pMax > pStart[i] ? pMax : pStart[i]; - if (pCoreLength >= 8) - { - ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL); - cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000); - } + if (pMax > 0) + cpu->frequencyMax = pMax / 1000.0 / 1000.0 / 1000.0; return NULL; } @@ -67,7 +64,6 @@ static const char* detectFrequency(FFCPUResult* cpu) static const char* detectFrequency(FFCPUResult* cpu) { cpu->frequencyBase = ffSysctlGetInt64("hw.cpufrequency", 0) / 1000.0 / 1000.0 / 1000.0; - cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0; cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000.0 / 1000.0 / 1000.0; if(cpu->frequencyBase != cpu->frequencyBase) { diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 582053eac7..710963a1fb 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -48,11 +48,6 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { // MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000 uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10); - uint32_t fmin = fmax; - uint32_t i = ffStrbufLastIndexC(&buffer, ' '); - if (i < buffer.length) - fmin = (uint32_t) strtoul(buffer.chars + i + 1, NULL, 10); - if (!(cpu->frequencyMin <= fmin)) cpu->frequencyMin = fmin; // Counting for NaN if (!(cpu->frequencyMax >= fmax)) cpu->frequencyMax = fmax; if (options->showPeCoreCount) @@ -66,7 +61,6 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) } } } - cpu->frequencyMin /= 1000; cpu->frequencyMax /= 1000; int clockRate = ffSysctlGetInt("hw.clockrate", 0); diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 3a8df2565f..2886fd2ff6 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -165,14 +165,6 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) else cpu->frequencyMax = fmax; } - uint32_t fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer); - if (fmin > 0) - { - if (cpu->frequencyMin == cpu->frequencyMin) - cpu->frequencyMin = cpu->frequencyMin < fmin ? cpu->frequencyMin : fmin; - else - cpu->frequencyMin = fmin; - } if (options->showPeCoreCount) { @@ -189,7 +181,6 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) } cpu->frequencyBase /= 1e6; cpu->frequencyMax /= 1e6; - cpu->frequencyMin /= 1e6; cpu->frequencyBiosLimit /= 1e6; return true; } diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 044284a632..20607ba84c 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -17,7 +17,6 @@ void ffPrintCPU(FFCPUOptions* options) { FFCPUResult cpu = { .temperature = FF_CPU_TEMP_UNSET, - .frequencyMin = 0.0/0.0, .frequencyMax = 0.0/0.0, .frequencyBase = 0.0/0.0, .frequencyBiosLimit = 0.0/0.0, @@ -202,7 +201,6 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ { FFCPUResult cpu = { .temperature = FF_CPU_TEMP_UNSET, - .frequencyMin = 0.0/0.0, .frequencyMax = 0.0/0.0, .frequencyBase = 0.0/0.0, .frequencyBiosLimit = 0.0/0.0, @@ -234,7 +232,6 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency"); yyjson_mut_obj_add_real(doc, frequency, "base", cpu.frequencyBase); yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax); - yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin); yyjson_mut_obj_add_real(doc, frequency, "biosLimit", cpu.frequencyBiosLimit); yyjson_mut_val* coreTypes = yyjson_mut_obj_add_arr(doc, obj, "coreTypes"); diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 42df9c60cb..0fb9e73de9 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -30,7 +30,6 @@ void ffPrintLoadavg(FFLoadavgOptions* options) { FFCPUResult cpu = { .temperature = FF_CPU_TEMP_UNSET, - .frequencyMin = 0.0/0.0, .frequencyMax = 0.0/0.0, .frequencyBase = 0.0/0.0, .frequencyBiosLimit = 0.0/0.0, From d282050130f61008a2f6f13dcd13248263477d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 17 Jul 2024 10:56:30 +0800 Subject: [PATCH 28/58] CPU: support display frequency in MHz --- doc/json_schema.json | 4 +- src/common/parsing.c | 12 ++++++ src/common/parsing.h | 1 + src/data/help.json | 2 +- src/detection/cpu/cpu.h | 6 +-- src/detection/cpu/cpu_apple.c | 10 ++--- src/detection/cpu/cpu_bsd.c | 12 +++--- src/detection/cpu/cpu_linux.c | 34 +++++------------ src/detection/cpu/cpu_sunos.c | 2 +- src/detection/cpu/cpu_windows.c | 14 +++---- src/modules/cpu/cpu.c | 68 ++++++++++++++++----------------- src/modules/cpu/option.h | 2 +- src/modules/loadavg/loadavg.c | 6 +-- 13 files changed, 84 insertions(+), 89 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 3de8047d94..00e60af19d 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1104,9 +1104,9 @@ "$ref": "#/$defs/temperature" }, "freqNdigits": { - "description": "Set the number of digits to keep after the decimal point when printing CPU frequency", + "description": "Set the number of digits to keep after the decimal point when printing frequency in GHz, or MHz if set to -1", "type": "integer", - "minimum": 0, + "minimum": -1, "maximum": 9, "default": 2 }, diff --git a/src/common/parsing.c b/src/common/parsing.c index 0d1aaba545..1a050aec5e 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -96,6 +96,18 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result) } } +bool ffParseFrequency(uint32_t mhz, FFstrbuf* result, int8_t freqNdigits) +{ + if (mhz == 0) + return false; + + if (freqNdigits >= 0) + ffStrbufAppendF(result, "%.*f GHz", freqNdigits, mhz / 1000.); + else + ffStrbufAppendF(result, "%u MHz", (unsigned) mhz); + return true; +} + void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4) { if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0) diff --git a/src/common/parsing.h b/src/common/parsing.h index f295c74cc0..823d8b2ee9 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -26,3 +26,4 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty); int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2); void ffParseSize(uint64_t bytes, FFstrbuf* result); +bool ffParseFrequency(uint32_t mhz, FFstrbuf* result, int8_t freqNdigits); diff --git a/src/data/help.json b/src/data/help.json index 5b1a8b848a..c195ce23a3 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1179,7 +1179,7 @@ }, { "long": "cpu-freq-ndigits", - "desc": "Set the number of digits to keep after the decimal point when printing CPU frequency", + "desc": "Set the number of digits to keep after the decimal point when printing CPU frequency in GHz", "arg": { "type": "num", "default": 2 diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index c37fc19973..e27a437afb 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -19,9 +19,9 @@ typedef struct FFCPUResult uint16_t coresLogical; uint16_t coresOnline; - double frequencyBase; // GHz - double frequencyMax; // GHz - double frequencyBiosLimit; // GHz + uint32_t frequencyBase; // GHz + uint32_t frequencyMax; // GHz + uint32_t frequencyBiosLimit; // GHz FFCPUCore coreTypes[16]; // number of P cores, E cores, etc. diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 398c0ca9e4..20ef4a0239 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -56,21 +56,21 @@ static const char* detectFrequency(FFCPUResult* cpu) pMax = pMax > pStart[i] ? pMax : pStart[i]; if (pMax > 0) - cpu->frequencyMax = pMax / 1000.0 / 1000.0 / 1000.0; + cpu->frequencyMax = pMax / 1000 / 1000; return NULL; } #else static const char* detectFrequency(FFCPUResult* cpu) { - cpu->frequencyBase = ffSysctlGetInt64("hw.cpufrequency", 0) / 1000.0 / 1000.0 / 1000.0; - cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000.0 / 1000.0 / 1000.0; - if(cpu->frequencyBase != cpu->frequencyBase) + cpu->frequencyBase = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency", 0) / 1000 / 1000); + cpu->frequencyMax = (uint32_t) (ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000 / 1000); + if(cpu->frequencyBase == 0) { unsigned current = 0; size_t size = sizeof(current); if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0) - cpu->frequencyBase = (double) current / 1000.0 / 1000.0 / 1000.0; + cpu->frequencyBase = (uint32_t) (current / 1000 / 1000); } return NULL; } diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 710963a1fb..92773dcdc8 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -44,11 +44,13 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) ffStrbufClear(&buffer); char key[32]; snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i); - if (ffSysctlGetString(key, &buffer) == NULL && buffer.length > 0) + if (ffSysctlGetString(key, &buffer) == NULL) { + if (buffer.length == 0) continue; + // MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000 uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10); - if (!(cpu->frequencyMax >= fmax)) cpu->frequencyMax = fmax; + if (cpu->frequencyMax < fmax) cpu->frequencyMax = fmax; if (options->showPeCoreCount) { @@ -60,11 +62,11 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) cpu->coreTypes[ifreq].count++; } } + else + break; } - cpu->frequencyMax /= 1000; - int clockRate = ffSysctlGetInt("hw.clockrate", 0); - cpu->frequencyBase = clockRate <= 0 ? 0.0/0.0 : clockRate / 1000.0; + cpu->frequencyBase = (uint32_t) ffSysctlGetInt("hw.clockrate", 0); cpu->temperature = FF_CPU_TEMP_UNSET; if (options->temp) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 2886fd2ff6..36f6e1e9d0 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -94,7 +94,7 @@ static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, co bool ok = ffReadFileBuffer(basePath->chars, buffer); ffStrbufSubstrBefore(basePath, baseLen); if (ok) - return (uint32_t) ffStrbufToUInt(buffer, 0); + return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000); if (scalingFileName) { @@ -102,7 +102,7 @@ static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, co ok = ffReadFileBuffer(basePath->chars, buffer); ffStrbufSubstrBefore(basePath, baseLen); if (ok) - return (uint32_t) ffStrbufToUInt(buffer, 0); + return (uint32_t) (ffStrbufToUInt(buffer, 0) / 1000); } return 0; @@ -143,28 +143,15 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) ffStrbufAppendS(&path, entry->d_name); uint32_t fbase = getFrequency(&path, "/base_frequency", NULL, &buffer); if (fbase > 0) - { - if (cpu->frequencyBase == cpu->frequencyBase) - cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase; - else - cpu->frequencyBase = fbase; - } + cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase; + uint32_t fbioslimit = getFrequency(&path, "/bios_limit", NULL, &buffer); if (fbioslimit > 0) - { - if (cpu->frequencyBiosLimit == cpu->frequencyBiosLimit) - cpu->frequencyBiosLimit = cpu->frequencyBiosLimit > fbioslimit ? cpu->frequencyBiosLimit : fbioslimit; - else - cpu->frequencyBiosLimit = fbioslimit; - } + cpu->frequencyBiosLimit = cpu->frequencyBiosLimit > fbioslimit ? cpu->frequencyBiosLimit : fbioslimit; + uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer); if (fmax > 0) - { - if (cpu->frequencyMax == cpu->frequencyMax) - cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax; - else - cpu->frequencyMax = fmax; - } + cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax; if (options->showPeCoreCount) { @@ -179,9 +166,6 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) ffStrbufSubstrBefore(&path, baseLen); } } - cpu->frequencyBase /= 1e6; - cpu->frequencyMax /= 1e6; - cpu->frequencyBiosLimit /= 1e6; return true; } @@ -263,8 +247,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) cpu->coresOnline = (uint16_t) get_nprocs(); cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical); - if (!detectFrequency(cpu, options) || cpu->frequencyBase != cpu->frequencyBase) - cpu->frequencyBase = ffStrbufToDouble(&cpuMHz) / 1000; + if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0) + cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0); if(cpuUarch.length > 0) { diff --git a/src/detection/cpu/cpu_sunos.c b/src/detection/cpu/cpu_sunos.c index 4d66c69ab0..67954ee306 100644 --- a/src/detection/cpu/cpu_sunos.c +++ b/src/detection/cpu/cpu_sunos.c @@ -31,7 +31,7 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe } { kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz"); - cpu->frequencyBase = kn->value.ui32 / 1000.; + cpu->frequencyBase = kn->value.ui32; } ks = kstat_lookup(kc, "unix", -1, "system_misc"); diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 1e6ca5ff63..fa96bb6ffc 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -65,8 +65,8 @@ inline static const char* detectSpeedByCpuid(FFCPUResult* cpu) return "Unsupported instruction"; // cpuid returns 0 MHz when hyper-v is enabled - if (base) cpu->frequencyBase = base / 1000.0; - if (max) cpu->frequencyMax = max / 1000.0; + if (base) cpu->frequencyBase = base; + if (max) cpu->frequencyMax = max; return NULL; } @@ -97,7 +97,7 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu) return "No active CPU is found in SMBIOS data"; } - double speed = data->MaxSpeed / 1000.0; + uint32_t speed = data->MaxSpeed; // Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2) return "Possible invalid CPU max speed in SMBIOS data. See #800"; @@ -159,7 +159,7 @@ static const char* detectByRegistry(FFCPUResult* cpu) uint32_t mhz; if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL)) - cpu->frequencyBase = mhz / 1000.0; + cpu->frequencyBase = mhz; return NULL; } @@ -180,8 +180,8 @@ static const char* detectCoreTypes(FFCPUResult* cpu) ++cpu->coreTypes[ifreq].count; } - if (cpu->frequencyBase != cpu->frequencyBase) - cpu->frequencyBase = pinfo->MaxMhz / 1000.0; + if (cpu->frequencyBase == 0) + cpu->frequencyBase = pinfo->MaxMhz; return NULL; } @@ -196,7 +196,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) detectSpeedByCpuid(cpu); if (options->showPeCoreCount) detectCoreTypes(cpu); - if (cpu->frequencyMax != cpu->frequencyMax) + if (cpu->frequencyMax == 0) detectMaxSpeedBySmbios(cpu); if(options->temp) diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 20607ba84c..ebe6f297ac 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -17,9 +17,9 @@ void ffPrintCPU(FFCPUOptions* options) { FFCPUResult cpu = { .temperature = FF_CPU_TEMP_UNSET, - .frequencyMax = 0.0/0.0, - .frequencyBase = 0.0/0.0, - .frequencyBiosLimit = 0.0/0.0, + .frequencyMax = 0, + .frequencyBase = 0, + .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; @@ -71,13 +71,16 @@ void ffPrintCPU(FFCPUOptions* options) else if(cpu.coresOnline > 1) ffStrbufAppendF(&str, " (%u)", cpu.coresOnline); - double freq = cpu.frequencyBiosLimit; - if(!(freq > 0.0000001)) + uint32_t freq = cpu.frequencyBiosLimit; + if(freq == 0) freq = cpu.frequencyMax; - if(!(freq > 0.0000001)) + if(freq == 0) freq = cpu.frequencyBase; - if(freq > 0.0000001) - ffStrbufAppendF(&str, " @ %.*f GHz", options->freqNdigits, freq); + if(freq > 0) + { + ffStrbufAppendS(&str, " @ "); + ffParseFrequency(freq, &str, options->freqNdigits); + } if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET { @@ -89,19 +92,12 @@ void ffPrintCPU(FFCPUOptions* options) } else { - char freqBase[32], freqMax[32], freqBioslimit[32]; - if (cpu.frequencyBase > 0) - snprintf(freqBase, sizeof(freqBase), "%.*f", options->freqNdigits, cpu.frequencyBase); - else - freqBase[0] = 0; - if (cpu.frequencyMax > 0) - snprintf(freqMax, sizeof(freqMax), "%.*f", options->freqNdigits, cpu.frequencyMax); - else - freqMax[0] = 0; - if (cpu.frequencyBiosLimit > 0) - snprintf(freqBioslimit, sizeof(freqBioslimit), "%.*f", options->freqNdigits, cpu.frequencyBiosLimit); - else - freqBioslimit[0] = 0; + FF_STRBUF_AUTO_DESTROY freqBase = ffStrbufCreate(); + ffParseFrequency(cpu.frequencyBase, &freqBase, options->freqNdigits); + FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate(); + ffParseFrequency(cpu.frequencyBase, &freqBase, options->freqNdigits); + FF_STRBUF_AUTO_DESTROY freqBioslimit = ffStrbufCreate(); + ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit, options->freqNdigits); FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs); @@ -111,11 +107,11 @@ void ffPrintCPU(FFCPUOptions* options) {FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresPhysical, "cores-physical"}, {FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresLogical, "cores-logical"}, {FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresOnline, "cores-online"}, - {FF_FORMAT_ARG_TYPE_STRING, freqBase, "freq-base"}, - {FF_FORMAT_ARG_TYPE_STRING, freqMax, "freq-max"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &freqBase, "freq-base"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &freqMax, "freq-max"}, {FF_FORMAT_ARG_TYPE_STRBUF, &tempStr, "temperature"}, {FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes, "core-types"}, - {FF_FORMAT_ARG_TYPE_STRING, freqBioslimit, "freq-bios-limit"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &freqBioslimit, "freq-bios-limit"}, })); } } @@ -136,7 +132,7 @@ bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char if (ffStrEqualsIgnCase(subKey, "freq-ndigits")) { - options->freqNdigits = (uint8_t) ffOptionParseUInt32(key, value); + options->freqNdigits = (int8_t) ffOptionParseInt32(key, value); return true; } @@ -167,7 +163,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) if (ffStrEqualsIgnCase(key, "freqNdigits")) { - options->freqNdigits = (uint8_t) yyjson_get_uint(val); + options->freqNdigits = (int8_t) yyjson_get_int(val); continue; } @@ -191,7 +187,7 @@ void ffGenerateCPUJsonConfig(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig); if (defaultOptions.freqNdigits != options->freqNdigits) - yyjson_mut_obj_add_uint(doc, module, "freqNdigits", options->freqNdigits); + yyjson_mut_obj_add_int(doc, module, "freqNdigits", options->freqNdigits); if (defaultOptions.showPeCoreCount != options->showPeCoreCount) yyjson_mut_obj_add_bool(doc, module, "showPeCoreCount", options->showPeCoreCount); @@ -201,9 +197,9 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ { FFCPUResult cpu = { .temperature = FF_CPU_TEMP_UNSET, - .frequencyMax = 0.0/0.0, - .frequencyBase = 0.0/0.0, - .frequencyBiosLimit = 0.0/0.0, + .frequencyMax = 0, + .frequencyBase = 0, + .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; @@ -230,9 +226,9 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_uint(doc, cores, "online", cpu.coresOnline); yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency"); - yyjson_mut_obj_add_real(doc, frequency, "base", cpu.frequencyBase); - yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax); - yyjson_mut_obj_add_real(doc, frequency, "biosLimit", cpu.frequencyBiosLimit); + yyjson_mut_obj_add_uint(doc, frequency, "base", cpu.frequencyBase); + yyjson_mut_obj_add_uint(doc, frequency, "max", cpu.frequencyMax); + yyjson_mut_obj_add_uint(doc, frequency, "biosLimit", cpu.frequencyBiosLimit); yyjson_mut_val* coreTypes = yyjson_mut_obj_add_arr(doc, obj, "coreTypes"); for (uint32_t i = 0; i < sizeof (cpu.coreTypes) / sizeof (cpu.coreTypes[0]) && cpu.coreTypes[i].count > 0; i++) @@ -257,11 +253,11 @@ void ffPrintCPUHelpFormat(void) "Physical core count - cores-physical", "Logical core count - cores-logical", "Online core count - cores-online", - "Base frequency - freq-base", - "Max frequency - freq-max", + "Base frequency (formatted) - freq-base", + "Max frequency (formatted) - freq-max", "Temperature (formatted) - temperature", "Logical core count grouped by frequency - core-types", - "Bios limited frequency - freq-bios-limit", + "Bios limited frequency (formatted) - freq-bios-limit", })); } diff --git a/src/modules/cpu/option.h b/src/modules/cpu/option.h index fc2c6d1746..ff3cfd42f0 100644 --- a/src/modules/cpu/option.h +++ b/src/modules/cpu/option.h @@ -11,6 +11,6 @@ typedef struct FFCPUOptions bool temp; FFColorRangeConfig tempConfig; - uint8_t freqNdigits; + int8_t freqNdigits; bool showPeCoreCount; } FFCPUOptions; diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 0fb9e73de9..5d7de35820 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -30,9 +30,9 @@ void ffPrintLoadavg(FFLoadavgOptions* options) { FFCPUResult cpu = { .temperature = FF_CPU_TEMP_UNSET, - .frequencyMax = 0.0/0.0, - .frequencyBase = 0.0/0.0, - .frequencyBiosLimit = 0.0/0.0, + .frequencyMax = 0, + .frequencyBase = 0, + .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; From 7393bcdf057bfbdfa15154b9f89fc1306288fa22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 17 Jul 2024 14:11:52 +0800 Subject: [PATCH 29/58] CI: disable `--stat` which messes output --- .github/workflows/ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb0c248ceb..2e8e234140 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch -c presets/ci.jsonc + run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json run: time ./fastfetch -c presets/ci.jsonc --format json @@ -99,7 +99,7 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch -c presets/ci.jsonc + run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json run: time ./fastfetch -c presets/ci.jsonc --format json @@ -146,7 +146,7 @@ jobs: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features - time ./fastfetch -c presets/ci.jsonc + time ./fastfetch -c presets/ci.jsonc --stat false time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch @@ -185,7 +185,7 @@ jobs: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features - time ./fastfetch -c presets/ci.jsonc + time ./fastfetch -c presets/ci.jsonc --stat false time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch @@ -220,7 +220,7 @@ jobs: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features - time ./fastfetch -c presets/ci.jsonc + time ./fastfetch -c presets/ci.jsonc --stat false time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch @@ -259,7 +259,7 @@ jobs: - name: run run: | ./fastfetch --list-features - time ./fastfetch -c presets/ci.jsonc + time ./fastfetch -c presets/ci.jsonc --stat false time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch @@ -300,7 +300,7 @@ jobs: - name: run run: | ./fastfetch --list-features - time ./fastfetch -c presets/ci.jsonc + time ./fastfetch -c presets/ci.jsonc --stat false time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch @@ -348,7 +348,7 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch -c presets/ci.jsonc + run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json run: time ./fastfetch -c presets/ci.jsonc --format json @@ -477,7 +477,7 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch -c presets/ci.jsonc + run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json run: time ./fastfetch -c presets/ci.jsonc --format json @@ -547,7 +547,7 @@ jobs: run: curl -LO https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/raw/master/ags_lib/lib/amd_ags_x86.dll - name: run fastfetch - run: time ./fastfetch -c presets/ci.jsonc + run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json run: time ./fastfetch -c presets/ci.jsonc --format json From 46abc4f5f7e612cbd1508f48631832dc6684621e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 17 Jul 2024 14:42:09 +0800 Subject: [PATCH 30/58] CPU: move option `freqNdigits` into display section --- doc/json_schema.json | 21 ++++++++++++++------- src/common/parsing.c | 8 +++++--- src/common/parsing.h | 2 +- src/data/help.json | 16 ++++++++-------- src/modules/cpu/cpu.c | 20 +++++--------------- src/modules/cpu/option.h | 1 - src/options/display.c | 25 +++++++++++++++++++++++-- src/options/display.h | 1 + 8 files changed, 57 insertions(+), 37 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 00e60af19d..419e742b8a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -574,6 +574,20 @@ } } }, + "freq": { + "type": "object", + "additionalProperties": false, + "description": "Set how frequency values should be displayed", + "properties": { + "ndigits": { + "type": "integer", + "description": "Set the number of digits to keep after the decimal point when formatting frequency values\nA possitive value will show the frequency in GHz of decimal\n-1 will show the frequency in MHz", + "minimum": -1, + "maximum": 9, + "default": 2 + } + } + }, "noBuffer": { "type": "boolean", "description": "Whether to disable the stdout application buffer", @@ -1103,13 +1117,6 @@ "temp": { "$ref": "#/$defs/temperature" }, - "freqNdigits": { - "description": "Set the number of digits to keep after the decimal point when printing frequency in GHz, or MHz if set to -1", - "type": "integer", - "minimum": -1, - "maximum": 9, - "default": 2 - }, "showPeCoreCount": { "description": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported", "type": "boolean", diff --git a/src/common/parsing.c b/src/common/parsing.c index 1a050aec5e..ad21436638 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -96,13 +96,15 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result) } } -bool ffParseFrequency(uint32_t mhz, FFstrbuf* result, int8_t freqNdigits) +bool ffParseFrequency(uint32_t mhz, FFstrbuf* result) { if (mhz == 0) return false; - if (freqNdigits >= 0) - ffStrbufAppendF(result, "%.*f GHz", freqNdigits, mhz / 1000.); + int8_t ndigits = instance.config.display.freqNdigits; + + if (ndigits >= 0) + ffStrbufAppendF(result, "%.*f GHz", ndigits, mhz / 1000.); else ffStrbufAppendF(result, "%u MHz", (unsigned) mhz); return true; diff --git a/src/common/parsing.h b/src/common/parsing.h index 823d8b2ee9..722969ffb2 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -26,4 +26,4 @@ void ffVersionToPretty(const FFVersion* version, FFstrbuf* pretty); int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2); void ffParseSize(uint64_t bytes, FFstrbuf* result); -bool ffParseFrequency(uint32_t mhz, FFstrbuf* result, int8_t freqNdigits); +bool ffParseFrequency(uint32_t mhz, FFstrbuf* result); diff --git a/src/data/help.json b/src/data/help.json index c195ce23a3..7fc18e82e8 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -688,6 +688,14 @@ "default": "YB" } }, + { + "long": "freq-ndigits", + "desc": "Set the number of digits to keep after the decimal point when printing CPU / GPU frequency in GHz", + "arg": { + "type": "num", + "default": 2 + } + }, { "long": "temp-unit", "desc": "Set the unit of the temperature", @@ -1177,14 +1185,6 @@ "default": false } }, - { - "long": "cpu-freq-ndigits", - "desc": "Set the number of digits to keep after the decimal point when printing CPU frequency in GHz", - "arg": { - "type": "num", - "default": 2 - } - }, { "long": "cpu-show-pe-core-count", "desc": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index ebe6f297ac..a0df7cb7f5 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -79,7 +79,7 @@ void ffPrintCPU(FFCPUOptions* options) if(freq > 0) { ffStrbufAppendS(&str, " @ "); - ffParseFrequency(freq, &str, options->freqNdigits); + ffParseFrequency(freq, &str); } if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET @@ -93,11 +93,11 @@ void ffPrintCPU(FFCPUOptions* options) else { FF_STRBUF_AUTO_DESTROY freqBase = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyBase, &freqBase, options->freqNdigits); + ffParseFrequency(cpu.frequencyBase, &freqBase); FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyBase, &freqBase, options->freqNdigits); + ffParseFrequency(cpu.frequencyBase, &freqBase); FF_STRBUF_AUTO_DESTROY freqBioslimit = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit, options->freqNdigits); + ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit); FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs); @@ -130,12 +130,6 @@ bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char if (ffTempsParseCommandOptions(key, subKey, value, &options->temp, &options->tempConfig)) return true; - if (ffStrEqualsIgnCase(subKey, "freq-ndigits")) - { - options->freqNdigits = (int8_t) ffOptionParseInt32(key, value); - return true; - } - if (ffStrEqualsIgnCase(subKey, "show-pe-core-count")) { options->showPeCoreCount = ffOptionParseBoolean(value); @@ -163,7 +157,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) if (ffStrEqualsIgnCase(key, "freqNdigits")) { - options->freqNdigits = (int8_t) yyjson_get_int(val); + ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits"); continue; } @@ -186,9 +180,6 @@ void ffGenerateCPUJsonConfig(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig); - if (defaultOptions.freqNdigits != options->freqNdigits) - yyjson_mut_obj_add_int(doc, module, "freqNdigits", options->freqNdigits); - if (defaultOptions.showPeCoreCount != options->showPeCoreCount) yyjson_mut_obj_add_bool(doc, module, "showPeCoreCount", options->showPeCoreCount); } @@ -277,7 +268,6 @@ void ffInitCPUOptions(FFCPUOptions* options) ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; options->tempConfig = (FFColorRangeConfig) { 60, 80 }; - options->freqNdigits = 2; options->showPeCoreCount = false; } diff --git a/src/modules/cpu/option.h b/src/modules/cpu/option.h index ff3cfd42f0..af2c87a3f7 100644 --- a/src/modules/cpu/option.h +++ b/src/modules/cpu/option.h @@ -11,6 +11,5 @@ typedef struct FFCPUOptions bool temp; FFColorRangeConfig tempConfig; - int8_t freqNdigits; bool showPeCoreCount; } FFCPUOptions; diff --git a/src/options/display.c b/src/options/display.c index c0917b1151..eb79a90dbe 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -208,8 +208,14 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va yyjson_arr_foreach(val, idx, max, item) ffStrbufInitS(ffListAdd(&options->constants), yyjson_get_str(item)); } - else if (ffStrEqualsIgnCase(key, "tsVersion")) - return "display.tsVersion has been renamed to general.detectVersion"; + else if (ffStrEqualsIgnCase(key, "freq")) + { + if (!yyjson_is_obj(val)) + return "display.freq must be an object"; + + yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); + if (ndigits) options->freqNdigits = (int8_t) yyjson_get_int(ndigits); + } else return "Unknown display property"; } @@ -366,6 +372,12 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key else return false; } + else if(ffStrStartsWithIgnCase(key, "--freq-")) + { + const char* subkey = key + strlen("--freq-"); + if(ffStrEqualsIgnCase(subkey, "ndigits")) + options->freqNdigits = (int8_t) ffOptionParseInt32(key, value); + } else return false; return true; @@ -413,6 +425,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) ffStrbufInitStatic(&options->percentColorGreen, FF_COLOR_FG_GREEN); ffStrbufInitStatic(&options->percentColorYellow, instance.state.terminalLightTheme ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_LIGHT_YELLOW); ffStrbufInitStatic(&options->percentColorRed, instance.state.terminalLightTheme ? FF_COLOR_FG_RED : FF_COLOR_FG_LIGHT_RED); + options->freqNdigits = 2; ffListInit(&options->constants, sizeof(FFstrbuf)); } @@ -595,6 +608,14 @@ void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_do if (options->keyWidth != defaultOptions.keyWidth) yyjson_mut_obj_add_uint(doc, obj, "keyWidth", options->keyWidth); + { + yyjson_mut_val* freq = yyjson_mut_obj(doc); + if (options->freqNdigits != defaultOptions.freqNdigits) + yyjson_mut_obj_add_int(doc, freq, "ndigits", options->freqNdigits); + if (yyjson_mut_obj_size(freq) > 0) + yyjson_mut_obj_add_val(doc, obj, "freq", freq); + } + if (yyjson_mut_obj_size(obj) > 0) yyjson_mut_obj_add_val(doc, doc->root, "display", obj); } diff --git a/src/options/display.h b/src/options/display.h index ba0707e907..75125ce767 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -53,6 +53,7 @@ typedef struct FFOptionsDisplay FFstrbuf percentColorRed; bool noBuffer; uint32_t keyWidth; + int8_t freqNdigits; FFlist constants; // list of FFstrbuf } FFOptionsDisplay; From 408a2d731a91dd90602dd7e9ae12d4b0f7fa4fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 17 Jul 2024 14:52:35 +0800 Subject: [PATCH 31/58] GPU: support printing frequency in MHz --- src/detection/gpu/gpu.h | 4 ++-- src/detection/gpu/gpu_amd.c | 2 +- src/detection/gpu/gpu_driver_specific.h | 2 +- src/detection/gpu/gpu_intel.c | 2 +- src/detection/gpu/gpu_linux.c | 4 ++-- src/detection/gpu/gpu_nvidia.c | 6 +----- src/detection/opencl/opencl.c | 2 +- src/modules/gpu/gpu.c | 7 +++++-- 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 0ba9ea74ee..e3e50dacd5 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -5,7 +5,7 @@ #define FF_GPU_TEMP_UNSET (0/0.0) #define FF_GPU_CORE_COUNT_UNSET -1 #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) -#define FF_GPU_FREQUENCY_UNSET (0/0.0) +#define FF_GPU_FREQUENCY_UNSET 0 extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -32,7 +32,7 @@ typedef struct FFGPUResult FFstrbuf platformApi; double temperature; int32_t coreCount; - double frequency; // Maximum time clock frequency in GHz + uint32_t frequency; // Maximum time clock frequency in MHz FFGPUMemory dedicated; FFGPUMemory shared; uint64_t deviceId; // Used internally, may be uninitialized diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 8df677f65f..d50451ef46 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -60,7 +60,7 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu } if (result.frequency) - *result.frequency = device->coreClock / 1000.; // Maximum frequency + *result.frequency = (uint32_t) device->coreClock; // Maximum frequency if (result.type) *result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 8405e0de0e..8c935ff8c5 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -41,7 +41,7 @@ typedef struct FFGpuDriverResult FFGPUMemory* memory; uint32_t* coreCount; FFGPUType* type; - double* frequency; + uint32_t* frequency; } FFGpuDriverResult; const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index 7da51cc07b..3d4638cd3f 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -191,7 +191,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe maxValue = props.max; } } - *result.frequency = maxValue / 1000; + *result.frequency = (uint32_t) (maxValue + 0.5); } } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index e27a3e3cec..7b0fb54624 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -152,7 +152,7 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* ffStrbufAppendS(pciDir, "/gt_max_freq_mhz"); } if (ffReadFileBuffer(pciDir->chars, buffer)) - gpu->frequency = ffStrbufToDouble(buffer) / 1000.0; + gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0); } static bool loadPciIds(FFstrbuf* pciids) @@ -346,7 +346,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F }) >= 0) { gpu->coreCount = (int) paramsGlobal.num_cores_total_active; - gpu->frequency = paramsGlobal.max_frequency_khz / 1e6; + gpu->frequency = paramsGlobal.max_frequency_khz / 1000; gpu->deviceId = paramsGlobal.chip_id; } } diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 84a7938004..683e681ef2 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -122,11 +122,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR nvmlData.ffnvmlDeviceGetNumGpuCores(device, result.coreCount); if (result.frequency) - { - uint32_t clockMHz; - if (nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, &clockMHz) == NVML_SUCCESS) - *result.frequency = clockMHz / 1000.; - } + nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency); return NULL; diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 0626dd4d39..462f3aff20 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -116,7 +116,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) { cl_uint value; if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(value), &value, NULL) == CL_SUCCESS) - gpu->frequency = value / 1000.; + gpu->frequency = value; } { diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index d7cecf5163..22cef578cd 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -39,8 +39,11 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu if(gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) ffStrbufAppendF(&output, " (%d)", gpu->coreCount); - if(gpu->frequency == gpu->frequency && gpu->frequency > 0 /* Inactive? */) - ffStrbufAppendF(&output, " @ %.2f GHz", gpu->frequency); + if(gpu->frequency > 0) + { + ffStrbufAppendS(&output, " @ "); + ffParseFrequency(gpu->frequency, &output); + } if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET { From 63a0faa1d92837537c633fde523a837baab07e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 17 Jul 2024 15:51:15 +0800 Subject: [PATCH 32/58] GPU (macOS): support GPU frequency detection for Apple Silicon Also refactor CPU freq detection code --- src/detection/cpu/cpu_apple.c | 19 +++++++++------- src/detection/gpu/gpu_apple.c | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 20ef4a0239..ad6852732d 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -2,7 +2,6 @@ #include "common/sysctl.h" #include "detection/temps/temps_apple.h" #include "util/stringUtils.h" -#include "util/apple/cf_helpers.h" static double detectCpuTemp(const FFstrbuf* cpuName) { @@ -44,15 +43,19 @@ static const char* detectFrequency(FFCPUResult* cpu) if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) return "\"pmgr\" should conform to \"AppleARMIODevice\""; - FF_CFTYPE_AUTO_RELEASE CFDataRef pFreqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, kNilOptions); - if (CFGetTypeID(pFreqProperty) != CFDataGetTypeID()) + FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, kNilOptions); + if (CFGetTypeID(freqProperty) != CFDataGetTypeID()) return "\"voltage-states5-sram\" in \"pmgr\" is not found"; - // voltage-states5-sram stores supported frequencies of pcores from the lowest to the highest - CFIndex pCoreFreqLength = CFDataGetLength(pFreqProperty); - uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(pFreqProperty); - uint32_t pMax = 0; - for (CFIndex i = 0; i < pCoreFreqLength && pStart[i] > 0; i += 4) + // voltage-states5-sram stores supported pairs of pcores from the lowest to the highest + // voltage-states1-sram stores ecores' + CFIndex propLength = CFDataGetLength(freqProperty); + if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) + return "Invalid \"voltage-states5-sram\" length"; + + uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty); + uint32_t pMax = *pStart; + for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */) pMax = pMax > pStart[i] ? pMax : pStart[i]; if (pMax > 0) diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 6bc0ee48eb..c63974d1f9 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -36,6 +36,43 @@ static double detectGpuTemp(const FFstrbuf* gpuName) return result; } +#ifdef __aarch64__ +#include "util/apple/cf_helpers.h" + +#include + +static const char* detectFrequency(FFGPUResult* gpu) +{ + // https://github.com/giampaolo/psutil/pull/2222/files + + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr")); + if (!entryDevice) + return "IOServiceGetMatchingServices() failed"; + + if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) + return "\"pmgr\" should conform to \"AppleARMIODevice\""; + + FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states9-sram"), kCFAllocatorDefault, kNilOptions); + if (CFGetTypeID(freqProperty) != CFDataGetTypeID()) + return "\"voltage-states9-sram\" in \"pmgr\" is not found"; + + // voltage-states5-sram stores supported pairs of gpu from the lowest to the highest + CFIndex propLength = CFDataGetLength(freqProperty); + if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) + return "Invalid \"voltage-states9-sram\" length"; + + uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty); + uint32_t pMax = *pStart; + for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */) + pMax = pMax > pStart[i] ? pMax : pStart[i]; + + if (pMax > 0) + gpu->frequency = pMax / 1000 / 1000; + + return NULL; +} +#endif + const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL; @@ -94,6 +131,11 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->type = FF_GPU_TYPE_INTEGRATED; else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD) gpu->type = FF_GPU_TYPE_DISCRETE; + + #ifdef __aarch64__ + if (vendorStr == FF_GPU_VENDOR_NAME_APPLE) + detectFrequency(gpu); + #endif } gpu->temperature = options->temp ? detectGpuTemp(&gpu->name) : FF_GPU_TEMP_UNSET; From 6b7403281bc444de0b6f45d8eef5f4fbd869aae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 17 Jul 2024 16:00:59 +0800 Subject: [PATCH 33/58] JsonSchema: fix typo [ci skip] --- doc/json_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 419e742b8a..ec7bc3ead1 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -581,7 +581,7 @@ "properties": { "ndigits": { "type": "integer", - "description": "Set the number of digits to keep after the decimal point when formatting frequency values\nA possitive value will show the frequency in GHz of decimal\n-1 will show the frequency in MHz", + "description": "Set the number of digits to keep after the decimal point when formatting frequency values\nA positive value will show the frequency in GHz of decimal\n-1 will show the frequency in MHz", "minimum": -1, "maximum": 9, "default": 2 From 2a49f1d0ebc995ac78a86bdedfba29f521d24b0d Mon Sep 17 00:00:00 2001 From: mhkdepauw <87832202+mhkdepauw@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:55:31 +0200 Subject: [PATCH 34/58] Doc: Small typo corrected in man page (#1102) --- doc/fastfetch.1.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/fastfetch.1.in b/doc/fastfetch.1.in index 35f421c810..7503b47be6 100644 --- a/doc/fastfetch.1.in +++ b/doc/fastfetch.1.in @@ -98,7 +98,7 @@ config files, see the CONFIGURATION section .B \-\-gen\-config \fI[file] Generate a config file with options specified on the command line. -If \fIfile\fR is specified, the configuration will written to the +If \fIfile\fR is specified, the configuration will be written to the file, otherwise it will be written to stdout. .TP From 0d71ae7f9731d88b1d225dbd6818615ca34699bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 18 Jul 2024 13:46:26 +0800 Subject: [PATCH 35/58] Monitor (macOS): detect maximum refresh rate --- src/detection/monitor/monitor.h | 1 + src/detection/monitor/monitor_apple.m | 13 +++++++++++++ src/detection/monitor/monitor_linux.c | 1 + src/detection/monitor/monitor_windows.c | 1 + src/modules/monitor/monitor.c | 8 +++++++- 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/detection/monitor/monitor.h b/src/detection/monitor/monitor.h index a6150e5d36..4066f1178d 100644 --- a/src/detection/monitor/monitor.h +++ b/src/detection/monitor/monitor.h @@ -5,6 +5,7 @@ typedef struct FFMonitorResult FFstrbuf name; uint32_t width; // native / maximum resolution, in pixels uint32_t height; // native / maximum resolution, in pixels + double refreshRate;// maximum refresh rate in native resolution, in Hz uint32_t physicalWidth; // in mm uint32_t physicalHeight; // in mm bool hdrCompatible; diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 8d99e5c11a..2c4a1e3c2f 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -102,6 +102,19 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) detectHdrSupportWithNSScreen(display); monitor->serial = CGDisplaySerialNumber((CGDirectDisplayID) display->id); + FF_CFTYPE_AUTO_RELEASE CFArrayRef modes = CGDisplayCopyAllDisplayModes((CGDirectDisplayID) display->id, NULL); + double maxRefreshRate = 0; + for (uint32_t j = 0; j < CFArrayGetCount(modes); ++j) + { + CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, j); + if (CGDisplayModeGetWidth(mode) == (uint32_t) width && CGDisplayModeGetHeight(mode) == (uint32_t) height) + { + double refreshRate = CGDisplayModeGetRefreshRate(mode); + if (refreshRate > maxRefreshRate) maxRefreshRate = refreshRate; + } + } + monitor->refreshRate = maxRefreshRate; + int64_t year, week; if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayYearManufacture"), &year) == NULL) monitor->manufactureYear = (uint16_t) year; diff --git a/src/detection/monitor/monitor_linux.c b/src/detection/monitor/monitor_linux.c index 8d0f5ec114..b6c7e361e2 100644 --- a/src/detection/monitor/monitor_linux.c +++ b/src/detection/monitor/monitor_linux.c @@ -61,6 +61,7 @@ const char* ffDetectMonitor(FFlist* results) ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); + display->refreshRate = 0; } ffStrbufSubstrBefore(&drmDir, drmDirLength); diff --git a/src/detection/monitor/monitor_windows.c b/src/detection/monitor/monitor_windows.c index b695cf67a1..6bd7788ba0 100644 --- a/src/detection/monitor/monitor_windows.c +++ b/src/detection/monitor/monitor_windows.c @@ -49,6 +49,7 @@ const char* ffDetectMonitor(FFlist* results) ffStrbufInit(&display->name); ffEdidGetName(edidData, &display->name); ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); + display->refreshRate = 0; } return NULL; } diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index f1c62963e1..45b568cf65 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -6,7 +6,7 @@ #include -#define FF_MONITOR_NUM_FORMAT_ARGS 10 +#define FF_MONITOR_NUM_FORMAT_ARGS 11 void ffPrintMonitor(FFMonitorOptions* options) { @@ -52,6 +52,8 @@ void ffPrintMonitor(FFMonitorOptions* options) ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); printf("%ux%u px", display->width, display->height); + if (display->refreshRate > 0) + printf(" @ %.2f Hz", display->refreshRate); if (inch > 0) printf(" - %ux%u mm (%.2f inches, %.2f ppi)\n", display->physicalWidth, display->physicalHeight, inch, ppi); else @@ -79,6 +81,7 @@ void ffPrintMonitor(FFMonitorOptions* options) {FF_FORMAT_ARG_TYPE_UINT16, &display->manufactureYear, "manufacture-year"}, {FF_FORMAT_ARG_TYPE_UINT16, &display->manufactureWeek, "manufacture-week"}, {FF_FORMAT_ARG_TYPE_STRING, buf, "serial"}, + {FF_FORMAT_ARG_TYPE_DOUBLE, buf, "refresh-rate"}, })); } @@ -153,6 +156,8 @@ void ffGenerateMonitorJsonResult(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjs yyjson_mut_obj_add_uint(doc, physical, "height", item->physicalHeight); yyjson_mut_obj_add_uint(doc, physical, "width", item->physicalWidth); + yyjson_mut_obj_add_real(doc, obj, "refreshRate", item->refreshRate); + if (item->manufactureYear) { yyjson_mut_val* manufactureDate = yyjson_mut_obj_add_obj(doc, obj, "manufactureDate"); @@ -190,6 +195,7 @@ void ffPrintMonitorHelpFormat(void) "Year of manufacturing - manufacture-year", "Nth week of manufacturing in the year - manufacture-week", "Serial number - serial", + "Maximum refresh rate in Hz - refresh-rate", })); } From 121cbde661869ee4ca9de9e0f96381db13f7e307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 18 Jul 2024 15:09:04 +0800 Subject: [PATCH 36/58] Monitor (Windows): detect maximum refresh rate --- src/detection/monitor/monitor_windows.c | 132 +++++++++++++++++------- 1 file changed, 93 insertions(+), 39 deletions(-) diff --git a/src/detection/monitor/monitor_windows.c b/src/detection/monitor/monitor_windows.c index 6bd7788ba0..03cc568781 100644 --- a/src/detection/monitor/monitor_windows.c +++ b/src/detection/monitor/monitor_windows.c @@ -1,55 +1,109 @@ #include "monitor.h" -#include "common/io/io.h" #include "util/edidHelper.h" -#include "util/mallocHelper.h" -#include "util/stringUtils.h" #include "util/windows/registry.h" -#include "util/windows/unicode.h" #include -#include -#include - -static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev) -{ - if(*hdev) - SetupDiDestroyDeviceInfoList(*hdev); -} const char* ffDetectMonitor(FFlist* results) { - //https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices - HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) = - SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, 0, 0, DIGCF_PRESENT); - if(hdev == INVALID_HANDLE_VALUE) - return "SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR) failed"; - - SP_DEVINFO_DATA did = { .cbSize = sizeof(did) }; - for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev) + DISPLAYCONFIG_PATH_INFO paths[128]; + uint32_t pathCount = sizeof(paths) / sizeof(paths[0]); + DISPLAYCONFIG_MODE_INFO modes[256]; + uint32_t modeCount = sizeof(modes) / sizeof(modes[0]); + + if (QueryDisplayConfig( + QDC_ONLY_ACTIVE_PATHS, + &pathCount, + paths, + &modeCount, + modes, + NULL) != ERROR_SUCCESS) + return "QueryDisplayConfig() failed"; + + if (pathCount == 0) + return "QueryDisplayConfig() returns 0 paths"; + + for (uint32_t i = 0; i < pathCount; ++i) { - FF_HKEY_AUTO_DESTROY hKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); - if (!hKey) continue; + DISPLAYCONFIG_PATH_INFO* path = &paths[i]; - FF_AUTO_FREE uint8_t* edidData = NULL; - uint32_t edidLength = 0; - if (!ffRegReadData(hKey, L"EDID", &edidData, &edidLength, NULL)) continue; - if (edidLength == 0 || edidLength % 128 != 0) + DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = { + .header = { + .type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME, + .size = sizeof(targetName), + .adapterId = path->targetInfo.adapterId, + .id = path->targetInfo.id, + }, + }; + if (DisplayConfigGetDeviceInfo(&targetName.header) != ERROR_SUCCESS) continue; - uint32_t width, height; - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width == 0 || height == 0) continue; - - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - display->width = width; - display->height = height; - ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, edidLength); // Doesn't work. edidLength is always 128 - ffStrbufInit(&display->name); - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - display->refreshRate = 0; + wchar_t regPath[256] = L"SYSTEM\\CurrentControlSet\\Enum"; + wchar_t* pRegPath = regPath + strlen("SYSTEM\\CurrentControlSet\\Enum"); + wchar_t* pDevPath = targetName.monitorDevicePath + strlen("\\\\?"); + while (*pDevPath && *pDevPath != L'{') + { + if (*pDevPath == L'#') + *pRegPath = L'\\'; + else + *pRegPath = *pDevPath; + ++pRegPath; + ++pDevPath; + assert(pRegPath < regPath + sizeof(regPath) / sizeof(wchar_t) + strlen("Device Parameters")); + } + wcscpy(pRegPath, L"Device Parameters"); + + uint8_t edidData[1024]; + DWORD edidLength = sizeof(edidData); + + if (RegGetValueW(HKEY_LOCAL_MACHINE, regPath, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidLength) == ERROR_SUCCESS && + edidLength > 0 && edidLength % 128 == 0) + { + uint32_t width, height; + ffEdidGetPhysicalResolution(edidData, &width, &height); + if (width == 0 || height == 0) continue; + + FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); + display->width = width; + display->height = height; + ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); + ffStrbufInit(&display->name); + ffEdidGetName(edidData, &display->name); + ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); + display->refreshRate = 0; + display->hdrCompatible = false; + + DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = { + .header = { + .type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO, + .size = sizeof(advColorInfo), + .adapterId = path->targetInfo.adapterId, + .id = path->targetInfo.id, + } + }; + if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS) + display->hdrCompatible = !!advColorInfo.advancedColorSupported; + else + display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); + + DISPLAYCONFIG_TARGET_PREFERRED_MODE preferredMode = { + .header = { + .type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE, + .size = sizeof(preferredMode), + .adapterId = path->targetInfo.adapterId, + .id = path->targetInfo.id, + } + }; + if (DisplayConfigGetDeviceInfo(&preferredMode.header) == ERROR_SUCCESS) + { + if (preferredMode.width == width && preferredMode.height == height) + { + DISPLAYCONFIG_RATIONAL freq = preferredMode.targetMode.targetVideoSignalInfo.vSyncFreq; + display->refreshRate = freq.Numerator / (double) freq.Denominator; + } + } + } } return NULL; } From 4e84153e9dce79a86ffcb0e8ba2a54cc69be2055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 18 Jul 2024 15:17:26 +0800 Subject: [PATCH 37/58] Display (Windows): check for hdr enabled & bit depth --- src/detection/displayserver/displayserver.c | 11 +++++++---- src/detection/displayserver/displayserver.h | 6 ++++-- .../displayserver/displayserver_windows.c | 19 ++++++++++++++++++- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index d2499e3492..ddc973962f 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -1,6 +1,6 @@ #include "displayserver.h" -bool ffdsAppendDisplay( +FFDisplayResult* ffdsAppendDisplay( FFDisplayServerResult* result, uint32_t width, uint32_t height, @@ -16,7 +16,7 @@ bool ffdsAppendDisplay( uint32_t physicalHeight) { if(width == 0 || height == 0) - return false; + return NULL; FFDisplayResult* display = ffListAdd(&result->displays); display->width = width; @@ -27,12 +27,15 @@ bool ffdsAppendDisplay( display->rotation = rotation; ffStrbufInitMove(&display->name, name); display->type = type; - display->primary = primary; display->id = id; display->physicalWidth = physicalWidth; display->physicalHeight = physicalHeight; + display->primary = primary; + + display->bitDepth = 0; + display->hdrEnabled = false; - return true; + return display; } void ffConnectDisplayServerImpl(FFDisplayServerResult* ds); diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 7467ef56a7..127dbc5fe9 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -58,10 +58,12 @@ typedef struct FFDisplayResult FFstrbuf name; FFDisplayType type; uint32_t rotation; - bool primary; uint64_t id; // platform dependent uint32_t physicalWidth; uint32_t physicalHeight; + bool primary; + uint8_t bitDepth; + bool hdrEnabled; } FFDisplayResult; typedef struct FFDisplayServerResult @@ -76,7 +78,7 @@ typedef struct FFDisplayServerResult const FFDisplayServerResult* ffConnectDisplayServer(); -bool ffdsAppendDisplay( +FFDisplayResult* ffdsAppendDisplay( FFDisplayServerResult* result, uint32_t width, uint32_t height, diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 3ccb212fde..3c685e2878 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -146,7 +146,7 @@ static void detectDisplays(FFDisplayServerResult* ds) default: rotation = 0; break; } - ffdsAppendDisplay(ds, + FFDisplayResult* display = ffdsAppendDisplay(ds, width, height, path->targetInfo.refreshRate.Numerator / (double) path->targetInfo.refreshRate.Denominator, @@ -164,6 +164,23 @@ static void detectDisplays(FFDisplayServerResult* ds) physicalWidth, physicalHeight ); + + if (display) + { + DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = { + .header = { + .type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO, + .size = sizeof(advColorInfo), + .adapterId = path->targetInfo.adapterId, + .id = path->targetInfo.id, + } + }; + if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS) + { + display->hdrEnabled = !!advColorInfo.advancedColorEnabled; + display->bitDepth = (uint8_t) advColorInfo.bitsPerColorChannel; + } + } } } } From f11b07ba8a39b5ccddf3498242695ef96ec1d5d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 18 Jul 2024 16:41:31 +0800 Subject: [PATCH 38/58] DisplayServer (macOS): detect bit depth --- .../displayserver/displayserver_apple.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index a668ce9613..15bba56b5d 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -1,5 +1,6 @@ #include "displayserver.h" #include "util/apple/cf_helpers.h" +#include "util/stringUtils.h" #include #include @@ -69,7 +70,7 @@ static void detectDisplays(FFDisplayServerResult* ds) CGSize size = CGDisplayScreenSize(screen); - ffdsAppendDisplay(ds, + FFDisplayResult* display = ffdsAppendDisplay(ds, (uint32_t)CGDisplayModeGetPixelWidth(mode), (uint32_t)CGDisplayModeGetPixelHeight(mode), refreshRate, @@ -83,6 +84,24 @@ static void detectDisplays(FFDisplayServerResult* ds) (uint32_t) (size.width + 0.5), (uint32_t) (size.height + 0.5) ); + if (display) + { + // Shitty code + uint8_t bitDepth = 0; + FF_CFTYPE_AUTO_RELEASE CFStringRef desc = CFCopyDescription(mode); + CFRange start = CFStringFind(desc, CFSTR("BitsPerSample = "), 0); + if (start.location != kCFNotFound) + { + for (CFIndex idx = start.location + start.length; idx < CFStringGetLength(desc); ++idx) + { + UniChar ch = CFStringGetCharacterAtIndex(desc, idx); + if (!ffCharIsDigit((char) ch)) + break; + bitDepth = (uint8_t) (bitDepth * 10 + (ch - '0')); + } + } + display->bitDepth = bitDepth; + } CGDisplayModeRelease(mode); } CGDisplayRelease(screen); From c3de29345025d4cc817b803c3504798a0f83b370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 18 Jul 2024 16:43:19 +0800 Subject: [PATCH 39/58] Display: print more information --- src/modules/display/display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index e6b2104de2..f694f76f0a 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -310,6 +310,8 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_uint(doc, obj, "scaledHeight", item->scaledHeight); yyjson_mut_obj_add_uint(doc, obj, "physicalWidth", item->physicalWidth); yyjson_mut_obj_add_uint(doc, obj, "physicalHeight", item->physicalHeight); + yyjson_mut_obj_add_uint(doc, obj, "bitDepth", item->bitDepth); + yyjson_mut_obj_add_bool(doc, obj, "hdrEnabled", item->hdrEnabled); switch (item->type) { From 96ec2b662c50f6938c5cae85e7fcf59e6f6e1f67 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 18 Jul 2024 18:33:46 +0800 Subject: [PATCH 40/58] Display (Linux): support HDR detection for KDE; fix build --- .../displayserver/linux/wayland/kde-output.c | 16 ++++++++++++---- .../displayserver/linux/wayland/wayland.h | 1 + src/detection/displayserver/linux/xcb.c | 4 ++-- src/detection/displayserver/linux/xlib.c | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index c6f08f243d..7732758ea3 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -105,7 +105,7 @@ static void waylandKdeGeometryListener(void *data, display->transform = (enum wl_output_transform) transform; } -void waylandOutputNameListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* output, const char *name) +static void waylandKdeNameListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* kde_output_device_v2, const char *name) { WaylandDisplay* display = data; display->type = ffdsGetDisplayType(name); @@ -113,6 +113,12 @@ void waylandOutputNameListener(void* data, FF_MAYBE_UNUSED struct kde_output_dev ffStrbufAppendS(&display->name, name); } +static void waylandKdeHdrListener(void *data, FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2, uint32_t hdr_enabled) +{ + WaylandDisplay* display = data; + display->hdrEnabled = !!hdr_enabled; +} + static struct kde_output_device_v2_listener outputListener = { .geometry = waylandKdeGeometryListener, .current_mode = waylandKdeCurrentModeListener, @@ -128,8 +134,8 @@ static struct kde_output_device_v2_listener outputListener = { .overscan = (void*) stubListener, .vrr_policy = (void*) stubListener, .rgb_range = (void*) stubListener, - .name = waylandOutputNameListener, - .high_dynamic_range = (void*) stubListener, + .name = waylandKdeNameListener, + .high_dynamic_range = waylandKdeHdrListener, .sdr_brightness = (void*) stubListener, .wide_color_gamut = (void*) stubListener, .auto_rotate_policy = (void*) stubListener, @@ -171,7 +177,7 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t rotation = ffWaylandHandleRotation(&display); - ffdsAppendDisplay(wldata->result, + FFDisplayResult* item = ffdsAppendDisplay(wldata->result, (uint32_t) display.width, (uint32_t) display.height, display.refreshRate / 1000.0, @@ -187,6 +193,8 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, (uint32_t) display.physicalWidth, (uint32_t) display.physicalHeight ); + if (item) + item->hdrEnabled = display.hdrEnabled; ffStrbufDestroy(&display.description); ffStrbufDestroy(&display.name); diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index e78a3c6de4..df7056a7b1 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -46,6 +46,7 @@ typedef struct WaylandDisplay FFstrbuf description; FFstrbuf edidName; uint64_t id; + bool hdrEnabled; void* internal; } WaylandDisplay; diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 6eb2bcdfbd..a64e55bd8b 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -241,7 +241,7 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb break; } bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation, primary, output, displayType); - res = res ? true : ffdsAppendDisplay( + res = res ? true : !!ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, @@ -317,7 +317,7 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* data->ffxcb_randr_output_next(&outputIterator); }; - return foundOutput ? true : ffdsAppendDisplay( + return foundOutput ? true : !!ffdsAppendDisplay( data->result, (uint32_t) monitor->width, (uint32_t) monitor->height, diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index cebbbf358e..69beb63afd 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -242,7 +242,7 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) foundOutput = true; } - return foundOutput ? true : ffdsAppendDisplay( + return foundOutput ? true : !!ffdsAppendDisplay( data->result, (uint32_t) monitorInfo->width, (uint32_t) monitorInfo->height, From 672bf0ef54ed12188e4905abd240eef1c549b886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 18 Jul 2024 19:21:58 +0800 Subject: [PATCH 41/58] Display: update JSON output structure --- src/modules/display/display.c | 19 +++++++++++++------ src/modules/monitor/monitor.c | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index f694f76f0a..ab914100cb 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -299,17 +299,24 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs FF_LIST_FOR_EACH(FFDisplayResult, item, dsResult->displays) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - yyjson_mut_obj_add_uint(doc, obj, "width", item->width); - yyjson_mut_obj_add_uint(doc, obj, "height", item->height); yyjson_mut_obj_add_uint(doc, obj, "id", item->id); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_obj_add_bool(doc, obj, "primary", item->primary); + + 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_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* 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, "scaledWidth", item->scaledWidth); - yyjson_mut_obj_add_uint(doc, obj, "scaledHeight", item->scaledHeight); - yyjson_mut_obj_add_uint(doc, obj, "physicalWidth", item->physicalWidth); - yyjson_mut_obj_add_uint(doc, obj, "physicalHeight", item->physicalHeight); yyjson_mut_obj_add_uint(doc, obj, "bitDepth", item->bitDepth); yyjson_mut_obj_add_bool(doc, obj, "hdrEnabled", item->hdrEnabled); diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 45b568cf65..c090f3d6c9 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -53,7 +53,7 @@ void ffPrintMonitor(FFMonitorOptions* options) printf("%ux%u px", display->width, display->height); if (display->refreshRate > 0) - printf(" @ %.2f Hz", display->refreshRate); + printf(" @ %.3f Hz", display->refreshRate); if (inch > 0) printf(" - %ux%u mm (%.2f inches, %.2f ppi)\n", display->physicalWidth, display->physicalHeight, inch, ppi); else From 7ba1e3d3d95f4199e25e6b7d7b84cc13af9e4c0b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 19 Jul 2024 11:13:17 +0800 Subject: [PATCH 42/58] Monitor (Linux): detect by Xrandr if EDID is not available --- src/detection/displayserver/linux/xlib.c | 2 - src/detection/monitor/monitor_linux.c | 188 ++++++++++++++++++++++- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 69beb63afd..ac06f499d0 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -119,7 +119,6 @@ typedef struct XrandrData FF_LIBRARY_SYMBOL(XInternAtom) FF_LIBRARY_SYMBOL(XGetAtomName); FF_LIBRARY_SYMBOL(XFree); - FF_LIBRARY_SYMBOL(XRRConfigCurrentRate) FF_LIBRARY_SYMBOL(XRRGetMonitors) FF_LIBRARY_SYMBOL(XRRGetScreenResourcesCurrent) FF_LIBRARY_SYMBOL(XRRGetOutputInfo) @@ -321,7 +320,6 @@ void ffdsConnectXrandr(FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XInternAtom,); FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XGetAtomName,); FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XFree,); - FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRConfigCurrentRate,); FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetMonitors,); FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetScreenResourcesCurrent,); FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetOutputInfo,); diff --git a/src/detection/monitor/monitor_linux.c b/src/detection/monitor/monitor_linux.c index b6c7e361e2..d5c0e4fe3f 100644 --- a/src/detection/monitor/monitor_linux.c +++ b/src/detection/monitor/monitor_linux.c @@ -1,13 +1,178 @@ #include "monitor.h" #include "common/io/io.h" +#include "common/library.h" #include "util/edidHelper.h" #include "util/stringUtils.h" -#include -#include +#ifdef FF_HAVE_XRANDR -const char* ffDetectMonitor(FFlist* results) +#include +#include + +typedef struct XrandrData +{ + FF_LIBRARY_SYMBOL(XInternAtom) + FF_LIBRARY_SYMBOL(XGetAtomName); + FF_LIBRARY_SYMBOL(XFree); + FF_LIBRARY_SYMBOL(XRRGetMonitors) + FF_LIBRARY_SYMBOL(XRRGetOutputInfo) + FF_LIBRARY_SYMBOL(XRRGetOutputProperty) + FF_LIBRARY_SYMBOL(XRRFreeOutputInfo) + FF_LIBRARY_SYMBOL(XRRFreeMonitors) + + //Init once + Display* display; + + //Init per screen + XRRScreenResources* screenResources; +} XrandrData; + +static const char* xrandrHandleMonitors(XrandrData* data, Screen* screen, FFlist* results) +{ + int numberOfMonitors; + XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, RootWindowOfScreen(screen), True, &numberOfMonitors); + if(monitorInfos == NULL) + return "XRRGetMonitors() failed"; + + for(int i = 0; i < numberOfMonitors; i++) + { + XRRMonitorInfo* monitorInfo = &monitorInfos[i]; + for(int i = 0; i < monitorInfo->noutput; i++) + { + RROutput output = monitorInfo->outputs[i]; + XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output); + if(outputInfo == NULL) + continue; + + FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); + ffStrbufInit(&display->name); + display->width = 0; + display->height = 0; + display->manufactureYear = 0; + display->manufactureWeek = 0; + display->serial = 0; + display->hdrCompatible = false; + display->refreshRate = 0; + + bool edidOk = false; + Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true); + if (atomEdid != None) + { + int actual_format = 0; + unsigned long nitems = 0, bytes_after = 0; + Atom actual_type = None; + uint8_t* edidData = NULL; + if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success) + { + if (nitems > 0 && nitems % 128 == 0) + { + ffEdidGetName(edidData, &display->name); + ffEdidGetPhysicalResolution(edidData, &display->width, &display->height); + ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); + ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); + display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) nitems); + edidOk = true; + } + } + if (edidData) + data->ffXFree(edidData); + } + + if (!edidOk) + { + ffStrbufSetS(&display->name, data->ffXGetAtomName(data->display, monitorInfo->name)); + display->physicalWidth = (uint32_t) monitorInfo->mwidth; + display->physicalHeight = (uint32_t) monitorInfo->mheight; + display->width = (uint32_t) monitorInfo->width; + display->height = (uint32_t) monitorInfo->height; + } + + for(int i = 0; i < data->screenResources->nmode; i++) + { + bool found = false; + for (int j = 0; j < outputInfo->nmode; ++j) + { + if (data->screenResources->modes[i].id == outputInfo->modes[j]) + { + found = true; + break; + } + } + + if(found) + { + XRRModeInfo* modeInfo = &data->screenResources->modes[i]; + double refreshRate = (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); + if (edidOk) + { + if (display->width != modeInfo->width || display->height != modeInfo->height) + continue; + } + else + { + if (display->width < modeInfo->width || display->height < modeInfo->height) + { + display->width = (uint32_t) modeInfo->width; + display->height = (uint32_t) modeInfo->height; + display->refreshRate = refreshRate; + continue; + } + else if (display->width != modeInfo->width || display->height != modeInfo->height) + continue; + } + if (display->refreshRate < refreshRate) + display->refreshRate = refreshRate; + } + } + data->ffXRRFreeOutputInfo(outputInfo); + } + } + + data->ffXRRFreeMonitors(monitorInfos); + return NULL; +} + +static const char* detectByXrandr(FFlist* results) +{ + FF_LIBRARY_LOAD(xrandr, &instance.config.library.libXrandr, "dlopen libXrandr" FF_LIBRARY_EXTENSION " failed", "libXrandr" FF_LIBRARY_EXTENSION, 3) + + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XOpenDisplay) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XCloseDisplay) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XRRGetScreenResourcesCurrent); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XRRFreeScreenResources); + + XrandrData data; + + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XInternAtom); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XGetAtomName); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XFree); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetMonitors); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetOutputInfo); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetOutputProperty); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeOutputInfo); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeMonitors); + + data.display = ffXOpenDisplay(NULL); + if(data.display == NULL) + return "XOpenDisplay() failed"; + + for(int i = 0; i < ScreenCount(data.display); i++) + { + Screen* screen = ScreenOfDisplay(data.display, i); + data.screenResources = ffXRRGetScreenResourcesCurrent(data.display, RootWindowOfScreen(screen)); + xrandrHandleMonitors(&data, screen, results); + ffXRRFreeScreenResources(data.screenResources); + } + + ffXCloseDisplay(data.display); + + return NULL; +} +#endif // FF_HAVE_XRANDR + +#ifdef __linux__ +FF_MAYBE_UNUSED static const char* detectByDrm(FFlist* results) { const char* drmDirPath = "/sys/class/drm/"; @@ -70,3 +235,20 @@ const char* ffDetectMonitor(FFlist* results) closedir(dirp); return NULL; } +#endif // __linux__ + +const char* ffDetectMonitor(FFlist* results) +{ + const char* error = "Fastfetch was compiled without xrandr support"; + + #ifdef FF_HAVE_XRANDR + error = detectByXrandr(results); + if (!error) return NULL; + #endif + + #if defined(__linux__) + error = detectByDrm(results); + #endif + + return error; +} From e12c6e6fd71fab09d3c48f0513ffb149f20ed523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 19 Jul 2024 15:02:17 +0800 Subject: [PATCH 43/58] Colors: fix bug with `--pipe` enabled --- src/modules/colors/colors.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 8d28405f7d..c78450bcca 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -46,7 +46,7 @@ void ffPrintColors(FFColorsOptions* options) if (options->paddingLeft > 0) ffPrintCharTimes(' ', options->paddingLeft); - if (!instance.config.display.pipe) + if (!instance.config.display.pipe || options->symbol == FF_COLORS_SYMBOL_BACKGROUND) ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); ffStrbufPutTo(&result, stdout); ffStrbufClear(&result); @@ -102,7 +102,7 @@ void ffPrintColors(FFColorsOptions* options) if(options->paddingLeft > 0) ffPrintCharTimes(' ', options->paddingLeft); - if(!instance.config.display.pipe) + if(!instance.config.display.pipe || options->symbol == FF_COLORS_SYMBOL_BACKGROUND) ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); ffStrbufPutTo(&result, stdout); } From f89cbf6bc83587a72acea1a3e0613ab3ddd1fa32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 19 Jul 2024 15:04:34 +0800 Subject: [PATCH 44/58] Monitor: enable module on FreeBSD and SunOS Fix #1101 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa10b9cbd3..7d674dd8b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -591,7 +591,7 @@ elseif(BSD) src/detection/gamepad/gamepad_bsd.c src/detection/media/media_linux.c src/detection/memory/memory_bsd.c - src/detection/monitor/monitor_nosupport.c + src/detection/monitor/monitor_linux.c src/detection/netio/netio_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -796,7 +796,7 @@ elseif(SunOS) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_sunos.c - src/detection/monitor/monitor_nosupport.c + src/detection/monitor/monitor_linux.c src/detection/netio/netio_sunos.c src/detection/opengl/opengl_linux.c src/detection/os/os_sunos.c From 9f23ce93bd356f328470a9e1ac1676099e103e9a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 19 Jul 2024 16:42:15 +0800 Subject: [PATCH 45/58] Doc: update changelog [ci skip] --- CHANGELOG.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb3c71c56a..4af9c5c0d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,62 @@ +# 2.19.0 + +Changes: +* JSON option `modules.cpu.freqNdigits` has been renamed and moved to `display.freq.ndigits` + * Previously: `{ "modules": { "type": "cpu", "freqNdigits": 2 } }` + * Now: `{ "display": { "freq": { "ndigits": 2 } } }` + * This option now affects GPU frequency too + * By default, frequencies are displayed in *GHz*. Set `display.freq.ndigits` to `-1` to display them in *MHz* + +Features: +* Print physical diagonal length if supported (Display) +* Detect display type in X11 mode (Display) +* Assume displays connected via DisplayPort are external monitors (Display, Linux) +* Support GPU frequency detection for Intel XE driver (GPU, Linux) +* Report init system on Android (InitSystem, Android) +* Use background to display color blocks (Colors) + * To fix weird vertical black lines in some terminals (#1094) + * And match the behavior of neofetch + * Can be reverted to old behavior with `--colors-symbol block` +* Support Zed terminal version detection (Terminal) +* Improve wezterm font detection (TerminalFont) +* Add option `--separator-length` +* Support GPU frequency detection for Apple Silicon (GPU, macOS) +* Detect maximum refresh rate (#1101, Monitor) +* Detect if HDR mode is enabled (Display) +* Support physical monitor info detection for FreeBSD and SunOS (Monitor) +* Support defining constant strings in JSON config file +```jsonc +{ + "display": { + "constants": [ + "Hello", // {$1} + "world" // {$2} + ] + }, + "modules": [ + { + "type": "custom", + "format": "{$1} {$2}!" // print "Hello world!" + }, + { + "type": "custom", + "format": "{$2} {$1}" // print "world Hello" + } + ] +} +``` + +Bugfixes: +* Fix some presets +* Better detection for XTerm terminal fonts (#1095, TerminalFont, Linux) +* Remove debug output (#1097, Windows) +* Fix command line option `--gpu-hide-type` doesnt work (#1098, GPU) +* Fix some typos + +Logos: +* Update void_small +* Add ALT Linux + # 2.18.1 Fix a regression introduced in v2.18.0 From 9e1ba0d1042b51b434a976f88fc3a361fee7a95a Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Fri, 19 Jul 2024 17:22:36 +0300 Subject: [PATCH 46/58] Doc: README.md: link to issue (#1107) [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ffa0ab325a..870d7fb550 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ You can always use `fastfetch --pipe false` to force fastfetch running in colorf ### Q: Why do fastfetch and neofetch show different memory usage result? -See #1096 +See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096). ### Q: I want feature A / B / C. Will fastfetch support it? From d7018c2fd37e899b64640b5bb6fce1611355ae6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 19 Jul 2024 22:33:52 +0800 Subject: [PATCH 47/58] DateTime: try fixing 32bit linux Fix #1108 --- src/common/time.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/time.h b/src/common/time.h index 0becc7e1d3..c402321f9a 100644 --- a/src/common/time.h +++ b/src/common/time.h @@ -20,7 +20,7 @@ static inline uint64_t ffTimeGetTick() //In msec #else struct timespec timeNow; clock_gettime(CLOCK_MONOTONIC, &timeNow); - return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000)); + return (uint64_t)((timeNow.tv_sec * 1000ull) + (timeNow.tv_nsec / 1000000ull)); #endif } @@ -33,7 +33,7 @@ static inline uint64_t ffTimeGetNow() #else struct timespec timeNow; clock_gettime(CLOCK_REALTIME, &timeNow); - return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000)); + return (uint64_t)((timeNow.tv_sec * 1000ull) + (timeNow.tv_nsec / 1000000ull)); #endif } From 40e67a1d9308586c9fbd6331bf36de8facfa56f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 19 Jul 2024 23:56:18 +0800 Subject: [PATCH 48/58] Doc: fix typo [ci skip] --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4af9c5c0d3..f0c7f34222 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,7 +50,7 @@ Bugfixes: * Fix some presets * Better detection for XTerm terminal fonts (#1095, TerminalFont, Linux) * Remove debug output (#1097, Windows) -* Fix command line option `--gpu-hide-type` doesnt work (#1098, GPU) +* Fix command line option `--gpu-hide-type` doesn't work (#1098, GPU) * Fix some typos Logos: From 2f26045d303b1f7b6162a3c070b4e2d299896ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 19 Jul 2024 23:57:44 +0800 Subject: [PATCH 49/58] Common: fix compiler warnings --- src/common/time.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/time.h b/src/common/time.h index c402321f9a..d98ca8e344 100644 --- a/src/common/time.h +++ b/src/common/time.h @@ -20,7 +20,7 @@ static inline uint64_t ffTimeGetTick() //In msec #else struct timespec timeNow; clock_gettime(CLOCK_MONOTONIC, &timeNow); - return (uint64_t)((timeNow.tv_sec * 1000ull) + (timeNow.tv_nsec / 1000000ull)); + return (uint64_t)(((uint64_t) timeNow.tv_sec * 1000u) + ((uint64_t) timeNow.tv_nsec / 1000000u)); #endif } @@ -33,7 +33,7 @@ static inline uint64_t ffTimeGetNow() #else struct timespec timeNow; clock_gettime(CLOCK_REALTIME, &timeNow); - return (uint64_t)((timeNow.tv_sec * 1000ull) + (timeNow.tv_nsec / 1000000ull)); + return (uint64_t)(((uint64_t) timeNow.tv_sec * 1000u) + ((uint64_t) timeNow.tv_nsec / 1000000u)); #endif } From 4fe1bb0b7e8098b383f78514d8b8dec831d44104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 20 Jul 2024 01:41:24 +0800 Subject: [PATCH 50/58] Display: detect if WCG enabled --- src/detection/displayserver/displayserver.c | 1 + src/detection/displayserver/displayserver.h | 1 + src/detection/displayserver/displayserver_windows.c | 1 + .../displayserver/linux/wayland/kde-output.c | 11 ++++++++++- src/detection/displayserver/linux/wayland/wayland.h | 1 + src/modules/display/display.c | 1 + 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index ddc973962f..73f1cd0c81 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -34,6 +34,7 @@ FFDisplayResult* ffdsAppendDisplay( display->bitDepth = 0; display->hdrEnabled = false; + display->wcgEnabled = false; return display; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 127dbc5fe9..aa0bd90076 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -64,6 +64,7 @@ typedef struct FFDisplayResult bool primary; uint8_t bitDepth; bool hdrEnabled; + bool wcgEnabled; } FFDisplayResult; typedef struct FFDisplayServerResult diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 3c685e2878..e443a7fd81 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -178,6 +178,7 @@ static void detectDisplays(FFDisplayServerResult* ds) if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS) { display->hdrEnabled = !!advColorInfo.advancedColorEnabled; + display->wcgEnabled = !!advColorInfo.wideColorEnforced; display->bitDepth = (uint8_t) advColorInfo.bitsPerColorChannel; } } diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index 7732758ea3..e02d6dbf21 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -119,6 +119,12 @@ static void waylandKdeHdrListener(void *data, FF_MAYBE_UNUSED struct kde_output_ display->hdrEnabled = !!hdr_enabled; } +static void waylandKdeWcgListener(void *data, FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2, uint32_t wcg_enabled) +{ + WaylandDisplay* display = data; + display->wcgEnabled = !!wcg_enabled; +} + static struct kde_output_device_v2_listener outputListener = { .geometry = waylandKdeGeometryListener, .current_mode = waylandKdeCurrentModeListener, @@ -137,7 +143,7 @@ static struct kde_output_device_v2_listener outputListener = { .name = waylandKdeNameListener, .high_dynamic_range = waylandKdeHdrListener, .sdr_brightness = (void*) stubListener, - .wide_color_gamut = (void*) stubListener, + .wide_color_gamut = waylandKdeWcgListener, .auto_rotate_policy = (void*) stubListener, .icc_profile_path = (void*) stubListener, .brightness_metadata = (void*) stubListener, @@ -194,7 +200,10 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, (uint32_t) display.physicalHeight ); if (item) + { item->hdrEnabled = display.hdrEnabled; + item->wcgEnabled = display.wcgEnabled; + } ffStrbufDestroy(&display.description); ffStrbufDestroy(&display.name); diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index df7056a7b1..c5d57c71ad 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -47,6 +47,7 @@ typedef struct WaylandDisplay FFstrbuf edidName; uint64_t id; bool hdrEnabled; + bool wcgEnabled; void* internal; } WaylandDisplay; diff --git a/src/modules/display/display.c b/src/modules/display/display.c index ab914100cb..707336432d 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -319,6 +319,7 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_uint(doc, obj, "rotation", item->rotation); yyjson_mut_obj_add_uint(doc, obj, "bitDepth", item->bitDepth); yyjson_mut_obj_add_bool(doc, obj, "hdrEnabled", item->hdrEnabled); + yyjson_mut_obj_add_bool(doc, obj, "wcgEnabled", item->wcgEnabled); switch (item->type) { From 7a1b214ffee60e2a0e8e03f471bbdee9fc65589a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 20 Jul 2024 23:29:40 +0800 Subject: [PATCH 51/58] Monitor (Windows): if current refresh rate is higher than preferred refresh rate, use it. No better methods. I have tried EnumDisplaySettings and winrt DisplayPath::GetModes but none of them work. --- src/detection/monitor/monitor_windows.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/detection/monitor/monitor_windows.c b/src/detection/monitor/monitor_windows.c index 03cc568781..4d9ebed2b6 100644 --- a/src/detection/monitor/monitor_windows.c +++ b/src/detection/monitor/monitor_windows.c @@ -103,6 +103,13 @@ const char* ffDetectMonitor(FFlist* results) display->refreshRate = freq.Numerator / (double) freq.Denominator; } } + + DISPLAYCONFIG_VIDEO_SIGNAL_INFO current = modes[path->targetInfo.modeInfoIdx].targetMode.targetVideoSignalInfo; + if (current.activeSize.cx == width && current.activeSize.cy == height) + { + double refreshRate = current.vSyncFreq.Numerator / (double) current.vSyncFreq.Denominator; + if (refreshRate > display->refreshRate) display->refreshRate = refreshRate; + } } } return NULL; From 3c9d9b3c67a7aa9376c8563d28ac824be9195702 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 21 Jul 2024 12:44:31 +0800 Subject: [PATCH 52/58] Brightness (Linux): use `brightness` instead of `actual_brightness` `actual_brightness` are above `max_brightness` on asahi. See also https://bugzilla.kernel.org/show_bug.cgi?id=203905 --- src/detection/brightness/brightness_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index de105504be..435f4e11b8 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -29,7 +29,7 @@ static const char* detectWithBacklight(FFlist* result) continue; ffStrbufAppendS(&backlightDir, entry->d_name); - ffStrbufAppendS(&backlightDir, "/actual_brightness"); + ffStrbufAppendS(&backlightDir, "/brightness"); if(ffReadFileBuffer(backlightDir.chars, &buffer)) { double actualBrightness = ffStrbufToDouble(&buffer); From 7f2ab7310aab8c8f6e72ce3abf40db40f14cfa0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 22 Jul 2024 09:22:01 +0800 Subject: [PATCH 53/58] Terminal: fix possible buffer overflow --- src/detection/terminalfont/terminalfont.c | 4 ++-- src/detection/terminalshell/terminalshell.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index bac06c6d1e..12fd4a7c8e 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -262,10 +262,10 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon static bool queryKittyTerm(const char* query, FFstrbuf* res) { // https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 - char buffer[64] = ""; + char buffer[256] = ""; if (ffGetTerminalResponse( query, // kitty-query-font_family;kitty-query-font_size - "\eP1+r%*[^=]=%64[^\e]\e\\", buffer) == NULL && *buffer) + "\eP1+r%*[^=]=%255[^\e]\e\\", buffer) == NULL) { // decode hex string for (const char* p = buffer; p[0] && p[1]; p += 2) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index dfb4fbbd9a..230b515c18 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -507,11 +507,11 @@ static bool getTerminalVersionZed(FFstrbuf* exe, FFstrbuf* version) #ifndef _WIN32 static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { - char versionHex[64] = ""; + char versionHex[64]; // https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233 if (ffGetTerminalResponse( "\eP+q6b697474792d71756572792d76657273696f6e\e\\", // kitty-query-version - "\eP1+r%*[^=]=%64[^\e]\e\\\\", versionHex) == NULL && *versionHex) + "\eP1+r%*[^=]=%63[^\e]\e\\\\", versionHex) == NULL) { // decode hex string for (const char* p = versionHex; p[0] && p[1]; p += 2) From 4a75123eb143fa336ddd92c64922e34fe8604c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 22 Jul 2024 09:23:06 +0800 Subject: [PATCH 54/58] Host (macOS): tidy --- src/detection/host/host_apple.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/host/host_apple.c b/src/detection/host/host_apple.c index d1065d9b8e..61a14e642d 100644 --- a/src/detection/host/host_apple.c +++ b/src/detection/host/host_apple.c @@ -22,10 +22,10 @@ static const char* getProductNameWithHwModel(const FFstrbuf* hwModel) if(ffStrEquals(version, "18,1") || ffStrEquals(version, "18,2")) return "MacBook Pro (16-inch, 2021)"; if(ffStrEquals(version, "17,1")) return "MacBook Pro (13-inch, M1, 2020)"; - if(ffStrEquals(version, "16,4")) return "MacBook Pro (16-inch, 2019)"; if(ffStrEquals(version, "16,3")) return "MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)"; if(ffStrEquals(version, "16,2")) return "MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)"; - if(ffStrEquals(version, "16,1")) return "MacBook Pro (16-inch, 2019)"; + if(ffStrEquals(version, "16,4") || + ffStrEquals(version, "16,1")) return "MacBook Pro (16-inch, 2019)"; if(ffStrEquals(version, "15,4")) return "MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)"; if(ffStrEquals(version, "15,3")) return "MacBook Pro (15-inch, 2019)"; if(ffStrEquals(version, "15,2")) return "MacBook Pro (13-inch, 2018/2019, Four Thunderbolt 3 ports)"; From 93bdaf10c4a84f1cdd9558e01d8d23b05d51037d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 22 Jul 2024 10:17:23 +0800 Subject: [PATCH 55/58] Release: v2.19.0 --- CHANGELOG.md | 13 ++++++++----- CMakeLists.txt | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0c7f34222..b28912632c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,19 +12,18 @@ Features: * Detect display type in X11 mode (Display) * Assume displays connected via DisplayPort are external monitors (Display, Linux) * Support GPU frequency detection for Intel XE driver (GPU, Linux) -* Report init system on Android (InitSystem, Android) +* Detect init system on Android (InitSystem, Android) * Use background to display color blocks (Colors) - * To fix weird vertical black lines in some terminals (#1094) - * And match the behavior of neofetch + * To fix weird vertical black lines in some terminals and match the behavior of neofetch (#1094) * Can be reverted to old behavior with `--colors-symbol block` * Support Zed terminal version detection (Terminal) * Improve wezterm font detection (TerminalFont) * Add option `--separator-length` * Support GPU frequency detection for Apple Silicon (GPU, macOS) * Detect maximum refresh rate (#1101, Monitor) -* Detect if HDR mode is enabled (Display) +* Detect if HDR mode is supported and enabled (Windows, Display / Monitor) * Support physical monitor info detection for FreeBSD and SunOS (Monitor) -* Support defining constant strings in JSON config file +* Support defining constant strings in JSON config file, which can be used to dedupe formattion strings ```jsonc { "display": { @@ -51,6 +50,10 @@ Bugfixes: * Better detection for XTerm terminal fonts (#1095, TerminalFont, Linux) * Remove debug output (#1097, Windows) * Fix command line option `--gpu-hide-type` doesn't work (#1098, GPU) +* Fix wrong date on Raspbian 10 (#1108, DateTime, Linux) +* Use `brightness` instead of `actuall_brightness` when detecting current brightness level (Brightness, Linux) + * Ref: https://bugzilla.kernel.org/show_bug.cgi?id=203905 +* Fix buffer overflow with long font family names when detecting kitty term font (TerminalFont) * Fix some typos Logos: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d674dd8b5..3a9a4b9a01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.18.1 + VERSION 2.19.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From 4a6209e0e370f3c902060701b50430a6c546721d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 22 Jul 2024 10:51:27 +0800 Subject: [PATCH 56/58] JsonConfig: rename `display.binaryPrefix` to `display.size.binaryPrefix` --- CHANGELOG.md | 3 ++ completions/fastfetch.bash | 4 +- doc/json_schema.json | 36 ++++++++--------- presets/examples/3.jsonc | 4 +- presets/examples/4.jsonc | 4 +- src/data/help.json | 26 ++++++------- src/options/display.c | 79 +++++++++++++++++++++++--------------- 7 files changed, 89 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b28912632c..0099ee1796 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ Changes: * Now: `{ "display": { "freq": { "ndigits": 2 } } }` * This option now affects GPU frequency too * By default, frequencies are displayed in *GHz*. Set `display.freq.ndigits` to `-1` to display them in *MHz* +* JSON option `display.binaryPrefix` has been moved to `display.size.binaryPrefix` + * Previously: `{ "display": { "binaryPrefix": "IEC" } }` + * Now: `{ "display": { "size": { "binaryPrefix": "IEC" } } }` Features: * Print physical diagonal length if supported (Display) diff --git a/completions/fastfetch.bash b/completions/fastfetch.bash index 8cfdc9a84d..76e43859a7 100644 --- a/completions/fastfetch.bash +++ b/completions/fastfetch.bash @@ -83,12 +83,12 @@ __fastfetch_complete_logo_type() __fastfetch_complete_binary_prefix() { - local __ff_binary_prefixes=( + local __ff_size_binary_prefixes=( "iec" "si" "jedec" ) - COMPREPLY=($(compgen -W "${__ff_binary_prefixes[*]}" -- "$CURRENT_WORD")) + COMPREPLY=($(compgen -W "${__ff_size_binary_prefixes[*]}" -- "$CURRENT_WORD")) } __fastfetch_complete_gl() diff --git a/doc/json_schema.json b/doc/json_schema.json index ec7bc3ead1..ca8d45690a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -424,29 +424,29 @@ "minimum": 0, "default": 0 }, - "binaryPrefix": { - "type": "string", - "description": "Set the binary prefix to used when printing bytes", - "oneOf": [ - { - "const": "iec", - "description": "1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard)" - }, - { - "const": "si", - "description": "1000 Bytes = 1 KB, 1000 KB = 1 MB, ..." - }, - { - "const": "jedec", - "description": "1024 Bytes = 1 kB, 1024 K = 1 MB, ..." - } - ] - }, "size": { "type": "object", "additionalProperties": false, "description": "Set how a size value should be displayed", "properties": { + "binaryPrefix": { + "type": "string", + "description": "Set the binary prefix to used when formatting sizes", + "oneOf": [ + { + "const": "iec", + "description": "1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard)" + }, + { + "const": "si", + "description": "1000 Bytes = 1 KB, 1000 KB = 1 MB, ..." + }, + { + "const": "jedec", + "description": "1024 Bytes = 1 kB, 1024 K = 1 MB, ..." + } + ] + }, "maxPrefix": { "type": "string", "description": "Set the largest binary prefix to use when formatting sizes", diff --git a/presets/examples/3.jsonc b/presets/examples/3.jsonc index 670a942a82..f3cb7d431b 100644 --- a/presets/examples/3.jsonc +++ b/presets/examples/3.jsonc @@ -6,7 +6,9 @@ "type": "small" }, "display": { - "binaryPrefix": "si" + "size": { + "binaryPrefix": "si" + } }, "modules": [ "vulkan", diff --git a/presets/examples/4.jsonc b/presets/examples/4.jsonc index fafeb892a1..9631644168 100644 --- a/presets/examples/4.jsonc +++ b/presets/examples/4.jsonc @@ -9,7 +9,9 @@ } }, "display": { - "binaryPrefix": "si", + "size": { + "binaryPrefix": "si" + }, "color": "blue", "separator": "  " }, diff --git a/src/data/help.json b/src/data/help.json index 7fc18e82e8..d69c80d05d 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -549,19 +549,6 @@ "default": false } }, - { - "long": "binary-prefix", - "desc": "Set the binary prefix to used", - "arg": { - "type": "enum", - "enum": { - "IEC": "1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ...", - "SI": "1000 Bytes = 1 KB, 1000 KB = 1 MB, ...", - "JEDEC": "1024 Bytes = 1 kB, 1024 kB = 1 MB, ..." - }, - "default": "IEC" - } - }, { "long": "percent-type", "desc": "Set the percentage output type", @@ -669,6 +656,19 @@ "type": "num" } }, + { + "long": "size-binary-prefix", + "desc": "Set the binary prefix to used when formatting sizes", + "arg": { + "type": "enum", + "enum": { + "IEC": "1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ...", + "SI": "1000 Bytes = 1 KB, 1000 KB = 1 MB, ...", + "JEDEC": "1024 Bytes = 1 kB, 1024 kB = 1 MB, ..." + }, + "default": "IEC" + } + }, { "long": "size-max-prefix", "desc": "Set the largest binary prefix to use when formatting sizes", diff --git a/src/options/display.c b/src/options/display.c index eb79a90dbe..2ed899cad8 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -61,17 +61,7 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va else if (ffStrEqualsIgnCase(key, "brightColor")) options->brightColor = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "binaryPrefix")) - { - int value; - const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { - { "iec", FF_BINARY_PREFIX_TYPE_IEC }, - { "si", FF_BINARY_PREFIX_TYPE_SI }, - { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, - {}, - }); - if (error) return error; - options->binaryPrefixType = (FFBinaryPrefixType) value; - } + return "`display.binaryPrefix` has been renamed to `display.size.binaryPrefix`. Sorry for another break change."; else if (ffStrEqualsIgnCase(key, "size")) { if (!yyjson_is_obj(val)) @@ -97,6 +87,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va options->sizeMaxPrefix = (uint8_t) value; } + yyjson_val* binaryPrefix = yyjson_obj_get(val, "binaryPrefix"); + if (binaryPrefix) + { + int value; + const char* error = ffJsonConfigParseEnum(binaryPrefix, &value, (FFKeyValuePair[]) { + { "iec", FF_BINARY_PREFIX_TYPE_IEC }, + { "si", FF_BINARY_PREFIX_TYPE_SI }, + { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, + {}, + }); + if (error) return error; + options->binaryPrefixType = (FFBinaryPrefixType) value; + } + yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); if (ndigits) options->sizeNdigits = (uint8_t) yyjson_get_uint(ndigits); } @@ -288,29 +292,40 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key options->brightColor = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(key, "--binary-prefix")) { - options->binaryPrefixType = (FFBinaryPrefixType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "iec", FF_BINARY_PREFIX_TYPE_IEC }, - { "si", FF_BINARY_PREFIX_TYPE_SI }, - { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, - {} - }); + fprintf(stderr, "--binary-prefix has been renamed to --size-binary-prefix\n"); + exit(477); } - else if(ffStrEqualsIgnCase(key, "--size-ndigits")) - options->sizeNdigits = (uint8_t) ffOptionParseUInt32(key, value); - else if(ffStrEqualsIgnCase(key, "--size-max-prefix")) + else if(ffStrStartsWithIgnCase(key, "--size-")) { - options->sizeMaxPrefix = (uint8_t) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "B", 0 }, - { "kB", 1 }, - { "MB", 2 }, - { "GB", 3 }, - { "TB", 4 }, - { "PB", 5 }, - { "EB", 6 }, - { "ZB", 7 }, - { "YB", 8 }, - {} - }); + const char* subkey = key + strlen("--size-"); + if (ffStrEqualsIgnCase(subkey, "binary-prefix")) + { + options->binaryPrefixType = (FFBinaryPrefixType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "iec", FF_BINARY_PREFIX_TYPE_IEC }, + { "si", FF_BINARY_PREFIX_TYPE_SI }, + { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, + {} + }); + } + else if (ffStrEqualsIgnCase(subkey, "ndigits")) + options->sizeNdigits = (uint8_t) ffOptionParseUInt32(key, value); + else if (ffStrEqualsIgnCase(subkey, "max-prefix")) + { + options->sizeMaxPrefix = (uint8_t) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "B", 0 }, + { "kB", 1 }, + { "MB", 2 }, + { "GB", 3 }, + { "TB", 4 }, + { "PB", 5 }, + { "EB", 6 }, + { "ZB", 7 }, + { "YB", 8 }, + {} + }); + } + else + return false; } else if(ffStrStartsWithIgnCase(key, "--temp-")) { From 52715a0ec5627c7c777e6eccb2002234c218ffb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 22 Jul 2024 10:59:23 +0800 Subject: [PATCH 57/58] Fastfetch: rename `binaryPrefixType` to `sizeBinaryPrefix` --- src/common/parsing.c | 8 +++---- src/options/display.c | 50 +++++++++++++++++++++---------------------- src/options/display.h | 12 +++++------ 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/common/parsing.c b/src/common/parsing.c index ad21436638..ec58f9fa21 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -79,15 +79,15 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha void ffParseSize(uint64_t bytes, FFstrbuf* result) { - switch (instance.config.display.binaryPrefixType) + switch (instance.config.display.sizeBinaryPrefix) { - case FF_BINARY_PREFIX_TYPE_IEC: + case FF_SIZE_BINARY_PREFIX_TYPE_IEC: parseSize(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL}); break; - case FF_BINARY_PREFIX_TYPE_SI: + case FF_SIZE_BINARY_PREFIX_TYPE_SI: parseSize(result, bytes, 1000, (const char*[]) {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", NULL}); break; - case FF_BINARY_PREFIX_TYPE_JEDEC: + case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC: parseSize(result, bytes, 1024, (const char*[]) {"B", "KB", "MB", "GB", "TB", NULL}); break; default: diff --git a/src/options/display.c b/src/options/display.c index 2ed899cad8..117cd689f6 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -92,13 +92,13 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va { int value; const char* error = ffJsonConfigParseEnum(binaryPrefix, &value, (FFKeyValuePair[]) { - { "iec", FF_BINARY_PREFIX_TYPE_IEC }, - { "si", FF_BINARY_PREFIX_TYPE_SI }, - { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, + { "iec", FF_SIZE_BINARY_PREFIX_TYPE_IEC }, + { "si", FF_SIZE_BINARY_PREFIX_TYPE_SI }, + { "jedec", FF_SIZE_BINARY_PREFIX_TYPE_JEDEC }, {}, }); if (error) return error; - options->binaryPrefixType = (FFBinaryPrefixType) value; + options->sizeBinaryPrefix = (FFSizeBinaryPrefixType) value; } yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); @@ -300,10 +300,10 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key const char* subkey = key + strlen("--size-"); if (ffStrEqualsIgnCase(subkey, "binary-prefix")) { - options->binaryPrefixType = (FFBinaryPrefixType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "iec", FF_BINARY_PREFIX_TYPE_IEC }, - { "si", FF_BINARY_PREFIX_TYPE_SI }, - { "jedec", FF_BINARY_PREFIX_TYPE_JEDEC }, + options->sizeBinaryPrefix = (FFSizeBinaryPrefixType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "iec", FF_SIZE_BINARY_PREFIX_TYPE_IEC }, + { "si", FF_SIZE_BINARY_PREFIX_TYPE_SI }, + { "jedec", FF_SIZE_BINARY_PREFIX_TYPE_JEDEC }, {} }); } @@ -417,7 +417,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) #endif options->hideCursor = false; - options->binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC; + options->sizeBinaryPrefix = FF_SIZE_BINARY_PREFIX_TYPE_IEC; options->sizeNdigits = 2; options->sizeMaxPrefix = UINT8_MAX; options->stat = false; @@ -506,23 +506,6 @@ void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_do if (options->brightColor != defaultOptions.brightColor) yyjson_mut_obj_add_bool(doc, obj, "brightColor", options->brightColor); - if (options->binaryPrefixType != defaultOptions.binaryPrefixType) - { - switch (options->binaryPrefixType) - { - case FF_BINARY_PREFIX_TYPE_IEC: - yyjson_mut_obj_add_str(doc, obj, "binaryPrefix", "iec"); - break; - case FF_BINARY_PREFIX_TYPE_SI: - yyjson_mut_obj_add_str(doc, obj, "binaryPrefix", "si"); - break; - case FF_BINARY_PREFIX_TYPE_JEDEC: - yyjson_mut_obj_add_str(doc, obj, "binaryPrefix", "jedec"); - break; - - } - } - { yyjson_mut_val* size = yyjson_mut_obj(doc); if (options->sizeNdigits != defaultOptions.sizeNdigits) @@ -541,6 +524,21 @@ void ffOptionsGenerateDisplayJsonConfig(FFOptionsDisplay* options, yyjson_mut_do "YB", })[options->sizeMaxPrefix]); } + if (options->sizeBinaryPrefix != defaultOptions.sizeBinaryPrefix) + { + switch (options->sizeBinaryPrefix) + { + case FF_SIZE_BINARY_PREFIX_TYPE_IEC: + yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "iec"); + break; + case FF_SIZE_BINARY_PREFIX_TYPE_SI: + yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "si"); + break; + case FF_SIZE_BINARY_PREFIX_TYPE_JEDEC: + yyjson_mut_obj_add_str(doc, size, "binaryPrefix", "jedec"); + break; + } + } if (yyjson_mut_obj_size(size) > 0) yyjson_mut_obj_add_val(doc, obj, "size", size); } diff --git a/src/options/display.h b/src/options/display.h index 75125ce767..42e5c22eef 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -2,12 +2,12 @@ #include "util/FFstrbuf.h" -typedef enum FFBinaryPrefixType +typedef enum FFSizeBinaryPrefixType { - FF_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) - FF_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 KB, 1000 KB = 1 MB, ... - FF_BINARY_PREFIX_TYPE_JEDEC, // 1024 Bytes = 1 kB, 1024 kB = 1 MB, ... -} FFBinaryPrefixType; + FF_SIZE_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) + FF_SIZE_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 KB, 1000 KB = 1 MB, ... + FF_SIZE_BINARY_PREFIX_TYPE_JEDEC, // 1024 Bytes = 1 kB, 1024 kB = 1 MB, ... +} FFSizeBinaryPrefixType; typedef enum FFTemperatureUnit { @@ -33,7 +33,7 @@ typedef struct FFOptionsDisplay bool showErrors; bool disableLinewrap; bool hideCursor; - FFBinaryPrefixType binaryPrefixType; + FFSizeBinaryPrefixType sizeBinaryPrefix; uint8_t sizeNdigits; uint8_t sizeMaxPrefix; FFTemperatureUnit tempUnit; From 036d407708dd0fa1317665be76adbb3ab1075ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 22 Jul 2024 13:44:29 +0800 Subject: [PATCH 58/58] Doc: update README [ci skip] --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 870d7fb550..54bcf1fd43 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,10 @@ Fastfetch uses JSON (with comments) for configuration. I suggest you use an IDE Alternatively, you can refer to the presets in [`presets` directory](https://github.com/fastfetch-cli/fastfetch/tree/dev/presets). +The **correct** way to edit the configuration: + +[![asciicast](https://asciinema.org/a/1uF6sTPGKrHKI1MVaFcikINSQ.svg)](https://asciinema.org/a/1uF6sTPGKrHKI1MVaFcikINSQ) + ### Q: I WANT THE DOCUMENTATION! [Here is the documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Json-Schema). It is generated from [JSON schema](https://github.com/fastfetch-cli/fastfetch/blob/dev/doc/json_schema.json) but you won't like it.