From 7b9fce0189c73ded464889176e72ca35bcebd023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 23 Sep 2025 14:54:06 +0800 Subject: [PATCH 01/61] CI (Linux): adds GCC 13 toolchain to CI build environment --- .github/workflows/ci.yml | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b1219ab69..4ae6f26e71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,8 +89,11 @@ jobs: - name: cat /proc/cpuinfo run: cat /proc/cpuinfo + - name: add gcc-13 repo + run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libchafa-dev directx-headers-dev rpm ninja-build + run: sudo apt-get update && sudo apt-get install -y gcc-13 g++-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libchafa-dev directx-headers-dev rpm ninja-build - name: install linuxbrew packages run: | @@ -104,7 +107,7 @@ jobs: languages: c - name: configure project - run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr . + run: CC=gcc-13 CXX=g++-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr . - name: build project run: cmake --build . --target package --verbose -j4 @@ -169,12 +172,13 @@ jobs: githubToken: ${{ github.token }} run: | uname -a - apt-get update && apt-get install -y ca-certificates gpg curl + apt-get update && apt-get install -y software-properties-common ca-certificates gpg curl + add-apt-repository -y ppa:ubuntu-toolchain-r/test curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null echo -e 'Acquire::https::Verify-Peer "false";\nAcquire::https::Verify-Host "false";' >> /etc/apt/apt.conf.d/99ignore-certificates - apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm + CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false @@ -209,8 +213,8 @@ jobs: run: | uname -a apt-get update && apt-get install -y wget - apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + apt-get install -y cmake make gcc libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false @@ -246,12 +250,14 @@ jobs: id: runcmd with: arch: ${{ matrix.arch }} - distro: ubuntu20.04 + distro: ubuntu22.04 githubToken: ${{ github.token }} run: | uname -a - apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev rpm - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + apt-get update && apt-get install -y software-properties-common + add-apt-repository -y ppa:ubuntu-toolchain-r/test + apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev rpm + CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false From 4e84094fd88557b2386c2058ff8a5dd4527bac9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 23 Sep 2025 16:24:59 +0800 Subject: [PATCH 02/61] CI (OpenBSD): updates CI workflow to upgrade packages before install --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ae6f26e71..82dea71fd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -455,7 +455,8 @@ jobs: version: '7.7' run: | uname -a - sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa + sudo pkg_add -u + sudo pkg_add -r llvm cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features From 0f5d321df8e6b305b586a66ec84cfcc6f1185505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 24 Sep 2025 10:11:02 +0800 Subject: [PATCH 03/61] Chore: updates comments to use English descriptions --- src/detection/physicalmemory/physicalmemory_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/physicalmemory/physicalmemory_linux.c b/src/detection/physicalmemory/physicalmemory_linux.c index de9dddad96..8fdea2812e 100644 --- a/src/detection/physicalmemory/physicalmemory_linux.c +++ b/src/detection/physicalmemory/physicalmemory_linux.c @@ -124,7 +124,7 @@ const char* ffDetectPhysicalMemory(FFlist* result) ffStrbufSetS(&device->locator, ldevice); const char* formFactorNames[] = { - NULL, // 0x00 (用于索引,实际上没有0x00的类型) + NULL, // 0x00 (Placeholder for indexing) "Other", // 0x01 "Unknown", // 0x02 "SIMM", // 0x03 @@ -148,7 +148,7 @@ const char* ffDetectPhysicalMemory(FFlist* result) ffStrbufSetF(&device->formFactor, "Unknown (%d)", (int) data->FormFactor); const char* memoryTypeNames[] = { - NULL, // 0x00 (用于索引,实际上没有0x00的类型) + NULL, // 0x00 (Placeholder for indexing) "Other", // 0x01 "Unknown", // 0x02 "DRAM", // 0x03 From 9eed149b09d1cf0e887e12797b29a63262506898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 25 Sep 2025 16:15:02 +0800 Subject: [PATCH 04/61] CMake (Linux): adds i686 CI build and unify processor naming Fixes #1978 --- .github/workflows/ci.yml | 64 ++++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 18 +++++++---- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82dea71fd9..d63c88c245 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,6 +153,69 @@ jobs: name: fastfetch-linux-${{ matrix.arch }} path: ./fastfetch-*.* + linux-i686: + name: Linux-i686 + runs-on: ubuntu-22.04 + permissions: + security-events: write + contents: read + steps: + - name: checkout repository + uses: actions/checkout@v5 + + - name: uname -a + run: uname -a + + - name: cat /etc/os-release + run: cat /etc/os-release + + - name: cat /proc/cpuinfo + run: cat /proc/cpuinfo + + - name: add gcc-13 repo + run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + + - name: install required packages + run: sudo apt-get update && sudo apt-get install -y gcc-13 gcc-13-multilib libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev rpm ninja-build + + - name: install linuxbrew packages + run: | + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + /home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies + + - name: cmake version + run: cmake --version + + - name: configure project + run: CC=gcc-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DCMAKE_C_FLAGS="-m32 -march=i686 -mtune=i686" -DCMAKE_SYSTEM_PROCESSOR_OVERRIDE=i686 -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_DIRECTX_HEADERS=Off . + + - name: build project + run: cmake --build . --target package --verbose -j4 + + - name: list features + run: ./fastfetch --list-features + + - name: run fastfetch + run: time ./fastfetch -c presets/ci.jsonc --stat false + + - name: run fastfetch --format json + run: time ./fastfetch -c presets/ci.jsonc --format json + + - name: run flashfetch + run: time ./flashfetch + + - name: print dependencies + run: ldd fastfetch + + - name: run tests + run: ctest --output-on-failure + + - name: upload artifacts + uses: actions/upload-artifact@v4 + with: + name: fastfetch-linux-i686 + path: ./fastfetch-*.* + linux-armv7l: name: Linux-armv7l runs-on: ubuntu-24.04 @@ -659,6 +722,7 @@ jobs: runs-on: ubuntu-latest needs: - linux-hosts + - linux-i686 - linux-armv7l - linux-armv6l - linux-vms diff --git a/CMakeLists.txt b/CMakeLists.txt index be123fd7ea..72c8e2e3cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,17 @@ project(fastfetch set(PROJECT_LICENSE "MIT license") +if(DEFINED CMAKE_SYSTEM_PROCESSOR_OVERRIDE) # Used by github actions for i686 build + set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR_OVERRIDE} CACHE INTERNAL "") +endif() +string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" CMAKE_SYSTEM_PROCESSOR) +if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(CMAKE_SYSTEM_PROCESSOR "amd64") +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set(CMAKE_SYSTEM_PROCESSOR "aarch64") +endif() +message(STATUS "Build for system processor: ${CMAKE_SYSTEM_PROCESSOR}") + ################### # Target Platform # ################### @@ -1682,7 +1693,7 @@ elseif(WIN32) PRIVATE "propsys" PRIVATE "secur32" ) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") # WoA only works on Windows 10 or higher target_link_libraries(libfastfetch PRIVATE "mincore" @@ -2020,11 +2031,6 @@ install( ################## set(CPACK_GENERATOR "TGZ;ZIP") -if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - set(CMAKE_SYSTEM_PROCESSOR "amd64") -elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") - set(CMAKE_SYSTEM_PROCESSOR "aarch64") -endif() if(APPLE) string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) # use macos instead of darwin elseif(IS_MUSL) From 7b689f94dff42a16e1d80f3c60f49bb42b31490e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Sep 2025 09:40:21 +0800 Subject: [PATCH 05/61] Logo (Builtin): adds secureblue Fixes #1979 --- src/logo/ascii/secureblue.txt | 20 ++++++++++++++++++++ src/logo/builtin.c | 10 ++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/logo/ascii/secureblue.txt diff --git a/src/logo/ascii/secureblue.txt b/src/logo/ascii/secureblue.txt new file mode 100644 index 0000000000..ce91b51b3b --- /dev/null +++ b/src/logo/ascii/secureblue.txt @@ -0,0 +1,20 @@ + ==++++++++++ + :========++++++++++++: + ===============+++++++++++ + ====================++++++++++ + :=============$3#%@@%$1======++++++++- + -============$3%@%+++*$3@@$1========+++++= + -============$3%@#======$3@@$1==========+++- + =============$3%@+======$3@@$1==============. +$2--$1=========$3+@@@@@@@@@@@@@@@%+$1==========- +$2------$1=====$3%@@@@@@@@@@@@@@@@*$1=========== +$2---------$1==$3%@@@@@@@%%@@@@@@@*$1=========== +$2:----------$3%@@@@@#$1===$3+%@@@@@*$1==========- + $2----------$3%@@@@@%$1===$3*@@@@@@*$1==========. + $2:---------$3%@@@@@@@@@@@@@@@@*$1=========- + $2:--------$3%@@@@@@@@@@@@@@@@*$1========- + $2:--------$3+##############+$1========: + $2-------------------------$1====- + $2-------------------------- + .--------------------. + ------------ \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 29f0540028..c468066617 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -4379,6 +4379,16 @@ static const FFlogo S[] = { FF_COLOR_FG_RED, }, }, + // Secureblue + { + .names = {"secureblue"}, + .lines = FASTFETCH_DATATEXT_LOGO_SECUREBLUE, + .colors = { + FF_COLOR_FG_BLUE, + FF_COLOR_FG_MAGENTA, + FF_COLOR_FG_DEFAULT, + }, + }, // Serpent OS { .names = {"Serpent OS"}, From 512ddfae6b0e5a24144b3ee545ee69ad1d8d6bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Sep 2025 09:40:48 +0800 Subject: [PATCH 06/61] Doc: adds padding check to logo request template --- .github/ISSUE_TEMPLATE/logo_request.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/logo_request.yml b/.github/ISSUE_TEMPLATE/logo_request.yml index 343c0d6c1d..9790eef5d6 100644 --- a/.github/ISSUE_TEMPLATE/logo_request.yml +++ b/.github/ISSUE_TEMPLATE/logo_request.yml @@ -36,3 +36,5 @@ body: required: true - label: The ASCII art contains color codes, or the color codes are available in `os-release` required: true + - label: The ASCII art contains no internal paddings (spaces at the start and the end of lines) + required: true From 5d571752ae97ada3bc5a840b3501c55a2b4830a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Sep 2025 14:35:41 +0800 Subject: [PATCH 07/61] Chore: updates FUNDING info --- .github/FUNDING.yml | 2 ++ README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..df28f14944 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +ko_fi: carterli +github: LinusDierheimer diff --git a/README.md b/README.md index 11832f6ba7..39ad40a4a9 100644 --- a/README.md +++ b/README.md @@ -314,7 +314,7 @@ Otherwise, please open a feature request in [GitHub Issues](https://github.com/f If you find Fastfetch useful, please consider donating. -* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui) +* Current maintainer: [@CarterLi](https://ko-fi.com/carterli) * Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer) ## Star History From 229fe7c7bf74157bc2df676b6630b574ae81b95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Sep 2025 14:36:55 +0800 Subject: [PATCH 08/61] CMake: update contact info --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72c8e2e3cf..daded92cd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2077,7 +2077,7 @@ endif() set(CPACK_SET_DESTDIR ON) -set(CPACK_PACKAGE_CONTACT "Linus Dierheimer ") +set(CPACK_PACKAGE_CONTACT "Carter Li ") set(CPACK_PACKAGE_DESCRIPTION "\ fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \ It is written mostly in C to achieve much better performance.\ From adc25f44202068e026ed43a550258986bbd51349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Sep 2025 14:38:01 +0800 Subject: [PATCH 09/61] CI: adds Debian libc6 dependency to package config Fixes #1981 --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d63c88c245..c64f3a642e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,6 +145,7 @@ jobs: strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17 strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17 echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake + echo 'set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)")' >> CPackConfig.cmake cpack - name: upload artifacts From bd9744c27cb9e8712384b6dc723ab64ee022968b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Sep 2025 15:07:45 +0800 Subject: [PATCH 10/61] CommandLine: adds `--json` flag as a shortcut for enabling JSON output --- src/data/help.json | 11 +++++++++++ src/fastfetch.c | 46 ++++++++++++++++++++++++++-------------------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/data/help.json b/src/data/help.json index 40382f2d8a..335f8563a7 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -63,6 +63,17 @@ }, "default": "default" } + }, + { + "long": "json", + "short": "j", + "arg": { + "type": "bool", + "default": false, + "optional": true + }, + "desc": "Enable or disable JSON output", + "remark": "Shortcut for `--format json`" } ], "Config": [ diff --git a/src/fastfetch.c b/src/fastfetch.c index d92760d0dd..b3845246e4 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -549,6 +549,26 @@ static void printVersion() printf("%s %s%s%s (%s)\n", result->projectName, result->version, result->versionTweak, result->debugMode ? "-debug" : "", result->architecture); } +static void enableJsonOutput(bool enable) +{ + if (!enable) + { + if (instance.state.resultDoc) + { + yyjson_mut_doc_free(instance.state.resultDoc); + instance.state.resultDoc = NULL; + } + } + else + { + if (!instance.state.resultDoc) + { + instance.state.resultDoc = yyjson_mut_doc_new(NULL); + yyjson_mut_doc_set_root(instance.state.resultDoc, yyjson_mut_arr(instance.state.resultDoc)); + } + } +} + static void parseCommand(FFdata* data, char* key, char* value) { if(ffStrEqualsIgnCase(key, "-h") || ffStrEqualsIgnCase(key, "--help")) @@ -640,29 +660,15 @@ static void parseCommand(FFdata* data, char* key, char* value) generateConfigFile(true, value, true); else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--config")) optionParseConfigFile(data, key, value); + else if(ffStrEqualsIgnCase(key, "-j") || ffStrEqualsIgnCase(key, "--json")) + enableJsonOutput(ffOptionParseBoolean(value)); else if(ffStrEqualsIgnCase(key, "--format")) { - switch (ffOptionParseEnum(key, value, (FFKeyValuePair[]) { - { "default", 0}, - { "json", 1 }, + enableJsonOutput(!!ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", false}, + { "json", true }, {}, - })) - { - case 0: - if (instance.state.resultDoc) - { - yyjson_mut_doc_free(instance.state.resultDoc); - instance.state.resultDoc = NULL; - } - break; - case 1: - if (!instance.state.resultDoc) - { - instance.state.resultDoc = yyjson_mut_doc_new(NULL); - yyjson_mut_doc_set_root(instance.state.resultDoc, yyjson_mut_arr(instance.state.resultDoc)); - } - break; - } + })); } else return; From 093f56a03d8658ade3edf2c104f587cfc6245b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 29 Sep 2025 09:25:24 +0800 Subject: [PATCH 11/61] Theme (macOS): moves macOS theme detection logic from DE to dedicated module The old behavior was inherited from neofetch. However `Aqua` and `Liquid Glass` are actually design language, not a DE. There is no DE on macOS. --- CMakeLists.txt | 2 +- .../displayserver/displayserver_apple.c | 16 ------------- src/detection/theme/theme_apple.c | 24 +++++++++++++++++++ 3 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 src/detection/theme/theme_apple.c diff --git a/CMakeLists.txt b/CMakeLists.txt index daded92cd3..baef303d7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -974,7 +974,7 @@ elseif(APPLE) src/detection/terminalfont/terminalfont_apple.m src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c - src/detection/theme/theme_nosupport.c + src/detection/theme/theme_apple.c src/detection/tpm/tpm_apple.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 4ef8d05209..7cf41204d6 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -196,21 +196,5 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) } } - const FFOSResult* os = ffDetectOS(); - - char* str_end; - const char* version = os->version.chars; - unsigned long osNum = strtoul(version, &str_end, 10); - if (str_end != version) - { - if (osNum > 15) { // Tahoe - ffStrbufSetStatic(&ds->dePrettyName, "Liquid Glass"); - } else if (osNum < 10) { - ffStrbufSetStatic(&ds->dePrettyName, "Platinum"); - } else { - ffStrbufSetStatic(&ds->dePrettyName, "Aqua"); - } - } - detectDisplays(ds); } diff --git a/src/detection/theme/theme_apple.c b/src/detection/theme/theme_apple.c new file mode 100644 index 0000000000..b46d5afbf2 --- /dev/null +++ b/src/detection/theme/theme_apple.c @@ -0,0 +1,24 @@ +#include "theme.h" + +#include "detection/os/os.h" + +const char* ffDetectTheme(FFThemeResult* result) +{ + const FFOSResult* os = ffDetectOS(); + + char* str_end; + const char* version = os->version.chars; + unsigned long osNum = strtoul(version, &str_end, 10); + if (str_end != version) + { + if (osNum > 15) { // Tahoe + ffStrbufSetStatic(&result->theme1, "Liquid Glass"); + } else if (osNum < 10) { + ffStrbufSetStatic(&result->theme1, "Platinum"); + } else { + ffStrbufSetStatic(&result->theme1, "Aqua"); + } + } + + return NULL; +} From 8be070998f531102b94486d4375154eb819d2d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 29 Sep 2025 09:40:10 +0800 Subject: [PATCH 12/61] Theme (Windows): moves Windows theme detection logic from DE to dedicated module Like the last commit --- CMakeLists.txt | 2 +- .../displayserver/displayserver_windows.c | 23 --------------- src/detection/theme/theme_windows.c | 29 +++++++++++++++++++ 3 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 src/detection/theme/theme_windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index baef303d7a..d52eb0da3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1044,7 +1044,7 @@ elseif(WIN32) src/detection/terminalfont/terminalfont_windows.c src/detection/terminalshell/terminalshell_windows.c src/detection/terminalsize/terminalsize_windows.c - src/detection/theme/theme_nosupport.c + src/detection/theme/theme_windows.c src/detection/tpm/tpm_windows.c src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 0773909602..55247ce731 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -254,27 +254,4 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) } detectDisplays(ds); - - //https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067 - const FFOSResult* os = ffDetectOS(); - uint32_t ver = (uint32_t) ffStrbufToUInt(&os->version, 0); - if (ver > 1000) - { - // Windows Server - if (ver >= 2016) - ffStrbufSetStatic(&ds->dePrettyName, "Fluent"); - else if (ver >= 2012) - ffStrbufSetStatic(&ds->dePrettyName, "Metro"); - else - ffStrbufSetStatic(&ds->dePrettyName, "Aero"); - } - else - { - if (ver >= 10) - ffStrbufSetStatic(&ds->dePrettyName, "Fluent"); - else if (ver >= 8) - ffStrbufSetStatic(&ds->dePrettyName, "Metro"); - else - ffStrbufSetStatic(&ds->dePrettyName, "Aero"); - } } diff --git a/src/detection/theme/theme_windows.c b/src/detection/theme/theme_windows.c new file mode 100644 index 0000000000..54853f62d5 --- /dev/null +++ b/src/detection/theme/theme_windows.c @@ -0,0 +1,29 @@ +#include "theme.h" + +#include "detection/os/os.h" + +const char* ffDetectTheme(FFThemeResult* result) +{ + const FFOSResult* os = ffDetectOS(); + uint32_t ver = (uint32_t) ffStrbufToUInt(&os->version, 0); + if (ver > 1000) + { + // Windows Server + if (ver >= 2016) + ffStrbufSetStatic(&result->theme1, "Fluent"); + else if (ver >= 2012) + ffStrbufSetStatic(&result->theme1, "Metro"); + else + ffStrbufSetStatic(&result->theme1, "Aero"); + } + else + { + if (ver >= 10) + ffStrbufSetStatic(&result->theme1, "Fluent"); + else if (ver >= 8) + ffStrbufSetStatic(&result->theme1, "Metro"); + else + ffStrbufSetStatic(&result->theme1, "Aero"); + } + return NULL; +} From 8b8e4a40a4d6f4e91034a8b109f8f8ccec57ca7d Mon Sep 17 00:00:00 2001 From: Rain Xelelo Date: Mon, 29 Sep 2025 05:01:03 +0300 Subject: [PATCH 13/61] Logo (Builtin): adds PrismLinux Fixes #1983 --- src/logo/ascii/prismlinux.txt | 17 +++++++++++++++++ src/logo/builtin.c | 9 +++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/logo/ascii/prismlinux.txt diff --git a/src/logo/ascii/prismlinux.txt b/src/logo/ascii/prismlinux.txt new file mode 100644 index 0000000000..ac27877191 --- /dev/null +++ b/src/logo/ascii/prismlinux.txt @@ -0,0 +1,17 @@ + .;oo;. + .;ldddol;. + .:cldddddolc:. + ':lloddddoooolcc:' + ':lllodddddooooolccc:, + ,:lllloddddooooollllccccc,. + .,clllllddddooooollllllccc::::,. + .,clllllloodoooooooollllccc:::::::,. +'cllllllllllllloooooollcccc::::::::::, + ,lllllllllllllooooolllccc::::::::::, + ,cllllllllllllloollllcc::::::::::; + 'clllllllllllllllcccc::::::::;:, + .clllllllccccc::cc:::::::::;:' + .cllllccccc:;;;:cc::::::;;:. + .cccccccc;;;:::::cc:::;;:. + .:cccc;;;:::::::::c::;:. + .;::::;;;;;;;;;;;;;::. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index c468066617..cb64d71110 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3998,6 +3998,15 @@ static const FFlogo P[] = { FF_COLOR_FG_WHITE, }, }, + // PrismLinux + { + .names = {"PrismLinux"}, + .lines = FASTFETCH_DATATEXT_LOGO_PRISMLINUX, + .colors = { + FF_COLOR_FG_BLUE, + FF_COLOR_FG_BLUE, + }, + }, // LAST {}, }; From 55a0c6e97d819615276fdaec9d8ea51a5d2072ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 29 Sep 2025 10:07:26 +0800 Subject: [PATCH 14/61] Logo (Builtin): adds EmperorOS Fixes #1963 --- src/logo/ascii/emperoros.txt | 13 +++++++++++++ src/logo/builtin.c | 9 +++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/logo/ascii/emperoros.txt diff --git a/src/logo/ascii/emperoros.txt b/src/logo/ascii/emperoros.txt new file mode 100644 index 0000000000..55dcaa97c7 --- /dev/null +++ b/src/logo/ascii/emperoros.txt @@ -0,0 +1,13 @@ + !! + !!!! + llllll + llllll + IIIIIIIIII + IIIIIIIIIIIIIIIIIIII +;;;;;;;;;;;;;;;;;;;;;;;; + ;;;;;;;;;;;;;;;;;;;; + :;;::;:;:: + :::::: + ,,,,,, + ,,,, + "" \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index cb64d71110..575ffa6a13 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1558,6 +1558,15 @@ static const FFlogo E[] = { .colorKeys = FF_COLOR_FG_DEFAULT, .colorTitle = FF_COLOR_FG_CYAN, }, + // EmperorOS + { + .names = {"Emperor"}, + .lines = FASTFETCH_DATATEXT_LOGO_EMPEROROS, + .colors = { + FF_COLOR_FG_YELLOW, + FF_COLOR_FG_DEFAULT, + }, + }, // EncryptOS { .names = {"EncryptOS"}, From e292bf1dee4f3fdefe4b52c7f5ec2f3d0a44532f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Sep 2025 09:02:03 +0800 Subject: [PATCH 15/61] OS (Linux): sets point release for Debian Fixes #1985 --- src/detection/os/os_linux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index b2d0621dc0..c90010f6f9 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -192,8 +192,10 @@ FF_MAYBE_UNUSED static void getDebianVersion(FFOSResult* result) ffAppendFileBuffer("/etc/debian_version", &debianVersion); ffStrbufTrimRightSpace(&debianVersion); if (!debianVersion.length) return; - ffStrbufSet(&result->version, &debianVersion); - ffStrbufSet(&result->versionID, &debianVersion); + ffStrbufDestroy(&result->versionID); + ffStrbufInitMove(&result->versionID, &debianVersion); + + ffStrbufSetF(&result->prettyName, "%s %s (%s)", result->name.chars, result->versionID.chars, result->codename.chars); } FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result) From 9b1e318bd1ef382e9824f5292e7914cd2f8ebfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Sep 2025 09:02:26 +0800 Subject: [PATCH 16/61] OS (Linux): sets code name for Ubuntu --- src/detection/os/os_linux.c | 48 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index c90010f6f9..6bf715c7da 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -59,17 +59,18 @@ FF_MAYBE_UNUSED static bool detectArmbianVersion(FFOSResult* result) return true; } -FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result) +// Returns false if PrettyName should be updated by caller +FF_MAYBE_UNUSED static bool getUbuntuFlavour(FFOSResult* result) { if (detectArmbianVersion(result)) - return; + return true; else if(ffStrbufStartsWithS(&result->prettyName, "Linux Lite ")) { ffStrbufSetStatic(&result->name, "Linux Lite"); ffStrbufSetStatic(&result->id, "linuxlite"); ffStrbufSetStatic(&result->idLike, "ubuntu"); ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Linux Lite ")); - return; + return true; } else if(ffStrbufStartsWithS(&result->prettyName, "Rhino Linux ")) { @@ -77,12 +78,13 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result) ffStrbufSetStatic(&result->id, "rhinolinux"); ffStrbufSetStatic(&result->idLike, "ubuntu"); ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Rhino Linux ")); - return; + return true; } else if(ffStrbufStartsWithS(&result->prettyName, "VanillaOS ")) { ffStrbufSetStatic(&result->id, "vanilla"); ffStrbufSetStatic(&result->idLike, "ubuntu"); + return true; } if (ffPathExists("/usr/bin/lliurex-version", FF_PATHTYPE_FILE)) @@ -97,93 +99,86 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result) ffStrbufTrimRightSpace(&result->version); ffStrbufSetF(&result->prettyName, "LliureX %s", result->version.chars); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return true; } const char* xdgConfigDirs = getenv("XDG_CONFIG_DIRS"); if(!ffStrSet(xdgConfigDirs)) - return; + return false; if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu")) { ffStrbufSetStatic(&result->name, "Kubuntu"); - ffStrbufSetF(&result->prettyName, "Kubuntu %s", result->version.chars); ffStrbufSetStatic(&result->id, "kubuntu"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "xfce") || ffStrContains(xdgConfigDirs, "xubuntu")) { ffStrbufSetStatic(&result->name, "Xubuntu"); - ffStrbufSetF(&result->prettyName, "Xubuntu %s", result->version.chars); ffStrbufSetStatic(&result->id, "xubuntu"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "lxqt") || ffStrContains(xdgConfigDirs, "lubuntu")) { ffStrbufSetStatic(&result->name, "Lubuntu"); - ffStrbufSetF(&result->prettyName, "Lubuntu %s", result->version.chars); ffStrbufSetStatic(&result->id, "lubuntu"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "budgie")) { ffStrbufSetStatic(&result->name, "Ubuntu Budgie"); - ffStrbufSetF(&result->prettyName, "Ubuntu Budgie %s", result->version.chars); ffStrbufSetStatic(&result->id, "ubuntu-budgie"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "cinnamon")) { ffStrbufSetStatic(&result->name, "Ubuntu Cinnamon"); - ffStrbufSetF(&result->prettyName, "Ubuntu Cinnamon %s", result->version.chars); ffStrbufSetStatic(&result->id, "ubuntu-cinnamon"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "mate")) { ffStrbufSetStatic(&result->name, "Ubuntu MATE"); - ffStrbufSetF(&result->prettyName, "Ubuntu MATE %s", result->version.chars); ffStrbufSetStatic(&result->id, "ubuntu-mate"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "studio")) { ffStrbufSetStatic(&result->name, "Ubuntu Studio"); - ffStrbufSetF(&result->prettyName, "Ubuntu Studio %s", result->version.chars); ffStrbufSetStatic(&result->id, "ubuntu-studio"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "sway")) { ffStrbufSetStatic(&result->name, "Ubuntu Sway"); - ffStrbufSetF(&result->prettyName, "Ubuntu Sway %s", result->version.chars); ffStrbufSetStatic(&result->id, "ubuntu-sway"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } if(ffStrContains(xdgConfigDirs, "touch")) { ffStrbufSetStatic(&result->name, "Ubuntu Touch"); - ffStrbufSetF(&result->prettyName, "Ubuntu Touch %s", result->version.chars); ffStrbufSetStatic(&result->id, "ubuntu-touch"); ffStrbufSetStatic(&result->idLike, "ubuntu"); - return; + return false; } + + return false; } FF_MAYBE_UNUSED static void getDebianVersion(FFOSResult* result) @@ -374,7 +369,10 @@ void ffDetectOSImpl(FFOSResult* os) #if __linux__ || __GNU__ if(ffStrbufEqualS(&os->id, "ubuntu")) - getUbuntuFlavour(os); + { + if (!getUbuntuFlavour(os)) + ffStrbufSetF(&os->prettyName, "%s %s", os->name.chars, os->version.chars); // os->version contains code name + } else if(ffStrbufEqualS(&os->id, "debian")) { if (!detectDebianDerived(os)) From 1594a69d6c37308ed367f66da6faa5ba6a49d726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Sep 2025 10:01:01 +0800 Subject: [PATCH 17/61] Kernel (Windows): move kernel.displayVersion to OS.codeName --- src/detection/os/os_windows.c | 20 ++++++++++++ src/modules/kernel/kernel.c | 9 +----- src/util/platform/FFPlatform.c | 1 - src/util/platform/FFPlatform.h | 1 - src/util/platform/FFPlatform_unix.c | 1 - src/util/platform/FFPlatform_windows.c | 44 +++++++++++--------------- 6 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/detection/os/os_windows.c b/src/detection/os/os_windows.c index ae3ff50832..1b6cc2e92a 100644 --- a/src/detection/os/os_windows.c +++ b/src/detection/os/os_windows.c @@ -2,11 +2,28 @@ #include "common/library.h" #include "util/windows/unicode.h" #include "util/stringUtils.h" +#include "util/windows/registry.h" #include PWSTR WINAPI BrandingFormatString(PCWSTR format); +static bool getCodeName(FFOSResult* os) +{ + FF_HKEY_AUTO_DESTROY hKey = NULL; + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL)) + return false; + + if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &os->codename, NULL)) + { + if (!ffRegReadStrbuf(hKey, L"CSDVersion", &os->codename, NULL)) // For Windows 7 and Windows 8 + if (!ffRegReadStrbuf(hKey, L"ReleaseId", &os->codename, NULL)) // For old Windows 10 + return false; + } + + return true; +} + void ffDetectOSImpl(FFOSResult* os) { //https://dennisbabkin.com/blog/?t=how-to-tell-the-real-version-of-windows-your-app-is-running-on#ver_string @@ -57,4 +74,7 @@ void ffDetectOSImpl(FFOSResult* os) ffStrbufAppendF(&os->id, "%s %s", os->name.chars, os->version.chars); ffStrbufSetStatic(&os->idLike, "Windows"); + + if (getCodeName(os) && os->codename.length > 0) + ffStrbufAppendF(&os->prettyName, " (%s)", os->codename.chars); } diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 62254b22c6..665361704e 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -10,12 +10,7 @@ bool ffPrintKernel(FFKernelOptions* options) if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - printf("%s %s", info->name.chars, info->release.chars); - - if(info->displayVersion.length > 0) - printf(" (%s)\n", info->displayVersion.chars); - else - putchar('\n'); + printf("%s %s\n", info->name.chars, info->release.chars); } else { @@ -26,7 +21,6 @@ bool ffPrintKernel(FFKernelOptions* options) FF_FORMAT_ARG(info->release, "release"), FF_FORMAT_ARG(info->version, "version"), FF_FORMAT_ARG(info->architecture, "arch"), - FF_FORMAT_ARG(info->displayVersion, "display-version"), FF_FORMAT_ARG(str, "page-size"), })); } @@ -61,7 +55,6 @@ bool ffGenerateKernelJsonResult(FF_MAYBE_UNUSED FFKernelOptions* options, yyjson yyjson_mut_obj_add_strbuf(doc, obj, "name", &info->name); yyjson_mut_obj_add_strbuf(doc, obj, "release", &info->release); yyjson_mut_obj_add_strbuf(doc, obj, "version", &info->version); - yyjson_mut_obj_add_strbuf(doc, obj, "displayVersion", &info->displayVersion); yyjson_mut_obj_add_uint(doc, obj, "pageSize", info->pageSize); return true; diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index 7db6abb229..5b0f554e01 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -56,7 +56,6 @@ void ffPlatformDestroy(FFPlatform* platform) ffStrbufDestroy(&info->name); ffStrbufDestroy(&info->release); ffStrbufDestroy(&info->version); - ffStrbufDestroy(&info->displayVersion); } void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path) diff --git a/src/util/platform/FFPlatform.h b/src/util/platform/FFPlatform.h index 79b7499125..2afd730f7d 100644 --- a/src/util/platform/FFPlatform.h +++ b/src/util/platform/FFPlatform.h @@ -9,7 +9,6 @@ typedef struct FFPlatformSysinfo FFstrbuf release; FFstrbuf version; FFstrbuf architecture; - FFstrbuf displayVersion; uint32_t pageSize; } FFPlatformSysinfo; diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 682c2e6f73..08379de98d 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -211,7 +211,6 @@ static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts) else #endif ffStrbufAppendS(&info->architecture, uts->machine); - ffStrbufInit(&info->displayVersion); #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__) size_t length = sizeof(info->pageSize); diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 92f4aad6a0..d886cdf0c1 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -168,15 +168,14 @@ static void getUserShell(FFPlatform* platform) ffStrbufReplaceAllC(&platform->userShell, '\\', '/'); } -static void detectWine(FFstrbuf* buf) +static const char* detectWine(void) { const char * __cdecl wine_get_version(void); HMODULE hntdll = GetModuleHandleW(L"ntdll.dll"); - if (!hntdll) return; + if (!hntdll) return NULL; FF_LIBRARY_LOAD_SYMBOL_LAZY(hntdll, wine_get_version); - if (!ffwine_get_version) return; - ffStrbufAppendS(buf, buf->length ? " - wine " : "wine "); - ffStrbufAppendS(buf, ffwine_get_version()); + if (!ffwine_get_version) return NULL; + return ffwine_get_version(); } static void getSystemReleaseAndVersion(FFPlatformSysinfo* info) @@ -199,29 +198,24 @@ static void getSystemReleaseAndVersion(FFPlatformSysinfo* info) (unsigned) osVersion.dwBuildNumber, (unsigned) ubr); - ffStrbufInit(&info->displayVersion); - if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &info->displayVersion, NULL)) - { - if (osVersion.szCSDVersion[0]) - ffStrbufSetWS(&info->displayVersion, osVersion.szCSDVersion); - else - ffRegReadStrbuf(hKey, L"ReleaseId", &info->displayVersion, NULL); // For old Windows 10 - } - detectWine(&info->displayVersion); - ffRegReadStrbuf(hKey, L"BuildLabEx", &info->version, NULL); - switch (osVersion.dwPlatformId) + const char* wineVersion = detectWine(); + if (wineVersion) + ffStrbufSetF(&info->name, "Wine_%s", wineVersion); { - case VER_PLATFORM_WIN32s: - ffStrbufSetStatic(&info->name, "WIN32s"); - break; - case VER_PLATFORM_WIN32_WINDOWS: - ffStrbufSetStatic(&info->name, "WIN32_WINDOWS"); - break; - case VER_PLATFORM_WIN32_NT: - ffStrbufSetStatic(&info->name, "WIN32_NT"); - break; + switch (osVersion.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + ffStrbufSetStatic(&info->name, "WIN32s"); + break; + case VER_PLATFORM_WIN32_WINDOWS: + ffStrbufSetStatic(&info->name, "WIN32_WINDOWS"); + break; + case VER_PLATFORM_WIN32_NT: + ffStrbufSetStatic(&info->name, "WIN32_NT"); + break; + } } } From c10b652a2e3933b0cc69f4f31ec4e99329816428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Sep 2025 10:05:08 +0800 Subject: [PATCH 18/61] Swap (Windows): prevents integer overflow in swap size Regression from 7ec0c664c541063dade5280c9e0efdde5ed6bdcf --- src/detection/swap/swap_windows.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/swap/swap_windows.c b/src/detection/swap/swap_windows.c index 26be6d204d..ad49658366 100644 --- a/src/detection/swap/swap_windows.c +++ b/src/detection/swap/swap_windows.c @@ -21,8 +21,8 @@ const char* ffDetectSwap(FFlist* result) ffStrbufInitNWS(&swap->name, current->FileName.Length / sizeof(wchar_t), current->FileName.Buffer); if (ffStrbufStartsWithS(&swap->name, "\\??\\")) ffStrbufSubstrAfter(&swap->name, strlen("\\??\\") - 1); - swap->bytesUsed = current->TotalUsed * pageSize; - swap->bytesTotal = current->CurrentSize * pageSize; + swap->bytesUsed = (uint64_t) current->TotalUsed * pageSize; + swap->bytesTotal = (uint64_t) current->CurrentSize * pageSize; if (current->NextEntryOffset == 0) break; } From e394efdd854f53afe5405cf285a75080942cf5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Sep 2025 13:19:58 +0800 Subject: [PATCH 19/61] OS (macOS): trims whitespace from full user name --- src/util/platform/FFPlatform_unix.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 08379de98d..85e624a0d6 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -1,4 +1,5 @@ #include "FFPlatform_private.h" +#include "util/FFstrbuf.h" #include "util/stringUtils.h" #include "fastfetch_config.h" #include "common/io/io.h" @@ -182,7 +183,11 @@ static void getUserName(FFPlatform* platform, const struct passwd* pwd) ffStrbufAppendS(&platform->userName, user); - if (pwd) ffStrbufAppendS(&platform->fullUserName, pwd->pw_gecos); + if (pwd) + { + ffStrbufAppendS(&platform->fullUserName, pwd->pw_gecos); + ffStrbufTrimSpace(&platform->fullUserName); + } } static void getHostName(FFPlatform* platform, const struct utsname* uts) From 09bef5f41dd49a3880b2457dc2f1dc36787cf556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Sep 2025 13:22:00 +0800 Subject: [PATCH 20/61] OS (macOS): removes fallback parsing of legacy macOS license file Doesn't work on Tahoe anymore --- src/detection/os/os_apple.m | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index 654d328895..8aabfabd4e 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -80,27 +80,6 @@ static bool detectOSCodeName(FFOSResult* os) return false; } -static void parseOSXSoftwareLicense(FFOSResult* os) -{ - FF_AUTO_CLOSE_FILE FILE* rtf = fopen("/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf", "r"); - if(rtf == NULL) - return; - - FF_AUTO_FREE char* line = NULL; - size_t len = 0; - const char* searchStr = "\\f0\\b SOFTWARE LICENSE AGREEMENT FOR macOS "; - while(getline(&line, &len, rtf) != EOF) - { - if (ffStrStartsWith(line, searchStr)) - { - ffStrbufAppendS(&os->codename, line + strlen(searchStr)); - ffStrbufTrimRight(&os->codename, '\n'); - ffStrbufTrimRight(&os->codename, '\\'); - break; - } - } -} - void ffDetectOSImpl(FFOSResult* os) { parseSystemVersion(os); @@ -115,6 +94,5 @@ void ffDetectOSImpl(FFOSResult* os) ffStrbufAppend(&os->versionID, &os->version); - if(!detectOSCodeName(os)) - parseOSXSoftwareLicense(os); + detectOSCodeName(os); } From e6e78a7aae6638c7f1234dd6b5efbf9d38370538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Sep 2025 13:35:48 +0800 Subject: [PATCH 21/61] OS (macOS): improves OS detection accuracy and sets pretty name --- src/detection/os/os_apple.m | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index 8aabfabd4e..82732ac79f 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -8,14 +8,14 @@ #include #import -static void parseSystemVersion(FFOSResult* os) +static bool parseSystemVersion(FFOSResult* os) { NSError* error; NSString* fileName = @"file:///System/Library/CoreServices/SystemVersion.plist"; NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName] error:&error]; if(error) - return; + return false; NSString* value; @@ -30,6 +30,8 @@ static void parseSystemVersion(FFOSResult* os) // macOS 26 Tahoe. #1809 os->version.chars[0] = '2'; } + + return true; } static bool detectOSCodeName(FFOSResult* os) @@ -86,13 +88,18 @@ void ffDetectOSImpl(FFOSResult* os) ffStrbufSetStatic(&os->id, "macos"); - if(os->version.length == 0) + if(__builtin_expect(os->name.length == 0, 0)) + ffStrbufSetStatic(&os->name, "macOS"); + + if(__builtin_expect(os->version.length == 0, 0)) ffSysctlGetString("kern.osproductversion", &os->version); - if(os->buildID.length == 0) + if(__builtin_expect(os->buildID.length == 0, 0)) ffSysctlGetString("kern.osversion", &os->buildID); ffStrbufAppend(&os->versionID, &os->version); detectOSCodeName(os); + + ffStrbufSetF(&os->prettyName, "%s %s %s (%s)", os->name.chars, os->codename.chars, os->version.chars, os->buildID.chars); } From 4d831c8c73a24389ce8a15387dac57365c4e9ad2 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 30 Sep 2025 15:24:12 +0800 Subject: [PATCH 22/61] OS (Linux): don't change prettyName on Ubuntu development branch Ref: #1483 --- src/detection/os/os_linux.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 6bf715c7da..e66e1fe62e 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -371,7 +371,10 @@ void ffDetectOSImpl(FFOSResult* os) if(ffStrbufEqualS(&os->id, "ubuntu")) { if (!getUbuntuFlavour(os)) - ffStrbufSetF(&os->prettyName, "%s %s", os->name.chars, os->version.chars); // os->version contains code name + { + if (!ffStrbufEndsWithS(&os->prettyName, " (development branch)")) + ffStrbufSetF(&os->prettyName, "%s %s", os->name.chars, os->version.chars); // os->version contains code name + } } else if(ffStrbufEqualS(&os->id, "debian")) { From 0a807ac1a3a7863be7a7184a323556e1e2eab73f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 1 Oct 2025 08:08:49 +0800 Subject: [PATCH 23/61] TerminalFont (Linux): fixes default font size for ghostty Fixes #1986 --- src/detection/terminalfont/terminalfont.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index a4468b9c15..19df07b020 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -105,7 +105,13 @@ static void detectGhostty(const FFstrbuf* exe, FFTerminalFontResult* terminalFon } if (fontSize.length == 0) { - ffStrbufAppendS(&fontSize, "13"); + ffStrbufAppendS(&fontSize, + #if __APPLE__ + "13" + #else + "12" + #endif + ); FF_DEBUG("using default size='%s'", fontSize.chars); } From 7a055a2254352b40bf05398dad443c861ad03240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Oct 2025 09:49:45 +0800 Subject: [PATCH 24/61] CI: upgrades compiler versions --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c64f3a642e..667270b171 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -520,8 +520,8 @@ jobs: run: | uname -a sudo pkg_add -u - sudo pkg_add -r llvm cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . + sudo pkg_add -r llvm-19.1.7p3 cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa + CC=clang-19 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false @@ -556,8 +556,8 @@ jobs: version: '10.1' run: | uname -a - sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . + sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick + CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false @@ -589,10 +589,10 @@ jobs: prepare: | uname -a pkg update - pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf + pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf run: | - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . + env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false From 554184ec72ef73c520ffe5aa03faed8eacc9bddd Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 1 Oct 2025 16:06:32 +0800 Subject: [PATCH 25/61] OS (Windows): restores compatibility with WINE Revert "OS (Windows): hard linking winbrand" This reverts commit 4146bb6731102b8bd35160b5300e781bad3c5752. --- CMakeLists.txt | 3 +- .../os/{os_windows.c => os_windows.cpp} | 46 ++++++++++++++++--- 2 files changed, 41 insertions(+), 8 deletions(-) rename src/detection/os/{os_windows.c => os_windows.cpp} (70%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d52eb0da3b..7c4071ea06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1035,7 +1035,7 @@ elseif(WIN32) src/detection/physicalmemory/physicalmemory_linux.c src/detection/netio/netio_windows.c src/detection/opengl/opengl_windows.c - src/detection/os/os_windows.c + src/detection/os/os_windows.cpp src/detection/packages/packages_windows.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_windows.c @@ -1689,7 +1689,6 @@ elseif(WIN32) PRIVATE "wtsapi32" PRIVATE "imagehlp" PRIVATE "cfgmgr32" - PRIVATE "winbrand" PRIVATE "propsys" PRIVATE "secur32" ) diff --git a/src/detection/os/os_windows.c b/src/detection/os/os_windows.cpp similarity index 70% rename from src/detection/os/os_windows.c rename to src/detection/os/os_windows.cpp index 1b6cc2e92a..39ce406e4c 100644 --- a/src/detection/os/os_windows.c +++ b/src/detection/os/os_windows.cpp @@ -1,10 +1,31 @@ +extern "C" { #include "os.h" #include "common/library.h" -#include "util/windows/unicode.h" #include "util/stringUtils.h" #include "util/windows/registry.h" +} +#include "util/windows/unicode.hpp" +#include "util/windows/wmi.hpp" + +static const char* getOsNameByWmi(FFstrbuf* osName) +{ + FFWmiQuery query(L"SELECT Caption FROM Win32_OperatingSystem"); + if(!query) + return "Query WMI service failed"; + + if(FFWmiRecord record = query.next()) + { + if(auto vtCaption = record.get(L"Caption")) + { + ffStrbufSetWSV(osName, vtCaption.get()); + ffStrbufTrimRight(osName, ' '); + return NULL; + } + return "Get Caption failed"; + } -#include + return "No WMI result returned"; +} PWSTR WINAPI BrandingFormatString(PCWSTR format); @@ -24,19 +45,32 @@ static bool getCodeName(FFOSResult* os) return true; } -void ffDetectOSImpl(FFOSResult* os) +static const char* getOsNameByWinbrand(FFstrbuf* osName) { //https://dennisbabkin.com/blog/?t=how-to-tell-the-real-version-of-windows-your-app-is-running-on#ver_string - const wchar_t* rawName = BrandingFormatString(L"%WINDOWS_LONG%"); - ffStrbufSetWS(&os->variant, rawName); + FF_LIBRARY_LOAD(winbrand, "dlopen winbrand" FF_LIBRARY_EXTENSION " failed", "winbrand" FF_LIBRARY_EXTENSION, 1); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(winbrand, BrandingFormatString); + + const wchar_t* rawName = ffBrandingFormatString(L"%WINDOWS_LONG%"); + ffStrbufSetWS(osName, rawName); GlobalFree((HGLOBAL)rawName); - ffStrbufSet(&os->prettyName, &os->variant); + return NULL; +} + +extern "C" +void ffDetectOSImpl(FFOSResult* os) +{ + if(getOsNameByWinbrand(&os->variant) && getOsNameByWmi(&os->variant)) + return; + ffStrbufTrimRight(&os->variant, ' '); //WMI returns the "Microsoft" prefix while BrandingFormatString doesn't. Make them consistent. if(ffStrbufStartsWithS(&os->variant, "Microsoft ")) ffStrbufSubstrAfter(&os->variant, strlen("Microsoft ") - 1); + ffStrbufSet(&os->prettyName, &os->variant); + if(ffStrbufStartsWithS(&os->variant, "Windows ")) { ffStrbufAppendS(&os->name, "Windows"); From 240ba5c00c2142f3a39c07d3db8dc9f8c1ed89df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 1 Oct 2025 16:45:13 +0800 Subject: [PATCH 26/61] Platform (Windows): adds missing else for Wine version detection --- src/util/platform/FFPlatform_windows.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index d886cdf0c1..ee45f68bf8 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -203,6 +203,7 @@ static void getSystemReleaseAndVersion(FFPlatformSysinfo* info) const char* wineVersion = detectWine(); if (wineVersion) ffStrbufSetF(&info->name, "Wine_%s", wineVersion); + else { switch (osVersion.dwPlatformId) { From 5d8c21a5caed0cf88aa36fb02574e216af48c3cd Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 2 Oct 2025 07:39:05 +0800 Subject: [PATCH 27/61] Memory (Linux): fallbacks to calcuate ourselves when `MemAvailable` seems unreasonable Fixes #1988 --- src/detection/memory/memory_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/memory/memory_linux.c b/src/detection/memory/memory_linux.c index 14c86bf938..42051279a2 100644 --- a/src/detection/memory/memory_linux.c +++ b/src/detection/memory/memory_linux.c @@ -28,7 +28,7 @@ const char* ffDetectMemory(FFMemoryResult* ram) if((token = strstr(buf, "MemAvailable:")) != NULL) memAvailable = strtoul(token + strlen("MemAvailable:"), NULL, 10); - else + if (memAvailable == 0 || memAvailable >= memTotal) // MemAvailable can be unreasonable. #1988 { if((token = strstr(buf, "MemFree:")) != NULL) memFree = strtoul(token + strlen("MemFree:"), NULL, 10); From 316d8ddf9b86182ded30f6144da99c759fb09caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 3 Oct 2025 12:16:15 +0800 Subject: [PATCH 28/61] CI (Linux): disables post operations for polyfilled binaries Fixes #1990 --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 667270b171..a987bde1b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,8 +145,10 @@ jobs: strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17 strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17 echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake + echo 'set(CPACK_PACKAGE_RELOCATABLE OFF)' >> CPackConfig.cmake echo 'set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)")' >> CPackConfig.cmake - cpack + echo 'set(CPACK_RPM_SPEC_MORE_DEFINE "%global __os_install_post %{nil}")' >> CPackConfig.cmake + cpack -V - name: upload artifacts uses: actions/upload-artifact@v4 From 1bbb21486c9b82c46018666f0797b86c2df64ad4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 3 Oct 2025 16:53:09 +0800 Subject: [PATCH 29/61] Disk (Linux): f* Android Fixes #1993 --- src/detection/disk/disk_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 8cb9130e91..68f783e4cd 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -10,7 +10,7 @@ #include #include -#ifdef STATX_BTIME +#if defined(STATX_BTIME) && !defined(__ANDROID__) #include #endif From 31ae7a642a180fca3c054074445eb064f9438e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 3 Oct 2025 23:41:26 +0800 Subject: [PATCH 30/61] Display (Windows): fixes incorrect refresh rate when VRR is enabled Fixes #1994 --- src/detection/displayserver/displayserver_windows.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 55247ce731..b25ea2b28f 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -1,8 +1,5 @@ #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 @@ -164,10 +161,11 @@ static void detectDisplays(FFDisplayServerResult* ds) preferredRefreshRate = freq.Numerator / (double) freq.Denominator; } + DISPLAYCONFIG_VIDEO_SIGNAL_INFO* signalInfo = &modes[path->targetInfo.modeInfoIdx].targetMode.targetVideoSignalInfo; FFDisplayResult* display = ffdsAppendDisplay(ds, width, height, - path->targetInfo.refreshRate.Numerator / (double) path->targetInfo.refreshRate.Denominator, + signalInfo->vSyncFreq.Numerator / (double) signalInfo->vSyncFreq.Denominator, (uint32_t) (monitorInfo->info.rcMonitor.right - monitorInfo->info.rcMonitor.left), (uint32_t) (monitorInfo->info.rcMonitor.bottom - monitorInfo->info.rcMonitor.top), preferredMode.width, From 77c43c02147a298d330b512739fbebb278d1604c Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 4 Oct 2025 18:34:50 +0800 Subject: [PATCH 31/61] Display (Linux): prefer resolutions reported by randr mode info --- src/detection/displayserver/linux/xcb.c | 6 +++--- src/detection/displayserver/linux/xlib.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 795e46bf2c..d00020c102 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -215,8 +215,8 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFDisplayResult* item = ffdsAppendDisplay( data->result, - (uint32_t) crtcInfoReply->width, - (uint32_t) crtcInfoReply->height, + (uint32_t) (currentMode ? currentMode->width : crtcInfoReply->width), + (uint32_t) (currentMode ? currentMode->height : crtcInfoReply->height), currentMode ? (double) currentMode->dot_clock / (double) ((uint32_t) currentMode->htotal * currentMode->vtotal) : 0, (uint32_t) (crtcInfoReply->width / scaleFactor + .5), (uint32_t) (crtcInfoReply->height / scaleFactor + .5), @@ -230,7 +230,7 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, 0, (uint32_t) outputInfoReply->mm_width, (uint32_t) outputInfoReply->mm_height, - "xcb-randr-crtc" + currentMode ? "xcb-randr-mode" : "xcb-randr-crtc" ); if (item && edidLength) { diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index bc2e83a774..0d7aeea294 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -134,8 +134,8 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* FFDisplayResult* item = ffdsAppendDisplay( data->result, - (uint32_t) crtcInfo->width, - (uint32_t) crtcInfo->height, + (uint32_t) (currentMode ? currentMode->width : crtcInfo->width), + (uint32_t) (currentMode ? currentMode->height : crtcInfo->height), currentMode ? (double) currentMode->dotClock / (double) ((uint32_t) currentMode->hTotal * currentMode->vTotal) : 0, (uint32_t) (crtcInfo->width / scaleFactor + .5), (uint32_t) (crtcInfo->height / scaleFactor + .5), @@ -149,7 +149,7 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* 0, (uint32_t) output->mm_width, (uint32_t) output->mm_height, - "xlib-randr-crtc" + currentMode ? "xlib-randr-mode" : "xlib-randr-crtc" ); if (item) From 66aad0e4f14983b9c093e8c55b8029ad809b3eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 5 Oct 2025 00:15:58 +0800 Subject: [PATCH 32/61] Revert "Display (Windows): fixes incorrect refresh rate when VRR is enabled" Doesn't work This reverts commit 31ae7a642a180fca3c054074445eb064f9438e2b. --- src/detection/displayserver/displayserver_windows.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index b25ea2b28f..307bc497ae 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -161,11 +161,10 @@ static void detectDisplays(FFDisplayServerResult* ds) preferredRefreshRate = freq.Numerator / (double) freq.Denominator; } - DISPLAYCONFIG_VIDEO_SIGNAL_INFO* signalInfo = &modes[path->targetInfo.modeInfoIdx].targetMode.targetVideoSignalInfo; FFDisplayResult* display = ffdsAppendDisplay(ds, width, height, - signalInfo->vSyncFreq.Numerator / (double) signalInfo->vSyncFreq.Denominator, + path->targetInfo.refreshRate.Numerator / (double) path->targetInfo.refreshRate.Denominator, (uint32_t) (monitorInfo->info.rcMonitor.right - monitorInfo->info.rcMonitor.left), (uint32_t) (monitorInfo->info.rcMonitor.bottom - monitorInfo->info.rcMonitor.top), preferredMode.width, From e84739bff002d2413ba25d7b0669c22306563b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 5 Oct 2025 09:15:59 +0800 Subject: [PATCH 33/61] Logo (Builtin): update T2 --- src/logo/ascii/t2.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/logo/ascii/t2.txt b/src/logo/ascii/t2.txt index 1a4b858ce0..c174d0ee31 100644 --- a/src/logo/ascii/t2.txt +++ b/src/logo/ascii/t2.txt @@ -1,14 +1,14 @@ - $3//$2 $3//$2 - $1TTTTTTTTTTTTTTT$2 $3//$2 $1..::$2 $4:-:.$2 - $4ttt$2 $3//$2 $1.::.$2 $4.:-:$2 - $4ttt$2 $3//$2 $1.:.$2 $4--$2 - $4ttt$2 $3//$2 $4:-:$2 - $4ttt$2 $3//$2 $4.:-:$2 - $4ttt$2 $3//$2 $4:-:.$2 - $4ttt$2 $3//$2 $4.--.$2 - $4ttt$2 $3//$2 $4.:-:$2 - $4ttt$2 $3//$2 $4...$2 - $4ttt$2 $3//$2 - $3//$2 $3.:::::::::::.$2 - $3//$2 +$1TTTTTTTTTTTTTTT$2 $3//$2 +$1TTTTTTTTTTTTTTT$2 $3//$2 $1..::$2 $4:-:.$2 + $4ttt$2 $3//$2 $1.::.$2 $4.:-:$2 + $4ttt$2 $3//$2 $1.:.$2 $4--$2 + $4ttt$2 $3//$2 $4:-:$2 + $4ttt$2 $3//$2 $4.:-:$2 + $4ttt$2 $3//$2 $4:-:.$2 + $4ttt$2 $3//$2 $4.--.$2 + $4ttt$2 $3//$2 $4.:-:$2 + $4ttt$2 $3//$2 $4...$2 + $4ttt$2 $3//$2 + $3//$2 $3.:::::::::::.$2 + $3//$2 From f4c43abbf7a2e8a9d52e4d0312c2b6379021e55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 3 Oct 2025 23:56:30 +0800 Subject: [PATCH 34/61] Display (Windows): adds VRR status detection support --- src/detection/displayserver/displayserver.c | 1 + src/detection/displayserver/displayserver.h | 8 ++++++++ .../displayserver/displayserver_windows.c | 1 + src/modules/display/display.c | 15 +++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 6ae9efbc48..25f06c844d 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -45,6 +45,7 @@ FFDisplayResult* ffdsAppendDisplay( display->manufactureYear = 0; display->manufactureWeek = 0; display->serial = 0; + display->vrrStatus = FF_DISPLAY_VRR_STATUS_UNKNOWN; return display; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 3e9efea084..1dfa1a3513 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -60,6 +60,13 @@ typedef enum __attribute__((__packed__)) FFDisplayHdrStatus FF_DISPLAY_HDR_STATUS_ENABLED, } FFDisplayHdrStatus; +typedef enum __attribute__((__packed__)) FFDisplayVrrStatus +{ + FF_DISPLAY_VRR_STATUS_UNKNOWN, + FF_DISPLAY_VRR_STATUS_DISABLED, + FF_DISPLAY_VRR_STATUS_ENABLED, +} FFDisplayVrrStatus; + typedef struct FFDisplayResult { uint32_t width; // in px @@ -83,6 +90,7 @@ typedef struct FFDisplayResult uint16_t manufactureYear; uint16_t manufactureWeek; uint32_t serial; + FFDisplayVrrStatus vrrStatus; } FFDisplayResult; typedef struct FFDisplayServerResult diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 307bc497ae..88d1a2e007 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -229,6 +229,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } if (edidLength > 0) ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); + display->vrrStatus = path->flags & DISPLAYCONFIG_PATH_BOOST_REFRESH_RATE ? FF_DISPLAY_VRR_STATUS_ENABLED : FF_DISPLAY_VRR_STATUS_DISABLED; } } } diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 7d8e80d962..2d3a87ce60 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -348,6 +348,21 @@ bool ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_uint(doc, output, "height", item->height); yyjson_mut_obj_add_real(doc, output, "refreshRate", item->refreshRate); + if (item->vrrStatus == FF_DISPLAY_VRR_STATUS_UNKNOWN) + yyjson_mut_obj_add_null(doc, output, "vrrStatus"); + else switch (item->vrrStatus) + { + case FF_DISPLAY_VRR_STATUS_DISABLED: + yyjson_mut_obj_add_str(doc, output, "vrrStatus", "Disabled"); + break; + case FF_DISPLAY_VRR_STATUS_ENABLED: + yyjson_mut_obj_add_str(doc, output, "vrrStatus", "Enabled"); + break; + default: + yyjson_mut_obj_add_str(doc, output, "vrrStatus", "Unknown"); + break; + } + 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); From af26828f910c91d4e1dd11dab5bfe2e0df636ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 5 Oct 2025 09:22:06 +0800 Subject: [PATCH 35/61] =?UTF-8?q?CPU=20(Linux):=20adds=20support=20for=20H?= =?UTF-8?q?P=20PA=E2=80=91RISC=20&=20SuperH=20CPU=20architecture=20detecti?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detection/cpu/cpu_linux.c | 4 ++++ src/detection/version/version.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 06145e802b..4f8c65538d 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -360,6 +360,10 @@ static const char* parseCpuInfo( (cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) || (cpu->vendor.length == 0 && ffParsePropLine(line, "vendor :", &cpu->vendor)) || (cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz :", cpuMHz)) || + #elif __hppa__ + (cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || + #elif __sh__ + (cpu->name.length == 0 && ffParsePropLine(line, "cpu type :", &cpu->name)) || #else (cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) || (cpu->name.length == 0 && ffParsePropLine(line, "model :", &cpu->name)) || diff --git a/src/detection/version/version.c b/src/detection/version/version.c index 7d278107e7..edccce86d5 100644 --- a/src/detection/version/version.c +++ b/src/detection/version/version.c @@ -26,6 +26,8 @@ #define FF_ARCHITECTURE "alpha" #elif defined(__hppa__) #define FF_ARCHITECTURE "hppa" +#elif defined(__sh__) + #define FF_ARCHITECTURE "sh" #elif defined(__m68k__) #define FF_ARCHITECTURE "m68k" #else From 6b8b7c1a62927747efff9a1003721c3665b7d80e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 7 Oct 2025 23:26:05 +0800 Subject: [PATCH 36/61] CI (Windows): signs PE files --- .github/workflows/ci.yml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a987bde1b9..e879816c9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -707,17 +707,41 @@ jobs: - name: run tests run: ctest --output-on-failure + - if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch' + id: upload-unsigned-artifact + name: upload artifacts for signing + uses: actions/upload-artifact@v4 + with: + name: fastfetch-windows-${{ matrix.arch }} + path: | + *.dll + fastfetch.exe + flashfetch.exe + + - if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch' + name: submit signing request + uses: signpath/github-action-submit-signing-request@v1 + with: + api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' + organization-id: '${{ vars.SIGNPATH_ORG_ID }}' + project-slug: 'fastfetch' + signing-policy-slug: 'test-signing' + github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}' + wait-for-completion: true + output-artifact-directory: '.' + - name: create zip archive run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets - name: create 7z archive run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets - - name: upload artifacts + - name: upload true artifacts uses: actions/upload-artifact@v4 with: name: fastfetch-windows-${{ matrix.arch }} path: ./fastfetch-windows-${{ matrix.arch }}.* + overwrite: true release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch' From f3a8fedf0a70e28ef8a71ce58790419a3ab0996b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 10 Oct 2025 10:50:20 +0800 Subject: [PATCH 37/61] CPU (Linux): improves SoC name detection from device tree Fixes #1997 --- src/detection/cpu/cpu_linux.c | 47 +++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 4f8c65538d..18a6ae01f3 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -621,19 +621,46 @@ FF_MAYBE_UNUSED static void detectSocName(FFCPUResult* cpu) if (cpu->name.length > 0) return; - // device-vendor,device-model\0soc-vendor,soc-model\0 - char content[256]; + // [x-vendor,x-model\0]*N + char content[512]; ssize_t length = ffReadFileData("/proc/device-tree/compatible", ARRAY_SIZE(content), content); - if (length <= 2) return; + if (length < 4) return; // v,m\0 - // get the second NUL terminated string if it exists - char* vendor = memchr(content, '\0', (size_t) length) + 1; - if (!vendor || vendor - content >= length) vendor = content; + if (content[length - 1] != '\0') return; // must end with \0 - char* model = strchr(vendor, ','); - if (!model) return; - *model = '\0'; - ++model; + --length; + + char* vendor = NULL; + char* model = NULL; + + for (char* p; length > 0; length = p ? (ssize_t) (p - content) - 1 : 0) + { + p = memrchr(content, '\0', (size_t) length); + + vendor = p /* first entry */ ? p + 1 : content; + + size_t partLen = (size_t) (length - (vendor - content)); + if (partLen < 3) continue; + + char* comma = memchr(vendor, ',', partLen); + if (!comma) continue; + + size_t vendorLen = (size_t) (comma - vendor); + if (vendorLen == 0) continue; + + model = comma + 1; + size_t modelLen = (size_t) (partLen - (size_t) (model - vendor)); + if (modelLen == 0) continue; + + if ((modelLen >= strlen("-platform") && ffStrEndsWith(model, "-platform")) || + (modelLen >= strlen("-soc") && ffStrEndsWith(model, "-soc"))) + continue; + + *comma = '\0'; + break; + } + + if (!length) return; if (false) {} #if __aarch64__ From 88c8dcb3e8d668155e03195f980adf46d84834b3 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 10 Oct 2025 10:55:12 +0800 Subject: [PATCH 38/61] CPU (Linux): improves detection for T-Head CPU vendor Ref: #1997 --- src/detection/cpu/cpu_linux.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 18a6ae01f3..5ee6dcdd32 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -716,6 +716,13 @@ FF_MAYBE_UNUSED static void detectSocName(FFCPUResult* cpu) for (const char* p = model; *p; ++p) ffStrbufAppendC(&cpu->name, (char) toupper(*p)); } + else if (ffStrEquals(vendor, "thead")) + { + // Lichee Pi? + ffStrbufSetStatic(&cpu->vendor, "T-Head"); + for (const char* p = model; *p; ++p) + ffStrbufAppendC(&cpu->name, (char) toupper(*p)); + } else { ffStrbufSetS(&cpu->name, model); From 24459b2fbf26840e1d1c3ab011022d6c9afac967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 10 Oct 2025 14:24:11 +0800 Subject: [PATCH 39/61] Brightness (macOS): enhance DDC/CI detection by enumerating all I2C buses --- src/detection/brightness/brightness_apple.c | 93 ++++++++++++--------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index de3750a941..5552e61411 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -55,7 +55,7 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa // Works for Apple Silicon and USB-C adapter connection ( but not HTMI ) static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) { - if (!IOAVServiceCreate || !IOAVServiceReadI2C) + if (!IOAVServiceCreate || !IOAVServiceReadI2C || !IOAVServiceWriteI2C) return "IOAVService is not available"; FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL; @@ -136,52 +136,63 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F if (framebuffer == 0) continue; IOItemCount count; - if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue; - - io_service_t interface = 0; - if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue; - - uint8_t i2cOut[12] = {}; - IOI2CConnectRef connect; - if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) + if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) { - IOObjectRelease(interface); + IOObjectRelease(framebuffer); continue; } - uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 }; - i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3]; - - IOI2CRequest request = { - .commFlags = kNilOptions, - .sendAddress = 0x6e, - .sendTransactionType = kIOI2CSimpleTransactionType, - .sendBuffer = (vm_address_t) i2cIn, - .sendBytes = ARRAY_SIZE(i2cIn), - .minReplyDelay = options->ddcciSleep, - .replyAddress = 0x6F, - .replySubAddress = 0x51, - .replyTransactionType = kIOI2CDDCciReplyTransactionType, - .replyBytes = ARRAY_SIZE(i2cOut), - .replyBuffer = (vm_address_t) i2cOut, - }; - IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); - IOI2CInterfaceClose(connect, kNilOptions); - IOObjectRelease(interface); - - if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue; - - if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; + bool found = false; + for (IOItemCount bus = 0; bus < count && !found; ++bus) + { + io_service_t interface = 0; + if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue; + + uint8_t i2cOut[12] = {}; + IOI2CConnectRef connect; + if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) + { + IOObjectRelease(interface); + continue; + } + + uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 }; + i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3]; + + IOI2CRequest request = { + .commFlags = kNilOptions, + .sendAddress = 0x6e, + .sendTransactionType = kIOI2CSimpleTransactionType, + .sendBuffer = (vm_address_t) i2cIn, + .sendBytes = ARRAY_SIZE(i2cIn), + .minReplyDelay = options->ddcciSleep * 1000ULL, + .replyAddress = 0x6F, + .replySubAddress = 0x51, + .replyTransactionType = kIOI2CDDCciReplyTransactionType, + .replyBytes = ARRAY_SIZE(i2cOut), + .replyBuffer = (vm_address_t) i2cOut, + }; + IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); + IOI2CInterfaceClose(connect, kNilOptions); + IOObjectRelease(interface); - uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9]; - uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7]; + if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess || request.replyBytes < 10) continue; + if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; - FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->max = max; - brightness->min = 0; - brightness->current = current; - ffStrbufInitCopy(&brightness->name, &display->name); - brightness->builtin = false; + uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9]; + uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7]; + + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); + brightness->max = max; + brightness->min = 0; + brightness->current = current; + ffStrbufInitCopy(&brightness->name, &display->name); + brightness->builtin = false; + + found = true; + } + + IOObjectRelease(framebuffer); } } From 185a9211f1f2f452828e180d76a60883b134eb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 10 Oct 2025 15:09:25 +0800 Subject: [PATCH 40/61] Doc: update changelog --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a07852c8f9..72ec51bdc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +# 2.54.0 + +Changes: +* Moves macOS and Windows design language detection from the DE module to the Theme module + +Features: +* Adds `--json` and `-j` command line flags as a shortcut for `--format json` +* Various improvements to the OS module (OS) + * Displays point releases for Debian + * Displays code names for Ubuntu + * Displays build ID for macOS + * Displays code names for Windows (previously shown in the Kernel module) +* Adds basic support for Wine (Windows) +* Adds basic support for hppa and sh architectures (CPU, Linux) +* Improves T-Head SoC name detection from the device tree (#1997, CPU, Linux) + +Bugfixes: +* Avoids integer overflow when calculating swap size (#1988, Swap, Windows) +* Trims whitespace from full user name (Title, macOS) +* Fixes default font size for Ghostty (#1986, TerminalFont, Linux) +* Works around an issue that could report impossibly high memory usage in rare cases (#1988, Memory, Linux) +* Fixes incorrect glibc dependency in polyfilled DEB packages (#1983, Linux) +* Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux) +* Fixes crashes on ancient Android kernels (#1993, Disk, Android) +* Prefers resolutions reported by randr mode info, fixing incorrect resolutions reported on XFCE when scaling is enabled (Display, Linux) + +Logos: +* Adds secureblue, PrismLinux, EmperorOS +* Updates T2 + # 2.53.0 Changes: From 0b9ecdeadea9966c5cb3dc39e8f93355276e0e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 11 Oct 2025 09:29:41 +0800 Subject: [PATCH 41/61] Doc: adds Chinese README [ci skip] --- .github/FUNDING.yml | 3 +- README-cn.md | 75 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 +- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 README-cn.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index df28f14944..fbf9686579 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,3 @@ -ko_fi: carterli github: LinusDierheimer +ko_fi: carterli +custom: https://paypal.me/zhangsongcui diff --git a/README-cn.md b/README-cn.md new file mode 100644 index 0000000000..ac2e075a5f --- /dev/null +++ b/README-cn.md @@ -0,0 +1,75 @@ +# Fastfetch + +Fastfetch 是一款类似 neofetch 的系统信息展示工具,主要用 C 编写,强调性能和可定制性。支持 Linux、macOS、Windows 7+、Android、FreeBSD、OpenBSD、NetBSD、DragonFly、Haiku、SunOS。 + +示例配置见 presets/examples,更多截图与平台说明见 Wiki。 + +## 安装 + +Linux(部分): +- Debian 13+ / Ubuntu: apt install fastfetch +- Arch: pacman -S fastfetch +- Fedora: dnf install fastfetch +- openSUSE: zypper install fastfetch +- Linuxbrew:brew install fastfetch +- 各发行版打包状态:https://repology.org/project/fastfetch/versions + +macOS: +- Homebrew:brew install fastfetch +- MacPorts:sudo port install fastfetch + +Windows: +- scoop install fastfetch +- choco install fastfetch +- winget install fastfetch +- MSYS2:pacman -S mingw-w64---fastfetch + +BSD: +- FreeBSD:pkg install fastfetch +- NetBSD:pkgin in fastfetch +- OpenBSD:pkg_add fastfetch + +Android(Termux): +- pkg install fastfetch + +Nightly 构建: +- https://nightly.link/fastfetch-cli/fastfetch/workflows/ci/dev?preview + +## 源码构建 + +基本上是 `cmake . && make`。详见 Wiki:https://github.com/fastfetch-cli/fastfetch/wiki/Building + +## 使用 + +- 默认运行:`fastfetch` +- 查看所有可用模块示例:`fastfetch -c all.jsonc` +- 以 JSON 输出指定模块:`fastfetch -s [:] --format json` +- 完整命令行帮助:`fastfetch --help` +- 生成最小配置:`fastfetch --gen-config []` + - 生成完整配置:`fastfetch --gen-config-full` + - 请使用支持 JSON schema 的编辑器(如 VSCode)编辑配置文件! + - 如果你连接 Github 有网络困难(智能提示不生效),可将配置文件中的 `$schema` 的值替换为 `https://gitee.com/carterl/fastfetch/raw/dev/doc/json_schema.json` + +## 定制 + +- 配置使用 JSONC,语法与选项见 Wiki:https://github.com/fastfetch-cli/fastfetch/wiki/Configuration +- 预设示例位于 presets,可用 `-c ` 加载 +- Logo 选项与图像显示见文档:https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options +- 模块格式化(示例,仅显示 GPU 名称): +```jsonc +{ + "modules": [ + { "type": "gpu", "format": "{name}" } + ] +} +``` +详见:https://github.com/fastfetch-cli/fastfetch/wiki/Format-String-Guide + +## 反馈与支持 + +- 使用问题:Discussions https://github.com/fastfetch-cli/fastfetch/discussions +- 疑似缺陷:Issues https://github.com/fastfetch-cli/fastfetch/issues(请填写模版) + +## 赞助 + + diff --git a/README.md b/README.md index 39ad40a4a9..42132af4e8 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ [![latest packaged version(s)](https://repology.org/badge/latest-versions/fastfetch.svg)](https://repology.org/project/fastfetch/versions) [![Packaging status](https://repology.org/badge/tiny-repos/fastfetch.svg)](https://repology.org/project/fastfetch/versions) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/fastfetch-cli/fastfetch) +[![中文README](https://img.shields.io/badge/%E4%B8%AD%E6%96%87-README-red)](README-cn.md) Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and SunOS. @@ -314,7 +315,7 @@ Otherwise, please open a feature request in [GitHub Issues](https://github.com/f If you find Fastfetch useful, please consider donating. -* Current maintainer: [@CarterLi](https://ko-fi.com/carterli) +* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui) * Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer) ## Star History From 78c6d7104999fe79222513c30adae249668360f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 11 Oct 2025 16:19:11 +0800 Subject: [PATCH 42/61] Disk (Linux): adds glob pattern matching for hidden disk folders Fixes #1999 --- src/modules/disk/disk.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index d33cf3d6fb..c9995db4f7 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -5,7 +5,10 @@ #include "common/time.h" #include "detection/disk/disk.h" #include "modules/disk/disk.h" -#include "util/stringUtils.h" + +#ifndef _WIN32 + #include +#endif #pragma GCC diagnostic ignored "-Wsign-conversion" @@ -186,6 +189,30 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index } } +static inline bool isMatchFolders(FFstrbuf* folders, const FFstrbuf* path, char separator) +{ + #ifndef _WIN32 + uint32_t startIndex = 0; + while(startIndex < folders->length) + { + uint32_t colonIndex = ffStrbufNextIndexC(folders, startIndex, separator); + + char savedColon = folders->chars[colonIndex]; // Can be '\0' if at end + folders->chars[colonIndex] = '\0'; + + bool matched = fnmatch(&folders->chars[startIndex], path->chars, 0) == 0; + folders->chars[colonIndex] = savedColon; + + if (matched) return true; + + startIndex = colonIndex + 1; + } + return false; + #else + return ffStrbufSeparatedContain(folders, path, separator); + #endif +} + bool ffPrintDisk(FFDiskOptions* options) { FF_LIST_AUTO_DESTROY disks = ffListCreate(sizeof (FFDisk)); @@ -203,8 +230,11 @@ bool ffPrintDisk(FFDiskOptions* options) if(__builtin_expect(options->folders.length == 0, 1) && (disk->type & ~options->showTypes)) continue; - if (options->hideFolders.length && ffStrbufSeparatedContain(&options->hideFolders, &disk->mountpoint, FF_DISK_FOLDER_SEPARATOR)) - continue; + if (options->hideFolders.length) + { + if (isMatchFolders(&options->hideFolders, &disk->mountpoint, FF_DISK_FOLDER_SEPARATOR)) + continue; + } if (options->hideFS.length && ffStrbufSeparatedContain(&options->hideFS, &disk->filesystem, ':')) continue; @@ -452,7 +482,7 @@ void ffInitDiskOptions(FFDiskOptions* options) #if _WIN32 || __APPLE__ || __ANDROID__ ffStrbufInit(&options->hideFolders); #else - ffStrbufInitStatic(&options->hideFolders, "/efi:/boot:/boot/efi:/boot/firmware"); + ffStrbufInitS(&options->hideFolders, "/efi:/boot:/boot/efi:/boot/firmware"); #endif ffStrbufInit(&options->hideFS); options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT; From 1631f74700de7f1c24d94299f9d4ce4fa46fc1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 11 Oct 2025 18:20:56 +0800 Subject: [PATCH 43/61] Disk (Linux): revisits 78c6d7104999fe79222513c30adae249668360f1 --- CHANGELOG.md | 2 ++ doc/json_schema.json | 4 ++-- src/modules/disk/disk.c | 9 +++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72ec51bdc2..33d59456f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Features: * Adds basic support for Wine (Windows) * Adds basic support for hppa and sh architectures (CPU, Linux) * Improves T-Head SoC name detection from the device tree (#1997, CPU, Linux) +* `Disk.hideFolders` now supports glob patterns (Disk) + * For example, `/boot/*` will match both `/boot/efi` and `/boot/firmware` Bugfixes: * Avoids integer overflow when calculating swap size (#1988, Swap, Windows) diff --git a/doc/json_schema.json b/doc/json_schema.json index d32269bd25..e39d4cf42c 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -2326,7 +2326,7 @@ ] }, "hideFolders": { - "description": "A list of folder paths to hide from the disk output", + "description": "A list of folder paths (or glob patterns) to hide from the disk output", "oneOf": [ { "type": "string", @@ -2342,7 +2342,7 @@ "uniqueItems": true } ], - "default": "/efi:/boot:/boot/efi:/boot/firmware" + "default": "/efi:/boot:/boot/*" }, "hideFS": { "description": "A list of file systems to hide from the disk output", diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index c9995db4f7..3369287c2e 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -230,11 +230,8 @@ bool ffPrintDisk(FFDiskOptions* options) if(__builtin_expect(options->folders.length == 0, 1) && (disk->type & ~options->showTypes)) continue; - if (options->hideFolders.length) - { - if (isMatchFolders(&options->hideFolders, &disk->mountpoint, FF_DISK_FOLDER_SEPARATOR)) - continue; - } + if (options->hideFolders.length && isMatchFolders(&options->hideFolders, &disk->mountpoint, FF_DISK_FOLDER_SEPARATOR)) + continue; if (options->hideFS.length && ffStrbufSeparatedContain(&options->hideFS, &disk->filesystem, ':')) continue; @@ -482,7 +479,7 @@ void ffInitDiskOptions(FFDiskOptions* options) #if _WIN32 || __APPLE__ || __ANDROID__ ffStrbufInit(&options->hideFolders); #else - ffStrbufInitS(&options->hideFolders, "/efi:/boot:/boot/efi:/boot/firmware"); + ffStrbufInitS(&options->hideFolders, "/efi:/boot:/boot/*"); #endif ffStrbufInit(&options->hideFS); options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT; From e3a698f7b1432821ec14eb480eea001cfac73fd6 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 11 Oct 2025 21:26:37 +0800 Subject: [PATCH 44/61] Brightness (macOS): fixes detection for external monitor on Intel platform --- src/detection/brightness/brightness_apple.c | 65 +++++++++++++++------ 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index 5552e61411..7d91e8ebf0 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -123,38 +123,70 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* return NULL; } #else +static IOOptionBits getSupportedTransactionType(void) { + FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL; + + if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("IOFramebufferI2CInterface"), &iterator) != KERN_SUCCESS) + return 0; + + io_registry_entry_t registryEntry; + while ((registryEntry = IOIteratorNext(iterator)) != MACH_PORT_NULL) + { + FF_IOOBJECT_AUTO_RELEASE io_service_t io_service = registryEntry; + FF_CFTYPE_AUTO_RELEASE CFNumberRef IOI2CTransactionTypes = IORegistryEntryCreateCFProperty(io_service, CFSTR(kIOI2CTransactionTypesKey), kCFAllocatorDefault, kNilOptions); + + if (IOI2CTransactionTypes) + { + int64_t types = 0; + ffCfNumGetInt64(IOI2CTransactionTypes, &types); + + /* + We want DDCciReply but Simple is better than No-thing. + Combined and DisplayPortNative are not useful in our case. + */ + if (types) { + if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types) + return kIOI2CSimpleTransactionType; + if ((1 << kIOI2CDDCciReplyTransactionType) & (uint64_t) types) + return kIOI2CDDCciReplyTransactionType; + if ((1 << kIOI2CCombinedTransactionType) & (uint64_t) types) + return kIOI2CCombinedTransactionType; + if ((1 << kIOI2CDisplayPortNativeTransactionType) & (uint64_t) types) + return kIOI2CDisplayPortNativeTransactionType; + } + } + break; + } + + return 0; +} + static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) { if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available"; + IOOptionBits transactionType = getSupportedTransactionType(); FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) { if (display->type == FF_DISPLAY_TYPE_EXTERNAL) { - io_service_t framebuffer = 0; + FF_IOOBJECT_AUTO_RELEASE io_service_t framebuffer = IO_OBJECT_NULL; CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer); - if (framebuffer == 0) continue; + if (framebuffer == IO_OBJECT_NULL) continue; IOItemCount count; if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) - { - IOObjectRelease(framebuffer); continue; - } - bool found = false; - for (IOItemCount bus = 0; bus < count && !found; ++bus) + for (IOItemCount bus = 0; bus < count; ++bus) { - io_service_t interface = 0; - if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue; + FF_IOOBJECT_AUTO_RELEASE io_service_t interface = IO_OBJECT_NULL; + if (IOFBCopyI2CInterfaceForBus(framebuffer, bus, &interface) != KERN_SUCCESS) continue; uint8_t i2cOut[12] = {}; - IOI2CConnectRef connect; + IOI2CConnectRef connect = NULL; if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS) - { - IOObjectRelease(interface); continue; - } uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 }; i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3]; @@ -168,13 +200,12 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F .minReplyDelay = options->ddcciSleep * 1000ULL, .replyAddress = 0x6F, .replySubAddress = 0x51, - .replyTransactionType = kIOI2CDDCciReplyTransactionType, + .replyTransactionType = transactionType, .replyBytes = ARRAY_SIZE(i2cOut), .replyBuffer = (vm_address_t) i2cOut, }; IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); IOI2CInterfaceClose(connect, kNilOptions); - IOObjectRelease(interface); if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess || request.replyBytes < 10) continue; if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; @@ -189,10 +220,8 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F ffStrbufInitCopy(&brightness->name, &display->name); brightness->builtin = false; - found = true; + break; } - - IOObjectRelease(framebuffer); } } From 32dcf9487fe04620f7db1264389f8a5caf5133bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 13 Oct 2025 09:54:34 +0800 Subject: [PATCH 45/61] Option: adds configurable spacing between icon and string keys Fixes #2004 --- doc/json_schema.json | 23 ++++++++++++++++++++++- src/common/option.h | 8 +++++++- src/common/printing.c | 13 +++++++------ src/data/help.json | 7 ++++++- src/options/display.c | 10 ++++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index e39d4cf42c..f8f34d607e 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1024,9 +1024,30 @@ }, { "const": "both", - "description": "Show both icon and string keys" + "description": "Show both icon and string keys (alias of `both-1`)" + }, + { + "const": "both-0", + "description": "Show both icon and string with no spaces between them" + }, + { + "const": "both-1", + "description": "Show both icon and string with a space between them" + }, + { + "const": "both-2", + "description": "Show both icon and string with 2 spaces between them" + }, + { + "const": "both-3", + "description": "Show both icon and string with 3 spaces between them" + }, + { + "const": "both-4", + "description": "Show both icon and string with 4 spaces between them" } ], + ], "default": "string" }, "paddingLeft": { diff --git a/src/common/option.h b/src/common/option.h index 4b8ea3eabf..713e5ba532 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -44,7 +44,13 @@ typedef enum __attribute__((__packed__)) FFModuleKeyType FF_MODULE_KEY_TYPE_NONE = 0, FF_MODULE_KEY_TYPE_STRING = 1 << 0, FF_MODULE_KEY_TYPE_ICON = 1 << 1, - FF_MODULE_KEY_TYPE_BOTH = FF_MODULE_KEY_TYPE_STRING | FF_MODULE_KEY_TYPE_ICON, + FF_MODULE_KEY_TYPE_SPACE_SHIFT = 4, + FF_MODULE_KEY_TYPE_BOTH_0 = FF_MODULE_KEY_TYPE_STRING | FF_MODULE_KEY_TYPE_ICON, + FF_MODULE_KEY_TYPE_BOTH_1 = FF_MODULE_KEY_TYPE_BOTH_0 | (1 << FF_MODULE_KEY_TYPE_SPACE_SHIFT), + FF_MODULE_KEY_TYPE_BOTH = FF_MODULE_KEY_TYPE_BOTH_1, // alias + FF_MODULE_KEY_TYPE_BOTH_2 = FF_MODULE_KEY_TYPE_BOTH_0 | (2 << FF_MODULE_KEY_TYPE_SPACE_SHIFT), + FF_MODULE_KEY_TYPE_BOTH_3 = FF_MODULE_KEY_TYPE_BOTH_0 | (3 << FF_MODULE_KEY_TYPE_SPACE_SHIFT), + FF_MODULE_KEY_TYPE_BOTH_4 = FF_MODULE_KEY_TYPE_BOTH_0 | (4 << FF_MODULE_KEY_TYPE_SPACE_SHIFT), FF_MODULE_KEY_TYPE_FORCE_UNSIGNED = UINT8_MAX, } FFModuleKeyType; diff --git a/src/common/printing.c b/src/common/printing.c index 857b06c7a2..f92677b0a3 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -28,17 +28,12 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu ffPrintColor(&instance.config.display.colorKeys); } - bool hasIcon = false; if (instance.config.display.keyType & FF_MODULE_KEY_TYPE_ICON && moduleArgs && moduleArgs->keyIcon.length > 0) - { ffStrbufWriteTo(&moduleArgs->keyIcon, stdout); - hasIcon = true; - } if (instance.config.display.keyType & FF_MODULE_KEY_TYPE_STRING) { - if(hasIcon) - putchar(' '); + ffPrintCharTimes(' ', instance.config.display.keyType >> FF_MODULE_KEY_TYPE_SPACE_SHIFT); //NULL check is required for modules with custom keys, e.g. disk with the folder path if((printType & FF_PRINT_TYPE_NO_CUSTOM_KEY) || !moduleArgs || moduleArgs->key.length == 0) @@ -136,6 +131,12 @@ void ffPrintCharTimes(char c, uint32_t times) if(times == 0) return; + if(times == 1) + { + putchar(c); + return; + } + char str[32]; memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled for(uint32_t i = sizeof(str); i <= times; i += (uint32_t)sizeof(str)) diff --git a/src/data/help.json b/src/data/help.json index 335f8563a7..745570ff20 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -566,7 +566,12 @@ "none": "Disable keys", "string": "Show string", "icon": "Show icon (requires newest nerd font)", - "both": "Show both icon and string" + "both": "Show both icon and string (alias of `both-1`)", + "both-0": "Show both icon and string with no spaces between them", + "both-1": "Show both icon and string with a space between them", + "both-2": "Show both icon and string with 2 spaces between them", + "both-3": "Show both icon and string with 3 spaces between them", + "both-4": "Show both icon and string with 4 spaces between them" }, "default": "string" } diff --git a/src/options/display.c b/src/options/display.c index ab9d4c372a..7ba790d460 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -451,6 +451,11 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va { "string", FF_MODULE_KEY_TYPE_STRING }, { "icon", FF_MODULE_KEY_TYPE_ICON }, { "both", FF_MODULE_KEY_TYPE_BOTH }, + { "both-0", FF_MODULE_KEY_TYPE_BOTH_0 }, + { "both-1", FF_MODULE_KEY_TYPE_BOTH_1 }, + { "both-2", FF_MODULE_KEY_TYPE_BOTH_2 }, + { "both-3", FF_MODULE_KEY_TYPE_BOTH_3 }, + { "both-4", FF_MODULE_KEY_TYPE_BOTH_4 }, {} }); if (error) return error; @@ -612,6 +617,11 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key { "string", FF_MODULE_KEY_TYPE_STRING }, { "icon", FF_MODULE_KEY_TYPE_ICON }, { "both", FF_MODULE_KEY_TYPE_BOTH }, + { "both-0", FF_MODULE_KEY_TYPE_BOTH_0 }, + { "both-1", FF_MODULE_KEY_TYPE_BOTH_1 }, + { "both-2", FF_MODULE_KEY_TYPE_BOTH_2 }, + { "both-3", FF_MODULE_KEY_TYPE_BOTH_3 }, + { "both-4", FF_MODULE_KEY_TYPE_BOTH_4 }, {} }); } From 98a65966e7e2aa2bab32fc56b044d9622aeaf81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 13 Oct 2025 10:19:22 +0800 Subject: [PATCH 46/61] Doc: update changelog [ci skip] --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33d59456f8..521b6522e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,12 @@ Features: * Adds basic support for Wine (Windows) * Adds basic support for hppa and sh architectures (CPU, Linux) * Improves T-Head SoC name detection from the device tree (#1997, CPU, Linux) -* `Disk.hideFolders` now supports glob patterns (Disk) +* Supports glob patterns in `Disk.hideFolders` (Disk) * For example, `/boot/*` will match both `/boot/efi` and `/boot/firmware` +* Adds brightness-level detection for external monitor support on Intel macOS (Brightness, macOS) +* Adds configurable spacing between icon and text in keys + * `display.key.type: "both-N"` where N is `0-4` + * Useful for non-monospaced Nerd Fonts Bugfixes: * Avoids integer overflow when calculating swap size (#1988, Swap, Windows) @@ -24,7 +28,7 @@ Bugfixes: * Fixes incorrect glibc dependency in polyfilled DEB packages (#1983, Linux) * Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux) * Fixes crashes on ancient Android kernels (#1993, Disk, Android) -* Prefers resolutions reported by randr mode info, fixing incorrect resolutions reported on XFCE when scaling is enabled (Display, Linux) +* Prefers resolutions reported by RandR mode info, fixing incorrect resolutions on XFCE when DPI scaling is enabled (Display, Linux) Logos: * Adds secureblue, PrismLinux, EmperorOS From 4b517263d0fea7db15bbe7aa59afdf61d0967e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 13 Oct 2025 14:27:23 +0800 Subject: [PATCH 47/61] Chore (macOS): refactors code for better resource management --- src/detection/bios/bios_apple.c | 70 +++++++++++++-------------------- src/detection/cpu/cpu_apple.c | 2 +- src/util/apple/smc_temps.c | 9 ++--- 3 files changed, 32 insertions(+), 49 deletions(-) diff --git a/src/detection/bios/bios_apple.c b/src/detection/bios/bios_apple.c index 34b7da1d47..66815464eb 100644 --- a/src/detection/bios/bios_apple.c +++ b/src/detection/bios/bios_apple.c @@ -5,69 +5,55 @@ const char* ffDetectBios(FFBiosResult* bios) { - io_registry_entry_t registryEntry; - #ifndef __aarch64__ //https://github.com/osquery/osquery/blob/master/osquery/tables/system/darwin/smbios_tables.cpp //For Intel - if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom"))) - { - CFMutableDictionaryRef properties; - if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) - { - IOObjectRelease(registryEntry); - return "IORegistryEntryCreateCFProperties(registryEntry) failed"; - } + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceRom = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom"); + if (!deviceRom) + return "IODeviceTree:/rom not found"; - ffCfDictGetString(properties, CFSTR("vendor"), &bios->vendor); - ffCfDictGetString(properties, CFSTR("version"), &bios->version); - ffCfDictGetString(properties, CFSTR("release-date"), &bios->date); - ffStrbufSetStatic(&bios->type, "UEFI"); + FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef deviceRomProps = NULL; + if(IORegistryEntryCreateCFProperties(deviceRom, &deviceRomProps, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) + return "IORegistryEntryCreateCFProperties(deviceRom) failed"; - CFRelease(properties); - IOObjectRelease(registryEntry); - return NULL; - } + ffCfDictGetString(deviceRomProps, CFSTR("vendor"), &bios->vendor); + ffCfDictGetString(deviceRomProps, CFSTR("version"), &bios->version); + ffCfDictGetString(deviceRomProps, CFSTR("release-date"), &bios->date); + ffStrbufSetStatic(&bios->type, "UEFI"); #else //For arm64 - if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/"))) - { - CFMutableDictionaryRef properties; - if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess) - { - ffCfDictGetString(properties, CFSTR("manufacturer"), &bios->vendor); - ffCfDictGetString(properties, CFSTR("time-stamp"), &bios->date); - CFRelease(properties); - } - IOObjectRelease(registryEntry); - } + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t device = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/"); + if (!device) + return "IODeviceTree:/ not found"; + + FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef deviceProps = NULL; + if(IORegistryEntryCreateCFProperties(device, &deviceProps, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) + return "IORegistryEntryCreateCFProperties(device) failed"; + + ffCfDictGetString(deviceProps, CFSTR("manufacturer"), &bios->vendor); + ffCfDictGetString(deviceProps, CFSTR("time-stamp"), &bios->date); - if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen"))) + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceChosen = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen"); + if (deviceChosen) { - CFMutableDictionaryRef properties; - if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess) + FF_CFTYPE_AUTO_RELEASE CFStringRef systemFirmWareVersion = IORegistryEntryCreateCFProperty(deviceChosen, CFSTR("system-firmware-version"), kCFAllocatorDefault, kNilOptions); + if (systemFirmWareVersion) { - ffCfDictGetString(properties, CFSTR("system-firmware-version"), &bios->version); + ffCfStrGetString(systemFirmWareVersion, &bios->version); uint32_t index = ffStrbufFirstIndexC(&bios->version, '-'); if (index != bios->version.length) { ffStrbufAppendNS(&bios->type, index, bios->version.chars); ffStrbufRemoveSubstr(&bios->version, 0, index + 1); } - else - { - ffStrbufSetStatic(&bios->type, "iBoot"); - } - CFRelease(properties); } - IOObjectRelease(registryEntry); - return NULL; } - + if (!bios->type.length) + ffStrbufSetStatic(&bios->type, "iBoot"); #endif - return "Failed to query bios info"; + return NULL; } diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 7a09d4c7b3..f1ca8845a9 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -39,7 +39,7 @@ static const char* detectFrequency(FFCPUResult* cpu) FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr")); if (!entryDevice) - return "IOServiceGetMatchingServices() failed"; + return "IOServiceGetMatchingService() failed"; if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) return "\"pmgr\" should conform to \"AppleARMIODevice\""; diff --git a/src/util/apple/smc_temps.c b/src/util/apple/smc_temps.c index 483d51e8d5..e415c7300a 100644 --- a/src/util/apple/smc_temps.c +++ b/src/util/apple/smc_temps.c @@ -1,5 +1,5 @@ -#include "fastfetch.h" #include "smc_temps.h" +#include "util/apple/cf_helpers.h" #include "util/stringUtils.h" #include @@ -137,14 +137,11 @@ static const char *smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcV static const char *smcOpen(io_connect_t *conn) { - io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC")); + FF_IOOBJECT_AUTO_RELEASE io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC")); if (!device) return "No SMC device found"; - kern_return_t result = IOServiceOpen(device, mach_task_self(), 0, conn); - IOObjectRelease(device); - - if (result != kIOReturnSuccess) + if (IOServiceOpen(device, mach_task_self(), 0, conn) != kIOReturnSuccess) return "IOServiceOpen() failed"; return NULL; From 25353261d0a7be7bbccc6bb78146af7a2c9f15dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Oct 2025 09:10:24 +0800 Subject: [PATCH 48/61] Chore (Windows): standardizes Windows header include casing. NOOP. Fixes #2006 --- src/common/processing_windows.c | 2 +- src/detection/displayserver/displayserver_windows.c | 2 +- src/detection/opengl/opengl_windows.c | 2 +- src/util/platform/FFPlatform_windows.c | 2 +- src/util/windows/wmi.hpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/processing_windows.c b/src/common/processing_windows.c index c8f28d87e3..f414ac7a19 100644 --- a/src/common/processing_windows.c +++ b/src/common/processing_windows.c @@ -2,7 +2,7 @@ #include "common/processing.h" #include "common/io/io.h" -#include +#include #include #include diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 88d1a2e007..304beaf44b 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -3,7 +3,7 @@ #include "util/edidHelper.h" #include -#include +#include #include typedef struct FFMonitorInfo diff --git a/src/detection/opengl/opengl_windows.c b/src/detection/opengl/opengl_windows.c index fe82ec14ea..8faa27dc41 100644 --- a/src/detection/opengl/opengl_windows.c +++ b/src/detection/opengl/opengl_windows.c @@ -2,7 +2,7 @@ #include "common/library.h" #include "common/printing.h" -#include +#include #include typedef struct WGLData diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index ee45f68bf8..753249df8c 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -6,7 +6,7 @@ #include "util/windows/registry.h" #include "util/windows/nt.h" -#include +#include #include #define SECURITY_WIN32 1 // For secext.h diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index f4340ae7bf..c506a8868d 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -7,7 +7,7 @@ extern "C" { } #include -#include +#include #include #include "variant.hpp" From 05108977e83806d46c7cc2d71aa61aeeb5ab012f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Oct 2025 14:44:16 +0800 Subject: [PATCH 49/61] CPU (Android): improves Android SoC vendor and model detection --- src/detection/cpu/cpu_linux.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 5ee6dcdd32..498f04896a 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -145,6 +145,7 @@ static void detectQualcomm(FFCPUResult* cpu) { // https://en.wikipedia.org/wiki/List_of_Qualcomm_Snapdragon_systems_on_chips + assert(cpu->name.length >= 2); uint32_t code = (uint32_t) strtoul(cpu->name.chars + 2, NULL, 10); const char* name = NULL; @@ -189,6 +190,7 @@ static void detectMediaTek(FFCPUResult* cpu) { // https://en.wikipedia.org/wiki/List_of_MediaTek_systems_on_chips + assert(cpu->name.length >= 2); uint32_t code = (uint32_t) strtoul(cpu->name.chars + 2, NULL, 10); const char* name = NULL; @@ -225,18 +227,26 @@ static void detectAndroid(FFCPUResult* cpu) { if (ffSettingsGetAndroidProperty("ro.soc.model", &cpu->name)) ffStrbufClear(&cpu->vendor); // We usually detect the vendor of CPU core as ARM, but instead we want the vendor of SOC - else if(ffSettingsGetAndroidProperty("ro.mediatek.platform", &cpu->name)) - ffStrbufSetStatic(&cpu->vendor, "MTK"); } if (cpu->vendor.length == 0) { if (!ffSettingsGetAndroidProperty("ro.soc.manufacturer", &cpu->vendor)) - ffSettingsGetAndroidProperty("ro.product.product.manufacturer", &cpu->vendor); + if (!ffSettingsGetAndroidProperty("ro.product.product.manufacturer", &cpu->vendor)) + if (!ffSettingsGetAndroidProperty("ro.product.vendor.manufacturer", &cpu->vendor)) + if(ffSettingsGetAndroidProperty("ro.mediatek.platform", &cpu->name)) + ffStrbufSetStatic(&cpu->vendor, "MediaTek"); } - if (ffStrbufEqualS(&cpu->vendor, "QTI") && ffStrbufStartsWithS(&cpu->name, "SM")) + if (ffStrbufEqualS(&cpu->vendor, "QTI")) + ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); + else if (ffStrbufIgnCaseEqualS(&cpu->vendor, "MediaTek")) // sometimes "Mediatek" + ffStrbufSetStatic(&cpu->vendor, "MediaTek"); + else if (cpu->vendor.length > 0) + cpu->vendor.chars[0] = (char) toupper(cpu->vendor.chars[0]); + + if (ffStrbufEqualS(&cpu->vendor, "Qualcomm") && ffStrbufStartsWithS(&cpu->name, "SM")) detectQualcomm(cpu); - else if (ffStrbufEqualS(&cpu->vendor, "MTK") && ffStrbufStartsWithS(&cpu->name, "MT")) + else if (ffStrbufEqualS(&cpu->vendor, "MediaTek") && ffStrbufStartsWithS(&cpu->name, "MT")) detectMediaTek(cpu); } #endif From 0a792e49358f2e4281a137109dd11e584ed14d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Oct 2025 14:44:49 +0800 Subject: [PATCH 50/61] CPU (Android): adds detection support for Samsung Exynos SoCs --- src/detection/cpu/cpu_linux.c | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 498f04896a..b799700cd2 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -221,6 +221,45 @@ static void detectMediaTek(FFCPUResult* cpu) } } +static void detectExynos(FFCPUResult* cpu) +{ + // https://en.wikipedia.org/wiki/Exynos + + assert(cpu->name.length > 3); + uint32_t code = (uint32_t) strtoul(cpu->name.chars + 3, NULL, 10); + const char* name = NULL; + + switch (code) + { + case 9955: name = "2500"; break; + case 9945: name = "2400"; break; + // No 2300 + case 9925: name = "2200"; break; + case 9840: name = "2100"; break; + + case 8855: name = "1580"; break; + case 8845: name = "1480"; break; + case 8835: name = "1380"; break; + case 8535: name = "1330"; break; + case 8825: name = "1280"; break; + case 9815: name = "1080"; break; + + case 9830: name = "990"; break; + case 9630: name = "980"; break; + + case 8805: name = "880"; break; + case 3830: name = "850"; break; + } + + if (name) + { + char str[32]; + ffStrCopy(str, cpu->name.chars, sizeof(str)); + ffStrbufSetF(&cpu->name, "Samsung Exynos %s [%s]", name, str); + return; + } +} + static void detectAndroid(FFCPUResult* cpu) { if (cpu->name.length == 0) @@ -248,6 +287,12 @@ static void detectAndroid(FFCPUResult* cpu) detectQualcomm(cpu); else if (ffStrbufEqualS(&cpu->vendor, "MediaTek") && ffStrbufStartsWithS(&cpu->name, "MT")) detectMediaTek(cpu); + else if (ffStrbufEqualS(&cpu->vendor, "Samsung") && ffStrbufStartsWithS(&cpu->name, "s5e")) + { + cpu->name.chars[0] = 'S'; + cpu->name.chars[2] = 'E'; + detectExynos(cpu); + } } #endif From a32404ba98246f224162138b22206d124129ee26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 Oct 2025 14:45:53 +0800 Subject: [PATCH 51/61] Doc: updates changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 521b6522e4..7496f91041 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Features: * Adds configurable spacing between icon and text in keys * `display.key.type: "both-N"` where N is `0-4` * Useful for non-monospaced Nerd Fonts +* Adds detection support for modern Samsung Exynos SoCs (CPU, Android) Bugfixes: * Avoids integer overflow when calculating swap size (#1988, Swap, Windows) @@ -29,6 +30,7 @@ Bugfixes: * Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux) * Fixes crashes on ancient Android kernels (#1993, Disk, Android) * Prefers resolutions reported by RandR mode info, fixing incorrect resolutions on XFCE when DPI scaling is enabled (Display, Linux) +* Various code cleanups and minor fixes Logos: * Adds secureblue, PrismLinux, EmperorOS From a92e4b2d674ba4803869702e2e4fc4e805006953 Mon Sep 17 00:00:00 2001 From: Dariqq <77271900+Dariqq@users.noreply.github.com> Date: Tue, 14 Oct 2025 07:19:19 +0000 Subject: [PATCH 52/61] Chore (Windows): standardize more windows header casing. Followup to 25353261d0a7be7bbccc6bb78146af7a2c9f15dc --- src/detection/wm/wm_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/wm/wm_windows.cpp b/src/detection/wm/wm_windows.cpp index 62e20a9268..5eff2d15b1 100644 --- a/src/detection/wm/wm_windows.cpp +++ b/src/detection/wm/wm_windows.cpp @@ -12,7 +12,7 @@ extern "C" #include #include #include -#include +#include template struct on_scope_exit { From 4b5e1a816bff3b586e7f6673fd6970220482add4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 Oct 2025 13:24:44 +0800 Subject: [PATCH 53/61] Display (Windows): rename VRR to DRR --- src/detection/displayserver/displayserver.c | 2 +- src/detection/displayserver/displayserver.h | 8 ++++---- .../displayserver/displayserver_windows.c | 2 +- src/modules/display/display.c | 16 ++++++++-------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 25f06c844d..5da3474014 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -45,7 +45,7 @@ FFDisplayResult* ffdsAppendDisplay( display->manufactureYear = 0; display->manufactureWeek = 0; display->serial = 0; - display->vrrStatus = FF_DISPLAY_VRR_STATUS_UNKNOWN; + display->drrStatus = FF_DISPLAY_DRR_STATUS_UNKNOWN; return display; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 1dfa1a3513..54788cfaa2 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -62,9 +62,9 @@ typedef enum __attribute__((__packed__)) FFDisplayHdrStatus typedef enum __attribute__((__packed__)) FFDisplayVrrStatus { - FF_DISPLAY_VRR_STATUS_UNKNOWN, - FF_DISPLAY_VRR_STATUS_DISABLED, - FF_DISPLAY_VRR_STATUS_ENABLED, + FF_DISPLAY_DRR_STATUS_UNKNOWN, + FF_DISPLAY_DRR_STATUS_DISABLED, + FF_DISPLAY_DRR_STATUS_ENABLED, } FFDisplayVrrStatus; typedef struct FFDisplayResult @@ -90,7 +90,7 @@ typedef struct FFDisplayResult uint16_t manufactureYear; uint16_t manufactureWeek; uint32_t serial; - FFDisplayVrrStatus vrrStatus; + FFDisplayVrrStatus drrStatus; } FFDisplayResult; typedef struct FFDisplayServerResult diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 304beaf44b..c5917f8571 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -229,7 +229,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } if (edidLength > 0) ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - display->vrrStatus = path->flags & DISPLAYCONFIG_PATH_BOOST_REFRESH_RATE ? FF_DISPLAY_VRR_STATUS_ENABLED : FF_DISPLAY_VRR_STATUS_DISABLED; + display->drrStatus = path->flags & DISPLAYCONFIG_PATH_BOOST_REFRESH_RATE ? FF_DISPLAY_DRR_STATUS_ENABLED : FF_DISPLAY_DRR_STATUS_DISABLED; } } } diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 2d3a87ce60..26f7430de9 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -348,18 +348,18 @@ bool ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_uint(doc, output, "height", item->height); yyjson_mut_obj_add_real(doc, output, "refreshRate", item->refreshRate); - if (item->vrrStatus == FF_DISPLAY_VRR_STATUS_UNKNOWN) - yyjson_mut_obj_add_null(doc, output, "vrrStatus"); - else switch (item->vrrStatus) + if (item->drrStatus == FF_DISPLAY_DRR_STATUS_UNKNOWN) + yyjson_mut_obj_add_null(doc, output, "drrStatus"); + else switch (item->drrStatus) { - case FF_DISPLAY_VRR_STATUS_DISABLED: - yyjson_mut_obj_add_str(doc, output, "vrrStatus", "Disabled"); + case FF_DISPLAY_DRR_STATUS_DISABLED: + yyjson_mut_obj_add_str(doc, output, "drrStatus", "Disabled"); break; - case FF_DISPLAY_VRR_STATUS_ENABLED: - yyjson_mut_obj_add_str(doc, output, "vrrStatus", "Enabled"); + case FF_DISPLAY_DRR_STATUS_ENABLED: + yyjson_mut_obj_add_str(doc, output, "drrStatus", "Enabled"); break; default: - yyjson_mut_obj_add_str(doc, output, "vrrStatus", "Unknown"); + yyjson_mut_obj_add_str(doc, output, "drrStatus", "Unknown"); break; } From 2eba761bedd0baf5a71fe3c869cc75323dd60fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 Oct 2025 14:33:53 +0800 Subject: [PATCH 54/61] IO (OpenBSD): fixes incorrect glob usage --- CHANGELOG.md | 1 + CMakeLists.txt | 5 +---- src/common/io/io_unix.c | 27 ++++++++++++++++----------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7496f91041..6abea1276d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Bugfixes: * Fixes incorrect glibc dependency in polyfilled DEB packages (#1983, Linux) * Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux) * Fixes crashes on ancient Android kernels (#1993, Disk, Android) +* Fixes incorrect usage of `glob(3)` (OpenBSD) * Prefers resolutions reported by RandR mode info, fixing incorrect resolutions on XFCE when DPI scaling is enabled (Display, Linux) * Various code cleanups and minor fixes diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c4071ea06..4e980fd1e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1743,6 +1743,7 @@ elseif(ANDROID) target_link_libraries(libfastfetch PRIVATE "m" ) + # https://github.com/termux/termux-packages/pull/7056 CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC) if(HAVE_LIBANDROID_WORDEXP_STATIC) target_link_libraries(libfastfetch @@ -1819,10 +1820,6 @@ if(NOT WIN32) if(HAVE_WORDEXP) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1) endif() - CHECK_INCLUDE_FILE("glob.h" HAVE_GLOB) - if(HAVE_GLOB) - target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLOB=1) - endif() if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT) CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP) if(HAVE_PTHREAD_NP) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 90560f3f64..cd4f3fae52 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -15,11 +15,9 @@ #if FF_HAVE_WORDEXP #include -#elif FF_HAVE_GLOB - #warning " is not available, use instead" - #include #else - #warning "Neither nor is available" + #warning " is not available, use glob(3) instead" + #include #endif static void createSubfolders(const char* fileName) @@ -136,14 +134,14 @@ bool ffAppendFileBufferRelative(int dfd, const char* fileName, FFstrbuf* buffer) return ffAppendFDBuffer(fd, buffer); } -bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* out) +bool ffPathExpandEnv(const char* in, FFstrbuf* out) { bool result = false; - #if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056 + #if FF_HAVE_WORDEXP wordexp_t exp; - if (wordexp(in, &exp, 0) != 0) + if (wordexp(in, &exp, 0) != 0) // WARN: 0 = no safety flags; command substitution allowed return false; if (exp.we_wordc >= 1) @@ -154,16 +152,23 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o wordfree(&exp); - #elif FF_HAVE_GLOB + #else glob_t gb; - if (glob(in, GLOB_NOSORT | GLOB_TILDE, NULL, &gb) != 0) + if (glob(in, GLOB_NOSORT + #ifdef GLOB_TILDE + | GLOB_TILDE + #endif + #ifdef GLOB_BRACE + | GLOB_BRACE + #endif + , NULL, &gb) != 0) return false; - if (gb.gl_matchc >= 1) + if (gb.gl_pathc >= 1) { result = true; - ffStrbufSetS(out, gb.gl_pathv[gb.gl_matchc > 1 ? ffTimeGetNow() % gb.gl_matchc : 0]); + ffStrbufSetS(out, gb.gl_pathv[gb.gl_pathc > 1 ? ffTimeGetNow() % (unsigned) gb.gl_pathc : 0]); } globfree(&gb); From 71a2cb4e1bb85707dc2d24dd118bf5f5425d7972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 Oct 2025 14:34:51 +0800 Subject: [PATCH 55/61] Doc: adds security warning for Command module in README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 42132af4e8..8f9ab82c5d 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,10 @@ Fastfetch uses JSONC (JSON with comments) for configuration. [See the Wiki for d Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information. +### WARNING + +Fastfetch supports a `Command` module that can run arbitrary shell commands. If you copy-paste a config file from an untrusted source, it may contain malicious commands that can harm your system or compromise your privacy. Please always review the config file before using it. + ## FAQ ### Q: Neofetch is good enough. Why do I need fastfetch? From be0756f8babfa48779a591a1c63dc0da8300d841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 Oct 2025 15:29:24 +0800 Subject: [PATCH 56/61] CMake: adds a new build option to gate wordexp usage and detection --- CHANGELOG.md | 3 +++ CMakeLists.txt | 31 ++++++++++++++++++------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6abea1276d..08826cd971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ Features: * `display.key.type: "both-N"` where N is `0-4` * Useful for non-monospaced Nerd Fonts * Adds detection support for modern Samsung Exynos SoCs (CPU, Android) +* Adds a new CMake option `-DENABLE_WORDEXP=` to enable or disable using `wordexp(3)` for acquiring logo file paths (`logo.source`) + * Enabled by default for compatibility + * Disabling this option reverts to using `glob(3)`, which is less functional but more secure Bugfixes: * Avoids integer overflow when calculating swap size (#1988, Swap, Windows) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e980fd1e6..d7622c0a25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON) option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF) option(ENABLE_EMBEDDED_AMDGPUIDS "Embed amdgpu.ids into fastfetch, requires `python`" OFF) +option(ENABLE_WORDEXP "Enable using of wordexp(3) if available, instead of glob(3)" ON) set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static) set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch") @@ -1743,18 +1744,20 @@ elseif(ANDROID) target_link_libraries(libfastfetch PRIVATE "m" ) - # https://github.com/termux/termux-packages/pull/7056 - CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC) - if(HAVE_LIBANDROID_WORDEXP_STATIC) - target_link_libraries(libfastfetch - PRIVATE -l:libandroid-wordexp.a - ) - else() - CHECK_LIBRARY_EXISTS(android-wordexp wordexp "" HAVE_LIBANDROID_WORDEXP) - if(HAVE_LIBANDROID_WORDEXP) + if(ENABLE_WORDEXP) + # https://github.com/termux/termux-packages/pull/7056 + CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC) + if(HAVE_LIBANDROID_WORDEXP_STATIC) target_link_libraries(libfastfetch - PRIVATE android-wordexp + PRIVATE -l:libandroid-wordexp.a ) + else() + CHECK_LIBRARY_EXISTS(android-wordexp wordexp "" HAVE_LIBANDROID_WORDEXP) + if(HAVE_LIBANDROID_WORDEXP) + target_link_libraries(libfastfetch + PRIVATE android-wordexp + ) + endif() endif() endif() elseif(Haiku) @@ -1816,9 +1819,11 @@ if(NOT WIN32) if(HAVE_UTMPX) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX=1) endif() - CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP) - if(HAVE_WORDEXP) - target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1) + if(ENABLE_WORDEXP) + CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP) + if(HAVE_WORDEXP) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1) + endif() endif() if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT) CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP) From 51bc6d421ad44e67549d169554015afe9d16b558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 Oct 2025 00:27:06 +0800 Subject: [PATCH 57/61] CI (Windows): switches CI to use the release signing policy on the master branch --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e879816c9f..90cf569b75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -725,7 +725,7 @@ jobs: api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' organization-id: '${{ vars.SIGNPATH_ORG_ID }}' project-slug: 'fastfetch' - signing-policy-slug: 'test-signing' + signing-policy-slug: ${{ github.ref == 'refs/heads/master' && 'release-signing' || 'test-signing' }} github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}' wait-for-completion: true output-artifact-directory: '.' diff --git a/CHANGELOG.md b/CHANGELOG.md index 08826cd971..718e0a5442 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # 2.54.0 +Windows binaries in Release page are now signed using SignPath. + Changes: * Moves macOS and Windows design language detection from the DE module to the Theme module From 70377a8afd195ab97b116fe7eab5d5f2491ef751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 Oct 2025 00:29:33 +0800 Subject: [PATCH 58/61] Release: v2.54.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7622c0a25..930dd540d0 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.53.0 + VERSION 2.54.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From 554e7bce4a726ff64985a824d17b4f7279f8b0aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 Oct 2025 00:56:14 +0800 Subject: [PATCH 59/61] Logo (Builtin): adds Zraxyl Fixes #1860 --- CHANGELOG.md | 2 +- src/logo/ascii/zraxyl.txt | 10 ++++++++++ src/logo/builtin.c | 10 ++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/logo/ascii/zraxyl.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 718e0a5442..ed64b20c3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ Bugfixes: * Various code cleanups and minor fixes Logos: -* Adds secureblue, PrismLinux, EmperorOS +* Adds secureblue, PrismLinux, EmperorOS and Zraxyl * Updates T2 # 2.53.0 diff --git a/src/logo/ascii/zraxyl.txt b/src/logo/ascii/zraxyl.txt new file mode 100644 index 0000000000..ee30979079 --- /dev/null +++ b/src/logo/ascii/zraxyl.txt @@ -0,0 +1,10 @@ + __________ + / __________ \ + / / \ \ + / / .-"````"-. \ \ +| | |/ \| | | +| | Z R A X Y L | | +| | \ ¯¯¯¯¯¯¯¯¯¯¯¯ / | | + \ \ `-.___..___.-' / / + '.'._ _.' .' + '-.| M - C | .-' \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 575ffa6a13..0fe3b03245 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -5489,6 +5489,16 @@ static const FFlogo Z[] = { FF_COLOR_FG_BLUE, }, }, + // Zraxyl + { + .names = {"Zraxyl" }, + .lines = FASTFETCH_DATATEXT_LOGO_ZRAXYL, + .colors = { + FF_COLOR_FG_BLUE, + }, + .colorKeys = FF_COLOR_FG_BLUE, + .colorTitle = FF_COLOR_FG_BLUE, + }, // LAST {}, }; From 96c7c2966dddb1bdadac8046416b64255e0abb41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 Oct 2025 01:11:03 +0800 Subject: [PATCH 60/61] =?UTF-8?q?Brightness=20(macOS):=20prioritizes=20DDC?= =?UTF-8?q?/CI=20reply=20over=20simple=20I=C2=B2C=20transaction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detection/brightness/brightness_apple.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index 7d91e8ebf0..3b5116e58d 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -140,15 +140,11 @@ static IOOptionBits getSupportedTransactionType(void) { int64_t types = 0; ffCfNumGetInt64(IOI2CTransactionTypes, &types); - /* - We want DDCciReply but Simple is better than No-thing. - Combined and DisplayPortNative are not useful in our case. - */ if (types) { - if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types) - return kIOI2CSimpleTransactionType; if ((1 << kIOI2CDDCciReplyTransactionType) & (uint64_t) types) return kIOI2CDDCciReplyTransactionType; + if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types) + return kIOI2CSimpleTransactionType; if ((1 << kIOI2CCombinedTransactionType) & (uint64_t) types) return kIOI2CCombinedTransactionType; if ((1 << kIOI2CDisplayPortNativeTransactionType) & (uint64_t) types) From f0759acd118a746433c8565239e90a55ccaff825 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 Oct 2025 09:35:34 +0800 Subject: [PATCH 61/61] Brightness (macOS): tidy --- src/detection/brightness/brightness_apple.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index 3b5116e58d..a6a77b2af3 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -123,11 +123,12 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* return NULL; } #else -static IOOptionBits getSupportedTransactionType(void) { +static IOOptionBits getSupportedTransactionType(void) +{ FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL; if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("IOFramebufferI2CInterface"), &iterator) != KERN_SUCCESS) - return 0; + return kIOI2CNoTransactionType; io_registry_entry_t registryEntry; while ((registryEntry = IOIteratorNext(iterator)) != MACH_PORT_NULL) @@ -145,22 +146,20 @@ static IOOptionBits getSupportedTransactionType(void) { return kIOI2CDDCciReplyTransactionType; if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types) return kIOI2CSimpleTransactionType; - if ((1 << kIOI2CCombinedTransactionType) & (uint64_t) types) - return kIOI2CCombinedTransactionType; - if ((1 << kIOI2CDisplayPortNativeTransactionType) & (uint64_t) types) - return kIOI2CDisplayPortNativeTransactionType; } } break; } - return 0; + return kIOI2CNoTransactionType; } static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result) { if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available"; IOOptionBits transactionType = getSupportedTransactionType(); + if (transactionType == kIOI2CNoTransactionType) + return "No supported IOI2C transaction type found"; FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) {