mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
276 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a9f43ff466 | |||
| 924d78d3c4 | |||
| fa92bb84ae | |||
| 288d25e17c | |||
| 610fc2ea36 | |||
| 716c0e2b5c | |||
| 945aed7160 | |||
| 1d4d68f6e0 | |||
| 3e1167260d | |||
| 0130f610e9 | |||
| 94941daf4f | |||
| 2bbd723321 | |||
| 608382109c | |||
| bdc5174f68 | |||
| bc869f1be9 | |||
| dc69e44829 | |||
| d236850119 | |||
| 60ec8c9097 | |||
| 42e7a7d2f7 | |||
| e766809e3a | |||
| cb1f0300b9 | |||
| f2a29309f3 | |||
| 6e7b4bab75 | |||
| b4f39e251c | |||
| af6196fe6e | |||
| bca56b2049 | |||
| f4401f172e | |||
| c11b88fee5 | |||
| 88b1b558d7 | |||
| ba6cdc77c9 | |||
| b952772902 | |||
| 7a322154fa | |||
| 0b6ca158ea | |||
| 100cd9a72b | |||
| 98fb810f1f | |||
| c613e558fd | |||
| c324f83826 | |||
| e50421a6ce | |||
| 417b944e1c | |||
| cb8b4b335d | |||
| c0160537b0 | |||
| 4cb7a6424a | |||
| 7d6c79d73e | |||
| 8652737f64 | |||
| d6ac89ea8d | |||
| 2b620cf487 | |||
| f644df481c | |||
| e99ecacb52 | |||
| 3e22dd4b0e | |||
| 19f30ec687 | |||
| 76bee78200 | |||
| ce7455d8f0 | |||
| 5e27ee0f57 | |||
| 84a5c6ebe8 | |||
| ad7e23f64c | |||
| 2738f20eea | |||
| 09362b236c | |||
| 3cfef81877 | |||
| 3a04ae2542 | |||
| dbaf8a319d | |||
| 2fe2a21bfe | |||
| 37639c3582 | |||
| 9a74e6d7bc | |||
| 5d13389827 | |||
| 1c2c6644d5 | |||
| ffcddf30e3 | |||
| 22c92c7b05 | |||
| b569048010 | |||
| f703d9ac89 | |||
| ed6abfd626 | |||
| 50388efc78 | |||
| 7e8fb0fa14 | |||
| 9d70469665 | |||
| a94f0efb5b | |||
| da3a9be7c6 | |||
| cd8ab8e55a | |||
| 1b5b32afad | |||
| 917f784438 | |||
| c2d5d5cca1 | |||
| b435738c34 | |||
| 934905e63a | |||
| d15bb8a232 | |||
| c22bca1f87 | |||
| e04cc9c9d5 | |||
| 7a2bf4e0ac | |||
| 662f5127fa | |||
| fb9117553b | |||
| 9f24e4363f | |||
| 084f9294f2 | |||
| a9f1f9a647 | |||
| 0aed89036b | |||
| df15bbc5f2 | |||
| e6b0bd3817 | |||
| 11cd7153a2 | |||
| f8bc1cb605 | |||
| 8b8eb6f290 | |||
| 056fe21ee2 | |||
| cb0a88df22 | |||
| 298c0431c3 | |||
| 448de9afa5 | |||
| 9401a4b9ad | |||
| ea92ad3785 | |||
| 7aaad5e03e | |||
| 645bf5c839 | |||
| 7638e0e4a1 | |||
| 302b8a7b1b | |||
| dbb9d8a660 | |||
| c51a164042 | |||
| 6b8a62da6e | |||
| 578ca23e75 | |||
| 2e73a90835 | |||
| cc6273fecc | |||
| e63b777916 | |||
| 907567f511 | |||
| e0fd7308be | |||
| b761034aae | |||
| 04d6b1453d | |||
| 11d1754686 | |||
| 25e84decff | |||
| 7d665b203f | |||
| ac62442798 | |||
| 758f96de60 | |||
| db623b9c86 | |||
| c353bf3c96 | |||
| 338b552499 | |||
| 5d73cc1232 | |||
| faddef7a3b | |||
| 2d9bbc8049 | |||
| 64afaa07e7 | |||
| 5cf3ab23b0 | |||
| 3fe926d3a0 | |||
| f71bb682de | |||
| 904f860f3c | |||
| 8f15c9604c | |||
| ff28f5807b | |||
| 6a317366d7 | |||
| dc3e4a2d18 | |||
| 46c4a71ba3 | |||
| f0759acd11 | |||
| 96c7c2966d | |||
| 554e7bce4a | |||
| 70377a8afd | |||
| 51bc6d421a | |||
| be0756f8ba | |||
| 71a2cb4e1b | |||
| 2eba761bed | |||
| 4b5e1a816b | |||
| a92e4b2d67 | |||
| a32404ba98 | |||
| 0a792e4935 | |||
| 05108977e8 | |||
| 25353261d0 | |||
| 4b517263d0 | |||
| 98a65966e7 | |||
| 32dcf9487f | |||
| e3a698f7b1 | |||
| 1631f74700 | |||
| 78c6d71049 | |||
| 0b9ecdeade | |||
| 185a9211f1 | |||
| 24459b2fbf | |||
| 88c8dcb3e8 | |||
| f3a8fedf0a | |||
| 6b8b7c1a62 | |||
| af26828f91 | |||
| f4c43abbf7 | |||
| e84739bff0 | |||
| 66aad0e4f1 | |||
| 77c43c0214 | |||
| 31ae7a642a | |||
| 1bbb21486c | |||
| 316d8ddf9b | |||
| 5d8c21a5ca | |||
| 240ba5c00c | |||
| 554184ec72 | |||
| 7a055a2254 | |||
| 0a807ac1a3 | |||
| 4d831c8c73 | |||
| e6e78a7aae | |||
| 09bef5f41d | |||
| e394efdd85 | |||
| c10b652a2e | |||
| 1594a69d6c | |||
| 9b1e318bd1 | |||
| e292bf1dee | |||
| 55a0c6e97d | |||
| 8b8e4a40a4 | |||
| 8be070998f | |||
| 093f56a03d | |||
| bd9744c27c | |||
| adc25f4420 | |||
| 229fe7c7bf | |||
| 5d571752ae | |||
| 512ddfae6b | |||
| 7b689f94df | |||
| 9eed149b09 | |||
| 0f5d321df8 | |||
| 4e84094fd8 | |||
| 7b9fce0189 | |||
| 9ab5c33008 | |||
| 613b1d63f1 | |||
| 8c86cafec7 | |||
| 4098cf51b3 | |||
| bfc23232f8 | |||
| 483fba44dc | |||
| 851751f99d | |||
| 3e86130ddd | |||
| 350ffced13 | |||
| cdcdb78b97 | |||
| 2ae9d01200 | |||
| e95393750b | |||
| de9229697a | |||
| 9d23d28594 | |||
| 57a4b9b6ed | |||
| ef3989d18d | |||
| 3079b44f63 | |||
| 403900639c | |||
| 0bb5b4cc9c | |||
| 1180eb55a4 | |||
| f0e9caaf04 | |||
| 2c22c3b0c0 | |||
| e9065e15e8 | |||
| 9e7816069b | |||
| 82cdc4cd91 | |||
| 822ddc6dc6 | |||
| 8bd171a9ff | |||
| 509d6bf30c | |||
| ab8a13b2d3 | |||
| 3bcdcc5dbf | |||
| 38f4215a94 | |||
| e3eec3f62a | |||
| e025f28cdc | |||
| 3ece4e3b4d | |||
| 6d72a32d1d | |||
| 45be29bad3 | |||
| 6f5e618341 | |||
| 1abfa70237 | |||
| baaeef5ab5 | |||
| 8eafec479e | |||
| 5f9e7c799a | |||
| aeb1722eb9 | |||
| de18a07938 | |||
| 88147f80ac | |||
| 505ff6ff65 | |||
| 390549394d | |||
| f7e7d54c16 | |||
| 5e068d22c8 | |||
| b77646f23e | |||
| aa40366a49 | |||
| a64a82f215 | |||
| 0a4d6220e9 | |||
| 6b037c595f | |||
| f628f5c382 | |||
| cf713e32e1 | |||
| 7d08f81075 | |||
| 8822653335 | |||
| 75ff054255 | |||
| c51cc8ce6b | |||
| 44e23412b5 | |||
| 59742bca00 | |||
| 303edb97ce | |||
| 37ab380a6f | |||
| a06e245c34 | |||
| 5de432b083 | |||
| 817285ac01 | |||
| 8687505505 | |||
| 34c34d25c4 | |||
| 21b15ee944 | |||
| 8e0a65126e | |||
| 54d8b0a95d | |||
| 48fc72e95c | |||
| e3d6a85888 | |||
| 7d92da8829 | |||
| 2f3a361b1f | |||
| ac71f21e6c | |||
| 8d5316f6aa |
@@ -0,0 +1,3 @@
|
||||
github: LinusDierheimer
|
||||
ko_fi: carterli
|
||||
custom: https://paypal.me/zhangsongcui
|
||||
@@ -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
|
||||
|
||||
+152
-252
@@ -38,7 +38,7 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -61,12 +61,19 @@ jobs:
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
linux-amd64:
|
||||
name: Linux-amd64
|
||||
runs-on: ubuntu-22.04
|
||||
linux-hosts:
|
||||
name: Linux-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runs-on: ubuntu-22.04
|
||||
- arch: aarch64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
outputs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
@@ -82,26 +89,31 @@ 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 libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev directx-headers-dev
|
||||
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: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -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
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
@@ -126,15 +138,27 @@ jobs:
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: polyfill glibc
|
||||
run: |
|
||||
wget https://github.com/CarterLi/polyfill-glibc/releases/download/v0.0.1/polyfill-glibc-${{ matrix.arch }} -O polyfill-glibc
|
||||
chmod +x polyfill-glibc
|
||||
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
|
||||
echo 'set(CPACK_RPM_SPEC_MORE_DEFINE "%global __os_install_post %{nil}")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-amd64
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-aarch64:
|
||||
name: Linux-aarch64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
linux-i686:
|
||||
name: Linux-i686
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -151,20 +175,29 @@ 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 libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev libchafa-dev libddcutil-dev rpm
|
||||
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: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
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 -DCPACK_DEBIAN_PACKAGE_ARCHITECTURE=i386 -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: check deb package
|
||||
run: dpkg -I fastfetch-*.deb
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
@@ -183,14 +216,10 @@ jobs:
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-aarch64
|
||||
name: fastfetch-linux-i686
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv7l:
|
||||
@@ -212,12 +241,13 @@ jobs:
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
|
||||
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
|
||||
dpkg -i *.deb
|
||||
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
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 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
|
||||
@@ -252,8 +282,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 libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-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
|
||||
@@ -268,12 +298,18 @@ jobs:
|
||||
name: fastfetch-linux-armv6l
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-riscv64:
|
||||
name: Linux-riscv64
|
||||
runs-on: ubuntu-24.04
|
||||
linux-vms:
|
||||
name: Linux-${{ matrix.arch }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: riscv64
|
||||
- arch: ppc64le
|
||||
- arch: s390x
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
@@ -282,13 +318,15 @@ jobs:
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: riscv64
|
||||
arch: ${{ matrix.arch }}
|
||||
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 libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-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
|
||||
@@ -300,77 +338,7 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-riscv64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-ppc64le:
|
||||
name: Linux-ppc64le
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: ppc64le
|
||||
distro: ubuntu20.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 libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-ppc64le
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-s390x:
|
||||
name: Linux-s390x
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: s390x
|
||||
distro: ubuntu20.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 libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-s390x
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-amd64:
|
||||
@@ -386,7 +354,7 @@ jobs:
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
@@ -411,12 +379,19 @@ jobs:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-amd64:
|
||||
name: macOS-amd64
|
||||
runs-on: macos-13
|
||||
macos-hosts:
|
||||
name: macOS-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runs-on: macos-15-intel
|
||||
- arch: aarch64
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
@@ -455,54 +430,7 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-aarch64:
|
||||
name: macOS-aarch64
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- 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: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-aarch64
|
||||
name: fastfetch-macos-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
sunos-amd64:
|
||||
@@ -518,7 +446,6 @@ jobs:
|
||||
usesh: true
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg install pkg:/package/pkg
|
||||
pkg update --accept
|
||||
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick
|
||||
|
||||
@@ -560,7 +487,7 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa
|
||||
sudo 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
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -596,8 +523,9 @@ jobs:
|
||||
version: '7.7'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
sudo pkg_add -u
|
||||
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
|
||||
@@ -632,8 +560,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
|
||||
@@ -665,10 +593,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 xfce4-conf 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
|
||||
@@ -718,12 +646,25 @@ jobs:
|
||||
name: fastfetch-haiku-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
windows-hosts:
|
||||
name: Windows-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runs-on: windows-latest
|
||||
msystem: CLANG64
|
||||
msystem-lower: clang64
|
||||
msys-arch: x86_64
|
||||
- arch: aarch64
|
||||
runs-on: windows-11-arm
|
||||
msystem: CLANGARM64
|
||||
msystem-lower: clangarm64
|
||||
msys-arch: aarch64
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
@@ -734,21 +675,21 @@ jobs:
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANG64
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-opencl-headers mingw-w64-clang-x86_64-cppwinrt mingw-w64-clang-x86_64-imagemagick
|
||||
install: git mingw-w64-clang-${{ matrix.msys-arch }}-7zip mingw-w64-clang-${{ matrix.msys-arch }}-cmake mingw-w64-clang-${{ matrix.msys-arch }}-clang mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-loader mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-headers mingw-w64-clang-${{ matrix.msys-arch }}-opencl-icd mingw-w64-clang-${{ matrix.msys-arch }}-opencl-headers mingw-w64-clang-${{ matrix.msys-arch }}-cppwinrt mingw-w64-clang-${{ matrix.msys-arch }}-imagemagick mingw-w64-clang-${{ matrix.msys-arch }}-chafa
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
run: env PKG_CONFIG_PATH=/${{ matrix.msystem-lower }}/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
|
||||
run: cp /${{ matrix.msystem-lower }}/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -768,102 +709,61 @@ jobs:
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
- 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-amd64
|
||||
path: ./fastfetch-windows-amd64.*
|
||||
name: fastfetch-windows-${{ matrix.arch }}
|
||||
path: |
|
||||
*.dll
|
||||
fastfetch.exe
|
||||
flashfetch.exe
|
||||
|
||||
windows-aarch64:
|
||||
name: Windows-aarch64
|
||||
runs-on: windows-11-arm
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: submit signing request
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
msystem: CLANGARM64
|
||||
update: true
|
||||
install: git mingw-w64-clang-aarch64-7zip mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-vulkan-loader mingw-w64-clang-aarch64-vulkan-headers mingw-w64-clang-aarch64-opencl-icd mingw-w64-clang-aarch64-opencl-headers mingw-w64-clang-aarch64-cppwinrt mingw-w64-clang-aarch64-imagemagick
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clangarm64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clangarm64/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- 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
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
|
||||
project-slug: 'fastfetch'
|
||||
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: '.'
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-aarch64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
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-aarch64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
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-aarch64
|
||||
path: ./fastfetch-windows-aarch64.*
|
||||
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'
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- linux-hosts
|
||||
- linux-i686
|
||||
- linux-armv7l
|
||||
- linux-armv6l
|
||||
- linux-riscv64
|
||||
- linux-ppc64le
|
||||
- linux-s390x
|
||||
- linux-vms
|
||||
- musl-amd64
|
||||
- macos-amd64
|
||||
- macos-aarch64
|
||||
- macos-hosts
|
||||
- freebsd-amd64
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- dragonfly-amd64
|
||||
- sunos-amd64
|
||||
- haiku-amd64
|
||||
- windows-amd64
|
||||
- windows-aarch64
|
||||
- windows-hosts
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -874,29 +774,29 @@ jobs:
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: download artifacts
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@v4
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@v5
|
||||
|
||||
- name: create release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-hosts.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-*/fastfetch-*
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-hosts.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
|
||||
- name: download source tarballs
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-amd64.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-hosts.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
ls fastfetch-*/*
|
||||
|
||||
- name: generate release notes
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-hosts.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
@@ -905,10 +805,10 @@ jobs:
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
|
||||
- name: update release body
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-hosts.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
bodyFile: fastfetch-release-notes.md
|
||||
allowUpdates: true
|
||||
|
||||
+215
@@ -1,3 +1,218 @@
|
||||
# 2.56.1
|
||||
|
||||
Features:
|
||||
* Improves compatibility with KDE Plasma 6.5 (#2093, Display)
|
||||
* Adds a `tempSensor` option to specify the sensor name used for CPU temperature detection (CPU)
|
||||
* Example: `{ "type": "cpu", "tempSensor": "hwmon0" /* Use /sys/class/hwmon/hwmon0 for temperature detection */ }`
|
||||
* Refines Memory usage detection on macOS to match Activity Monitor more closely (Memory, macOS)
|
||||
* Minor optimizations
|
||||
|
||||
Bugfixes:
|
||||
* Fixes cache line size detection (CPU, macOS)
|
||||
|
||||
Logos:
|
||||
* Removes Opak
|
||||
* Updates GXDE
|
||||
|
||||
# 2.56.0
|
||||
|
||||
Features:
|
||||
* Enhances config file loading. `--config` and `-c` with relative path now also searches paths defined in `fastfetch --list-config-paths` (typically `~/.config/fastfetch/`)
|
||||
* This allows users to use `fastfetch -c my-config` without needing to specify the full path.
|
||||
* Adds NUMA node count detection (CPU)
|
||||
* Exposed via `{numa-nodes}` in custom format
|
||||
* Supported on Linux, FreeBSD and Windows
|
||||
* Supports the newest Alacritty config format (#2070, TerminalFont)
|
||||
* Detects driver specific info for Zhaoxin GPUs (GPU, Linux)
|
||||
* Detects Android OEM UI for certain OSes (DE, Android)
|
||||
* Improves users detection on Linux (#2064, Users, Linux)
|
||||
* Adds systemd fallback when utmp is unavailable
|
||||
* Fixes resource leaks
|
||||
* Always reports the newest session info
|
||||
* Adds kiss package manager support (#2072, Packages, Linux)
|
||||
* Reports `sshd` if `$SSH_TTY` is not available (Terminal)
|
||||
* Zpool module rewrite (#2051, Zpool)
|
||||
* Adds new Zpool properties: allocated, guid, readOnly
|
||||
* Zpool module now uses runtime lookup for properties to ensure portability
|
||||
* Adds NetBSD (requires `sudo`) and macOS support
|
||||
* Adds `splitLines` option for Command module, which splits the output into sub modules, each containing one line of the output (Command)
|
||||
```
|
||||
* Command output:
|
||||
Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* Old behavior:
|
||||
Command: Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* With `"splitLines": true`:
|
||||
Command 1: Line 1
|
||||
Command 2: Line 2
|
||||
Command 3: Line 3
|
||||
```
|
||||
|
||||
Bugfixes:
|
||||
* Fixes {m,o}ksh version detection on Linux (Shell)
|
||||
* Fixes Alacritty config parsing for TOML format (#2070, TerminalFont)
|
||||
* Improves builtin logo printing for piping and buffering (#2065, Logo)
|
||||
* Uses absolute path when detecting shell and terminal version if available (#2067, TerminalShell)
|
||||
|
||||
Logos:
|
||||
* Updates Codex Linux logo (#2071)
|
||||
* Adds OS/2 Warp logo (#2062)
|
||||
* Adds Amiga logo (#2061)
|
||||
|
||||
# 2.55.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix parallel command execution breaks randomly (#2056 / #2058, Command)
|
||||
* Regression from v2.55.0
|
||||
* Fix `dylib` searching path on macOS (macOS)
|
||||
* Regression from v2.55.0
|
||||
* Fix an uninitialized field (#2057, Display)
|
||||
|
||||
# 2.55.0
|
||||
|
||||
Changes:
|
||||
* Commands are now executed in parallel by default to improve performance (#2045, Command)
|
||||
* This behavior can be disabled in the config file with `"parallel": false` if it causes problems with certain scripts
|
||||
* Folder/filesystem hiding is moved to the detection stage; hidden entries are no longer probed, improving performance (#2043, Disk)
|
||||
|
||||
Features:
|
||||
* Adds `command.parallel` and `command.useStdErr` config options (Command)
|
||||
* `parallel`: set to `false` to disable parallel execution (see Changes above)
|
||||
* `useStdErr`: set to `true` to use stderr output instead of stdout
|
||||
* Adds the command-line flag `--dynamic-interval <interval-in-ms>` to enable dynamic output auto-refresh (#2041)
|
||||
* Due to internal limitations, some modules do not support dynamic updates (notably Display and Media)
|
||||
* Adds support for using the current playing media's cover art as a logo source (Media / Logo)
|
||||
* Usage: `"logo": { "type": "<image-protocol>", "source": "media-cover" }` in JSON config; or `--<image-protocol> media-cover` in command line
|
||||
* Supports local sources only
|
||||
* Adds native GPU detection support on OpenBSD and NetBSD (instead of depending on `libpciaccess`) (GPU)
|
||||
* No functional changes
|
||||
* Root privileges are required to access PCI config space on OpenBSD (as always)
|
||||
* Adds GPU detection support on GNU/Hurd (GPU)
|
||||
* Requires building with `libpciaccess`
|
||||
* Shows Debian point release on Raspberry Pi OS (#2032, OS, Linux)
|
||||
* Adds `Brush` shell version detection (Shell)
|
||||
* Improves Mac family detection via prefix matching (Host)
|
||||
|
||||
Bugfixes:
|
||||
* Ignores `run-parts` during terminal/shell detection (#2048, Terminal / Shell, Linux)
|
||||
* Fixes fish version detection when `LC_ALL` is set (#2014, Shell, Linux)
|
||||
* Hides the module when no desktop icons are found (#2023, Icons, Windows)
|
||||
* Skips auxiliary display controllers to prevent the module from reporting duplicate entries (#2034, GPU, Linux)
|
||||
* Refines Apple rpath handling; fixes building for the Homebrew version on macOS (#1998, CMake)
|
||||
|
||||
Logos:
|
||||
* Adds Vincent OS and MacaroniOS
|
||||
|
||||
# 2.54.0
|
||||
|
||||
Windows binaries in Release page are now signed by SignPath.
|
||||
|
||||
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)
|
||||
* 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
|
||||
* Adds detection support for modern Samsung Exynos SoCs (CPU, Android)
|
||||
* Adds a new CMake option `-DENABLE_WORDEXP=<ON|OFF>` 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)
|
||||
* 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)
|
||||
* 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
|
||||
|
||||
Logos:
|
||||
* Adds secureblue, PrismLinux, EmperorOS and Zraxyl
|
||||
* Updates T2
|
||||
|
||||
# 2.53.0
|
||||
|
||||
Changes:
|
||||
* JSON property `length` in `Separator` module has been renamed to `times` for clarity (Separator)
|
||||
|
||||
Features:
|
||||
* Adds IPv6 type selection (#1459, LocalIP)
|
||||
* For example: `{ "type": "localip", "showIpv6": "ula" /* Show ULA only */ }`
|
||||
* Adds more ARM CPU part IDs (CPU, Linux)
|
||||
* Improves Ghostty font config parsing with fallback font detection (#1967, TerminalFont)
|
||||
* Replaces statx(2) call with syscall(2) for better compatibility (Disk, Linux)
|
||||
* Allows array input for disk folder and filesystem options (Disk)
|
||||
* For example: `{ "type": "disk", "folders": ["/", "/home"] }`
|
||||
* Adds support for ignoring input devices by name prefix (#1950, Keyboard / Mouse / Gamepad)
|
||||
* For example: `{ "type": "keyboard", "ignores": ["Apple ", "Corsair "] }`
|
||||
* Adds support for (B)SSID detection on macOS Tahoe (Wifi, macOS)
|
||||
* Please don't expect it to work on later macOS versions
|
||||
* Improves Ubuntu flavor detection (#1975, OS, Linux)
|
||||
* Refines ARMv8.4-A detection to require LSE2 (CPU, Windows)
|
||||
* Detects the latest Dimensity & Snapdragon SoC names (CPU, Android)
|
||||
|
||||
Bugfixes:
|
||||
* Handles zero temperature data (#1960, CPU, Windows)
|
||||
* Fixes `dlopen libzfs.so failed` error on Proxmox 9 (#1973, Zpool, Linux)
|
||||
|
||||
Logos:
|
||||
* Removes Starry Linux
|
||||
* Adds TempleOS
|
||||
* Updates ObsidianOS
|
||||
|
||||
# 2.52.0
|
||||
|
||||
Changes:
|
||||
* New optional build dependencies on Android
|
||||
* main: chafa dbus glib imagemagick libelf libxcb libxrandr pulseaudio zlib
|
||||
* x11: dconf (Optional)
|
||||
* Dependency on `libxfconf` is removed. XFCE related detection now uses `libdbus` instead (Linux)
|
||||
* The default format of `Display` module is updated to `{width}x{height} @ {scale-factor}x in {inch}", {refresh-rate} Hz`
|
||||
* Replaced scaled resolution with scale factor for shorter texts and avoiding potential confusion.
|
||||
|
||||
Bugfixes:
|
||||
* Fixes linking on 32-bit Android (#1939)
|
||||
* Skips network interfaces without IPs unless MAC address is requested (#1949, LocalIP)
|
||||
* Fixes unexpected padding when setting `logo.width` with chafa logos (#1947, Logo)
|
||||
* Regression from v2.51.0
|
||||
* Improves Wallpaper detection on XFCE4 (Wallpaper, Linux)
|
||||
* Ignores process `Relay(xxx)` when detecting terminal on WSL2 (Terminal, Linux)
|
||||
|
||||
Features:
|
||||
* Enables X11-related info (i.e., WM/DE) detection on Android (Global, Android)
|
||||
* This requires many dependencies. See above.
|
||||
* Adds scale factors detection for X11 (Display, Linux)
|
||||
* X11 doesn't natively report scale factor as Wayland does. Instead, Fastfetch tries to detect `Xft.dpi` (DPI used by X FreeType for scaling fonts), which is usually set by the WM when DPI scaling is enabled.
|
||||
* It's not always accurate. For example, XFCE4 has a separate config for text scaling, which is unaffected by the global DPI scaling setting.
|
||||
* Adds `display.fraction.trailingZeros: [always|never]` option for fraction formatting
|
||||
* The default value of `display.fraction.ndigits` is changed from `-1` (unlimited) to `2` for usability.
|
||||
* Used for displaying scale factor in Display module mentioned above, alongside other places for printing raw fraction numbers.
|
||||
* Informs users that module-specific CLI options are no longer supported and provide guidance for transitioning to JSON config
|
||||
* Adds CPU name detection support for IA64 (CPU, Linux)
|
||||
* Support Btrfs allocation profile detection (#1941, Btrfs, Linux)
|
||||
|
||||
# 2.51.1
|
||||
|
||||
Bugfixes:
|
||||
|
||||
+99
-100
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.51.1
|
||||
VERSION 2.56.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -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 #
|
||||
###################
|
||||
@@ -60,32 +71,30 @@ include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR ANDROID OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR ANDROID OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "GNU" OFF)
|
||||
|
||||
option(ENABLE_ZLIB "Enable zlib" ON)
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
|
||||
@@ -96,6 +105,8 @@ 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)
|
||||
option(ENABLE_LIBZFS "Enable libzfs" ON)
|
||||
|
||||
set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
|
||||
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
|
||||
@@ -378,6 +389,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/chassis/chassis.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuusage/cpuusage.c
|
||||
src/detection/command/command.c
|
||||
src/detection/disk/disk.c
|
||||
src/detection/diskio/diskio.c
|
||||
src/detection/displayserver/displayserver.c
|
||||
@@ -398,6 +410,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/version/version.c
|
||||
src/detection/vulkan/vulkan.c
|
||||
src/detection/weather/weather.c
|
||||
src/detection/zpool/zpool.c
|
||||
src/logo/builtin.c
|
||||
src/logo/image/im6.c
|
||||
src/logo/image/im7.c
|
||||
@@ -515,6 +528,7 @@ if(LINUX)
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_linux.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
@@ -569,12 +583,12 @@ if(LINUX)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
@@ -590,7 +604,7 @@ elseif(ANDROID)
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
src/detection/cpu/cpu_linux.c
|
||||
src/detection/cpucache/cpucache_linux.c
|
||||
src/detection/cursor/cursor_nosupport.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/cpuusage/cpuusage_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
src/detection/dns/dns_linux.c
|
||||
@@ -598,10 +612,16 @@ elseif(ANDROID)
|
||||
src/detection/physicalmemory/physicalmemory_nosupport.c
|
||||
src/detection/diskio/diskio_linux.c
|
||||
src/detection/displayserver/displayserver_android.c
|
||||
src/detection/font/font_nosupport.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_android.c
|
||||
src/detection/host/host_android.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/initsystem/initsystem_linux.c
|
||||
src/detection/keyboard/keyboard_nosupport.c
|
||||
src/detection/libc/libc_android.c
|
||||
@@ -610,7 +630,7 @@ elseif(ANDROID)
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_nosupport.c
|
||||
src/detection/media/media_nosupport.c
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_linux.c
|
||||
src/detection/mouse/mouse_nosupport.c
|
||||
src/detection/netio/netio_linux.c
|
||||
@@ -620,22 +640,22 @@ elseif(ANDROID)
|
||||
src/detection/packages/packages_nix.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_linux.c
|
||||
src/detection/sound/sound_nosupport.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/swap/swap_linux.c
|
||||
src/detection/terminalfont/terminalfont_android.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/terminalsize/terminalsize_linux.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/theme/theme_linux.c
|
||||
src/detection/tpm/tpm_nosupport.c
|
||||
src/detection/uptime/uptime_linux.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_nosupport.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_android.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/wm/wm_linux.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_android.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -665,6 +685,7 @@ elseif(FreeBSD)
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_bsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
@@ -717,7 +738,6 @@ elseif(FreeBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -759,6 +779,7 @@ elseif(NetBSD)
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_nbsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
@@ -772,7 +793,7 @@ elseif(NetBSD)
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_general.c
|
||||
src/detection/gpu/gpu_nbsd.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_nbsd.c
|
||||
@@ -810,7 +831,6 @@ elseif(NetBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -841,6 +861,7 @@ elseif(OpenBSD)
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_obsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
@@ -855,7 +876,7 @@ elseif(OpenBSD)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gpu/gpu_general.c
|
||||
src/detection/gpu/gpu_obsd.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_obsd.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
@@ -892,7 +913,6 @@ elseif(OpenBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/smbiosHelper.c
|
||||
@@ -952,7 +972,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
|
||||
@@ -962,7 +982,6 @@ elseif(APPLE)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/camera/camera_apple.m
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
src/util/apple/smc_temps.c
|
||||
@@ -1013,7 +1032,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
|
||||
@@ -1022,7 +1041,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
|
||||
@@ -1032,7 +1051,6 @@ elseif(WIN32)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/detection/camera/camera_windows.cpp
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
src/util/windows/registry.c
|
||||
@@ -1069,6 +1087,7 @@ elseif(SunOS)
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_sunos.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
@@ -1120,7 +1139,6 @@ elseif(SunOS)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -1189,7 +1207,6 @@ elseif(Haiku)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/haiku/version.cpp
|
||||
@@ -1220,6 +1237,7 @@ elseif(GNU)
|
||||
src/detection/physicalmemory/physicalmemory_nosupport.c
|
||||
src/detection/diskio/diskio_nosupport.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/common.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
@@ -1229,7 +1247,7 @@ elseif(GNU)
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_nosupport.c
|
||||
src/detection/gpu/gpu_general.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_nosupport.c
|
||||
@@ -1268,7 +1286,6 @@ elseif(GNU)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -1291,10 +1308,7 @@ endif()
|
||||
include(CheckFunctionExists)
|
||||
check_function_exists(wcwidth HAVE_WCWIDTH)
|
||||
if(NOT HAVE_WCWIDTH)
|
||||
list(APPEND LIBFASTFETCH_SRC src/3rdparty/mk_wcwidch/wcwidth.c)
|
||||
endif()
|
||||
if(LINUX)
|
||||
check_function_exists(statx HAVE_STATX)
|
||||
list(APPEND LIBFASTFETCH_SRC src/util/wcwidth.c)
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
@@ -1318,15 +1332,15 @@ add_library(libfastfetch OBJECT
|
||||
)
|
||||
|
||||
if(yyjson_FOUND)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON=1)
|
||||
target_link_libraries(libfastfetch PUBLIC yyjson::yyjson)
|
||||
# `target_link_libraries(yyjson::yyjson)` sets rpath implicitly
|
||||
else()
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE AND BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
@@ -1411,10 +1425,6 @@ if(FreeBSD OR OpenBSD OR NetBSD)
|
||||
unset(CMAKE_REQUIRED_DEFINITIONS)
|
||||
endif()
|
||||
|
||||
if(HAVE_STATX)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_STATX)
|
||||
endif()
|
||||
|
||||
if(HAVE_WCWIDTH)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WCWIDTH)
|
||||
endif()
|
||||
@@ -1525,10 +1535,6 @@ ff_lib_enable(DBUS
|
||||
"dbus-1"
|
||||
"DBus"
|
||||
)
|
||||
ff_lib_enable(XFCONF
|
||||
"libxfconf-0"
|
||||
"XFConf"
|
||||
)
|
||||
ff_lib_enable(SQLITE3
|
||||
"sqlite3"
|
||||
"SQLite3"
|
||||
@@ -1596,24 +1602,6 @@ ff_lib_enable(PCIACCESS
|
||||
"pciaccess"
|
||||
"pciaccess"
|
||||
)
|
||||
# The system <libzfs.h> is only usable on SunOS. We provide our local copy of it so it's always available.
|
||||
if(ENABLE_LIBZFS)
|
||||
if(BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
else()
|
||||
set(CMAKE_REQUIRED_LIBRARIES_BACKUP ${CMAKE_REQUIRED_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} zfs)
|
||||
check_function_exists("libzfs_init" LIBZFS_FOUND)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_BACKUP})
|
||||
if(NOT LIBZFS_FOUND)
|
||||
message(STATUS "Library: missing: LIBZFS")
|
||||
else()
|
||||
message(STATUS "Library: found LIBZFS")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
target_link_libraries(libfastfetch PRIVATE zfs)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_THREADS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
|
||||
@@ -1628,6 +1616,15 @@ endif()
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
|
||||
endif()
|
||||
if(ENABLE_LIBZFS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "zfs"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1676,11 +1673,10 @@ elseif(WIN32)
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "imagehlp"
|
||||
PRIVATE "cfgmgr32"
|
||||
PRIVATE "winbrand"
|
||||
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"
|
||||
@@ -1719,8 +1715,6 @@ elseif(SunOS)
|
||||
PRIVATE "socket"
|
||||
PRIVATE "kstat"
|
||||
PRIVATE "proc"
|
||||
PRIVATE "zfs"
|
||||
PRIVATE "nvpair"
|
||||
PRIVATE "devinfo"
|
||||
)
|
||||
elseif(GNU)
|
||||
@@ -1728,17 +1722,23 @@ elseif(GNU)
|
||||
PRIVATE "m"
|
||||
)
|
||||
elseif(ANDROID)
|
||||
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)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
)
|
||||
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)
|
||||
@@ -1800,13 +1800,17 @@ 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)
|
||||
message(STATUS "wordexp.h found, wordexp support enabled")
|
||||
else()
|
||||
set(ENABLE_WORDEXP OFF)
|
||||
endif()
|
||||
endif()
|
||||
CHECK_INCLUDE_FILE("glob.h" HAVE_GLOB)
|
||||
if(HAVE_GLOB)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLOB=1)
|
||||
if(NOT ENABLE_WORDEXP)
|
||||
message(STATUS "wordexp.h not found or disabled, glob used instead")
|
||||
endif()
|
||||
if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT)
|
||||
CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
|
||||
@@ -2015,11 +2019,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)
|
||||
@@ -2066,7 +2065,7 @@ endif()
|
||||
|
||||
set(CPACK_SET_DESTDIR ON)
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
|
||||
set(CPACK_PACKAGE_CONTACT "Carter Li <zhangsongcui@live.cn>")
|
||||
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.\
|
||||
|
||||
@@ -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-<subsystem>-<arch>-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 <module1>[:<module2>] --format json`
|
||||
- 完整命令行帮助:`fastfetch --help`
|
||||
- 生成最小配置:`fastfetch --gen-config [</path/to/config.jsonc>]`
|
||||
- 生成完整配置:`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 <filename>` 加载
|
||||
- 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(请填写模版)
|
||||
|
||||
## 赞助
|
||||
|
||||
<img src="https://github.com/user-attachments/assets/a36a6501-e8b0-4a10-9061-b9206d12ffba" width="220">
|
||||
@@ -11,8 +11,9 @@
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://deepwiki.com/fastfetch-cli/fastfetch)
|
||||
[](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.
|
||||
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 illumos (SunOS).
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
@@ -36,7 +37,8 @@ Some distributions package outdated versions of fastfetch. Older versions receiv
|
||||
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
|
||||
</a>
|
||||
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (Ubuntu 22.04 or newer; latest version)
|
||||
* Debian / Ubuntu: `apt install fastfetch` (Debian 13 or newer; Ubuntu 25.04 or newer)
|
||||
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
|
||||
* Arch Linux: `pacman -S fastfetch`
|
||||
* Fedora: `dnf install fastfetch`
|
||||
@@ -103,6 +105,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?
|
||||
@@ -317,6 +323,11 @@ If you find Fastfetch useful, please consider donating.
|
||||
* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui)
|
||||
* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer)
|
||||
|
||||
## Code signing
|
||||
|
||||
* Free code signing provided by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/)
|
||||
* This program will not transfer any information to other networked systems unless specifically requested by the user or the person installing or operating it
|
||||
|
||||
## Star History
|
||||
|
||||
Give us a star to show your support!
|
||||
|
||||
+49
-1
@@ -1,3 +1,52 @@
|
||||
fastfetch (2.56.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 18 Dec 2025 14:57:36 +0800
|
||||
|
||||
fastfetch (2.56.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Dec 2025 09:21:58 +0800
|
||||
|
||||
fastfetch (2.55.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 17 Nov 2025 10:15:44 +0800
|
||||
|
||||
fastfetch (2.55.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 12 Nov 2025 09:15:24 +0800
|
||||
|
||||
fastfetch (2.54.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Fix building on plucky
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 14:27:02 +0800
|
||||
|
||||
fastfetch (2.54.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.54.0
|
||||
* Test independent changelog entries for different Ubuntu releases
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 10:47:02 +0800
|
||||
|
||||
fastfetch (2.53.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.53.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 23 Sep 2025 09:58:48 +0800
|
||||
|
||||
fastfetch (2.52.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.52.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 05 Sep 2025 14:59:44 +0800
|
||||
|
||||
fastfetch (2.51.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.51.0
|
||||
@@ -423,4 +472,3 @@ fastfetch (2.7.1) jammy; urgency=medium
|
||||
* Initial release.
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Build-Depends: libelf-dev, 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, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build, python3-setuptools
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
fastfetch_2.51.0_source.buildinfo universe/utils optional
|
||||
Vendored
+74
-2
@@ -1,4 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# WARNING: DO NOT RUN THIS SCRIPT UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
|
||||
debuild -S -i -I
|
||||
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
|
||||
set -euo pipefail
|
||||
|
||||
command -v debuild >/dev/null 2>&1 || { echo "debuild not found. Install devscripts." >&2; exit 1; }
|
||||
command -v dput >/dev/null 2>&1 || { echo "dput not found." >&2; exit 1; }
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
|
||||
OUT_DIR="$(dirname "$ROOT_DIR")"
|
||||
PPA="ppa:zhangsongcui3371/fastfetch"
|
||||
CODENAMES=( jammy noble plucky questing resolute )
|
||||
DRY_RUN=0
|
||||
|
||||
if [[ -d "$OUT_DIR/build" ]]; then
|
||||
echo "Output directory exists: $OUT_DIR/build" >&2
|
||||
echo "Please move or delete it before proceeding." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMPLATE="$ROOT_DIR/debian/changelog.tpl"
|
||||
CHANGELOG_DEBIAN="$ROOT_DIR/debian/changelog"
|
||||
|
||||
if [[ ! -f "$TEMPLATE" ]]; then
|
||||
echo "Template not found: $TEMPLATE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '#UBUNTU_CODENAME#' "$TEMPLATE"; then
|
||||
echo "Template missing placeholder: #UBUNTU_CODENAME#" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "IMPORTANT: Before proceeding, please ensure that 'debian/changelog.tpl' is up-to-date"
|
||||
echo " with the correct version number, release notes, and maintainer information."
|
||||
echo
|
||||
echo " The template must contain a placeholder like '#UBUNTU_CODENAME#' for the codename."
|
||||
echo
|
||||
read -p "Have you reviewed and updated 'debian/changelog.tpl'? (y/N): " -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
rm -f "$CHANGELOG_DEBIAN"
|
||||
rm -f "$ROOT_DIR/debian/files"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
for codename in "${CODENAMES[@]}"; do
|
||||
echo "==> Publishing distro: $codename"
|
||||
sed "s/#UBUNTU_CODENAME#/${codename}/g" "$TEMPLATE" > "$CHANGELOG_DEBIAN"
|
||||
|
||||
( cd "$ROOT_DIR" && debuild -S -i -I )
|
||||
|
||||
changes=( "$OUT_DIR"/fastfetch_*~${codename}_source.changes )
|
||||
if [[ ${#changes[@]} -ne 1 ]]; then
|
||||
echo "Unable to uniquely identify .changes for '$codename' in: $OUT_DIR" >&2
|
||||
printf 'Found:\n'; printf ' %s\n' "${changes[@]}" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $DRY_RUN -eq 1 ]]; then
|
||||
echo "[DRY-RUN] dput \"$PPA\" \"${changes[0]}\""
|
||||
else
|
||||
dput "$PPA" "${changes[0]}"
|
||||
fi
|
||||
|
||||
rm -f "$OUT_DIR"/fastfetch_*~${codename}_source.{changes,dsc,tar.*}
|
||||
|
||||
echo "<== Done: $codename"
|
||||
done
|
||||
|
||||
+182
-17
@@ -1008,7 +1008,7 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Set whether to show icon before string keys",
|
||||
"description": "Set whether to show builtin icon before string keys",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "none",
|
||||
@@ -1020,11 +1020,31 @@
|
||||
},
|
||||
{
|
||||
"const": "icon",
|
||||
"description": "Show icon keys (requires newest nerd font)"
|
||||
"description": "Show builtin icon (requires newest nerd font)"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
@@ -1290,10 +1310,19 @@
|
||||
"description": "Set how frequency values should be displayed",
|
||||
"properties": {
|
||||
"ndigits": {
|
||||
"type": "integer",
|
||||
"description": "Set the number of digits to keep after the decimal point when formatting frequency values\nA positive value will show the frequency in GHz with decimal\n-1 will show the frequency in MHz",
|
||||
"minimum": -1,
|
||||
"maximum": 9,
|
||||
"description": "Set the number of decimal places to display when formatting frequency values",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 9,
|
||||
"description": "Integer value displays the frequency in GHz with specified decimal places"
|
||||
},
|
||||
{
|
||||
"type": "null",
|
||||
"description": "Null value display the frequency as integer MHz"
|
||||
}
|
||||
],
|
||||
"default": 2
|
||||
},
|
||||
"spaceBeforeUnit": {
|
||||
@@ -1333,6 +1362,28 @@
|
||||
"description": "The number of digits will be automatically determined based on the value"
|
||||
}
|
||||
],
|
||||
"default": 2
|
||||
},
|
||||
"trailingZeros": {
|
||||
"description": "Set when to keep trailing zeros",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "null",
|
||||
"description": "Same as `default`"
|
||||
},
|
||||
{
|
||||
"const": "default",
|
||||
"description": "Use the behavior defined internally"
|
||||
},
|
||||
{
|
||||
"const": "always",
|
||||
"description": "Always keep trailing zeros"
|
||||
},
|
||||
{
|
||||
"const": "never",
|
||||
"description": "Never keep trailing zeros"
|
||||
}
|
||||
],
|
||||
"default": null
|
||||
}
|
||||
}
|
||||
@@ -1829,6 +1880,10 @@
|
||||
"temp": {
|
||||
"$ref": "#/$defs/temperature"
|
||||
},
|
||||
"tempSensor": {
|
||||
"description": "Set the temperature sensor to use for CPU temperature detection\n* Linux: `hwmon` or `thermal` path name (eg. `hwmon0`, `thermal_zone0)`\n* macOS: SMC sensor key (eg. `Tp01`)\n* Windows: thermal zone key (eg. `\\_TZ.CPUZ`)\n* FreeBSD: sysctl key (eg. `dev.cpu.0.temperature`)\n* NetBSD: sysmon sensor key (eg. `coretemp0`)",
|
||||
"type": "string"
|
||||
},
|
||||
"showPeCoreCount": {
|
||||
"description": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported",
|
||||
"type": "boolean",
|
||||
@@ -2050,6 +2105,21 @@
|
||||
"description": "Set the command text to be executed",
|
||||
"type": "string"
|
||||
},
|
||||
"useStdErr": {
|
||||
"description": "Set if stderr should be used instead of stdout for command output",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"parallel": {
|
||||
"description": "Set if the command should be executed in parallel with other commands\nImprove performance when using multiple commands, but may cause issues with some commands",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"splitLines": {
|
||||
"description": "Set if the command output should be split into multiple lines",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -2276,17 +2346,60 @@
|
||||
"const": "disk"
|
||||
},
|
||||
"folders": {
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options"
|
||||
"description": "A list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths to get disk usage from",
|
||||
"default": "/"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of folder paths to get disk usage from",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"hideFolders": {
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output",
|
||||
"default": "/efi:/boot:/boot/efi:/boot/firmware"
|
||||
"description": "A list of folder paths (or glob patterns) to hide from the disk output",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of folder paths to hide from the disk output",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
],
|
||||
"default": "/efi:/boot:/boot/*"
|
||||
},
|
||||
"hideFS": {
|
||||
"type": "string",
|
||||
"description": "A colon separated file systems to hide from the disk output"
|
||||
"description": "A list of file systems to hide from the disk output",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A colon separated list of file systems to hide from the disk output"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of file systems to hide from the disk output",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"showRegular": {
|
||||
"type": "boolean",
|
||||
@@ -2562,6 +2675,15 @@
|
||||
"const": "gamepad",
|
||||
"description": "List connected gamepads"
|
||||
},
|
||||
"ignores": {
|
||||
"type": "array",
|
||||
"description": "An array of case-insensitive device name prefixes to ignore",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
@@ -2821,6 +2943,15 @@
|
||||
"const": "keyboard",
|
||||
"description": "List (connected) keyboards"
|
||||
},
|
||||
"ignores": {
|
||||
"type": "array",
|
||||
"description": "An array of case-insensitive device name prefixes to ignore",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -2889,7 +3020,32 @@
|
||||
},
|
||||
"showIpv6": {
|
||||
"description": "Show IPv6 addresses",
|
||||
"type": "boolean",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": true,
|
||||
"description": "Show the most useful IPv6 addresses"
|
||||
},
|
||||
{
|
||||
"const": false,
|
||||
"description": "Do not show IPv6 addresses"
|
||||
},
|
||||
{
|
||||
"const": "gua",
|
||||
"description": "Show only global unicast IPv6 addresses (2000::/3)"
|
||||
},
|
||||
{
|
||||
"const": "ula",
|
||||
"description": "Show only unique local IPv6 addresses (fc00::/7)"
|
||||
},
|
||||
{
|
||||
"const": "lla",
|
||||
"description": "Show only link-local IPv6 addresses (fe80::/10)"
|
||||
},
|
||||
{
|
||||
"const": "unknown",
|
||||
"description": "Show only IPv6 addresses that are not gua, ula or lla"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
},
|
||||
"showSpeed": {
|
||||
@@ -3119,6 +3275,15 @@
|
||||
"const": "mouse",
|
||||
"description": "List connected mouses"
|
||||
},
|
||||
"ignores": {
|
||||
"type": "array",
|
||||
"description": "An array of case-insensitive device name prefixes to ignore",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -3656,8 +3821,8 @@
|
||||
"description": "Set the color of the separator line",
|
||||
"$ref": "#/$defs/outputColor"
|
||||
},
|
||||
"length": {
|
||||
"description": "Set the length of the separator line, or 0 to auto-detect",
|
||||
"times": {
|
||||
"description": "Set the times of separator string to repeat, or 0 to auto-detect",
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
},
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"text": "clang --version | head -1 | awk '{print $NF}'",
|
||||
"text": "clang --version | sed -n 's/.*version \\([0-9][0-9.]*\\).*/\\1/p'",
|
||||
"format": "clang {}"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #1887
|
||||
{
|
||||
"$schema": "file:///Users/carter/fastfetch/doc/json_schema.json",
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": null,
|
||||
"display": {
|
||||
"constants": [
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": null,
|
||||
"display": {
|
||||
"key": {
|
||||
"type": "both",
|
||||
"paddingLeft": 6,
|
||||
"width": 17
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "|---------------------: {#1}Hardware{#} : ---------------------|"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"keyColor": "green",
|
||||
"type": "host"
|
||||
},
|
||||
{
|
||||
"keyColor": "green",
|
||||
"type": "cpu"
|
||||
},
|
||||
{
|
||||
"keyColor": "yellow",
|
||||
"type": "memory"
|
||||
},
|
||||
{
|
||||
"keyColor": "yellow",
|
||||
"type": "swap"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"keyIcon": "",
|
||||
"key": "Disks"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": " ",
|
||||
"format": " [{mountpoint}] - {size-used} / {size-total} ({size-percentage})"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "title",
|
||||
"format": "|-------------------------------------------------------|\u001b[40D: {#1}{user-name} @ {host-name}{#} :"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "os",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"keyColor": "red",
|
||||
"key": "Pkgs"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"keyColor": "red"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "Term",
|
||||
"keyColor": "red"
|
||||
},
|
||||
{
|
||||
"type": "locale",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "|---------------------: {#1}Software{#} : ---------------------|"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "colors",
|
||||
"symbol": "circle",
|
||||
"paddingLeft": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"home": "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c",
|
||||
"license": "MIT compatible (embed in source)",
|
||||
"version": "2007-05-26 (Unicode 5.0)",
|
||||
"author": "Markus Kuhn",
|
||||
"modified": "CarterLi"
|
||||
}
|
||||
Vendored
-314
@@ -1,314 +0,0 @@
|
||||
/*
|
||||
* This is an implementation of wcwidth() and wcswidth() (defined in
|
||||
* IEEE Std 1002.1-2001) for Unicode.
|
||||
*
|
||||
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
|
||||
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
|
||||
*
|
||||
* In fixed-width output devices, Latin characters all occupy a single
|
||||
* "cell" position of equal width, whereas ideographic CJK characters
|
||||
* occupy two such cells. Interoperability between terminal-line
|
||||
* applications and (teletype-style) character terminals using the
|
||||
* UTF-8 encoding requires agreement on which character should advance
|
||||
* the cursor by how many cell positions. No established formal
|
||||
* standards exist at present on which Unicode character shall occupy
|
||||
* how many cell positions on character terminals. These routines are
|
||||
* a first attempt of defining such behavior based on simple rules
|
||||
* applied to data provided by the Unicode Consortium.
|
||||
*
|
||||
* For some graphical characters, the Unicode standard explicitly
|
||||
* defines a character-cell width via the definition of the East Asian
|
||||
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
|
||||
* In all these cases, there is no ambiguity about which width a
|
||||
* terminal shall use. For characters in the East Asian Ambiguous (A)
|
||||
* class, the width choice depends purely on a preference of backward
|
||||
* compatibility with either historic CJK or Western practice.
|
||||
* Choosing single-width for these characters is easy to justify as
|
||||
* the appropriate long-term solution, as the CJK practice of
|
||||
* displaying these characters as double-width comes from historic
|
||||
* implementation simplicity (8-bit encoded characters were displayed
|
||||
* single-width and 16-bit ones double-width, even for Greek,
|
||||
* Cyrillic, etc.) and not any typographic considerations.
|
||||
*
|
||||
* Much less clear is the choice of width for the Not East Asian
|
||||
* (Neutral) class. Existing practice does not dictate a width for any
|
||||
* of these characters. It would nevertheless make sense
|
||||
* typographically to allocate two character cells to characters such
|
||||
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
|
||||
* represented adequately with a single-width glyph. The following
|
||||
* routines at present merely assign a single-cell width to all
|
||||
* neutral characters, in the interest of simplicity. This is not
|
||||
* entirely satisfactory and should be reconsidered before
|
||||
* establishing a formal standard in this area. At the moment, the
|
||||
* decision which Not East Asian (Neutral) characters should be
|
||||
* represented by double-width glyphs cannot yet be answered by
|
||||
* applying a simple rule from the Unicode database content. Setting
|
||||
* up a proper standard for the behavior of UTF-8 character terminals
|
||||
* will require a careful analysis not only of each Unicode character,
|
||||
* but also of each presentation form, something the author of these
|
||||
* routines has avoided to do so far.
|
||||
*
|
||||
* http://www.unicode.org/unicode/reports/tr11/
|
||||
*
|
||||
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software
|
||||
* for any purpose and without fee is hereby granted. The author
|
||||
* disclaims all warranties with regard to this software.
|
||||
*
|
||||
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
*/
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
struct interval {
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
/* auxiliary function for binary search in interval table */
|
||||
static int bisearch(wchar_t ucs, const struct interval *table, int max) {
|
||||
int min = 0;
|
||||
int mid;
|
||||
|
||||
if (ucs < table[0].first || ucs > table[max].last)
|
||||
return 0;
|
||||
while (max >= min) {
|
||||
mid = (min + max) / 2;
|
||||
if (ucs > table[mid].last)
|
||||
min = mid + 1;
|
||||
else if (ucs < table[mid].first)
|
||||
max = mid - 1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The following two functions define the column width of an ISO 10646
|
||||
* character as follows:
|
||||
*
|
||||
* - The null character (U+0000) has a column width of 0.
|
||||
*
|
||||
* - Other C0/C1 control characters and DEL will lead to a return
|
||||
* value of -1.
|
||||
*
|
||||
* - Non-spacing and enclosing combining characters (general
|
||||
* category code Mn or Me in the Unicode database) have a
|
||||
* column width of 0.
|
||||
*
|
||||
* - SOFT HYPHEN (U+00AD) has a column width of 1.
|
||||
*
|
||||
* - Other format characters (general category code Cf in the Unicode
|
||||
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
|
||||
*
|
||||
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
|
||||
* have a column width of 0.
|
||||
*
|
||||
* - Spacing characters in the East Asian Wide (W) or East Asian
|
||||
* Full-width (F) category as defined in Unicode Technical
|
||||
* Report #11 have a column width of 2.
|
||||
*
|
||||
* - All remaining characters (including all printable
|
||||
* ISO 8859-1 and WGL4 characters, Unicode control characters,
|
||||
* etc.) have a column width of 1.
|
||||
*
|
||||
* This implementation assumes that wchar_t characters are encoded
|
||||
* in ISO 10646.
|
||||
*/
|
||||
|
||||
int mk_wcwidth(wchar_t ucs)
|
||||
{
|
||||
/* sorted list of non-overlapping intervals of non-spacing characters */
|
||||
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
|
||||
static const struct interval combining[] = {
|
||||
{ 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
|
||||
{ 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
|
||||
{ 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
|
||||
{ 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
|
||||
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
|
||||
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
|
||||
{ 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
|
||||
{ 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
|
||||
{ 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
|
||||
{ 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
|
||||
{ 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
|
||||
{ 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
|
||||
{ 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
|
||||
{ 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
|
||||
{ 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
|
||||
{ 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
|
||||
{ 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
|
||||
{ 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
|
||||
{ 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
|
||||
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
|
||||
{ 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
|
||||
{ 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
|
||||
{ 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
|
||||
{ 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
|
||||
{ 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
|
||||
{ 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
|
||||
{ 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
|
||||
{ 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
|
||||
{ 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
|
||||
{ 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
|
||||
{ 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
|
||||
{ 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
|
||||
{ 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
|
||||
{ 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
|
||||
{ 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
|
||||
{ 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
|
||||
{ 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
|
||||
{ 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
|
||||
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
|
||||
{ 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
|
||||
{ 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
|
||||
{ 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
|
||||
{ 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
|
||||
{ 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
|
||||
{ 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
|
||||
{ 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
|
||||
{ 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
|
||||
{ 0xE0100, 0xE01EF }
|
||||
};
|
||||
|
||||
/* test for 8-bit control characters */
|
||||
if (ucs == 0)
|
||||
return 0;
|
||||
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
|
||||
return -1;
|
||||
|
||||
/* binary search in table of non-spacing characters */
|
||||
if (bisearch(ucs, combining,
|
||||
sizeof(combining) / sizeof(struct interval) - 1))
|
||||
return 0;
|
||||
|
||||
/* if we arrive here, ucs is not a combining or C0/C1 control character */
|
||||
|
||||
return 1 +
|
||||
(ucs >= 0x1100 &&
|
||||
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
|
||||
ucs == 0x2329 || ucs == 0x232a ||
|
||||
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
|
||||
ucs != 0x303f) || /* CJK ... Yi */
|
||||
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
|
||||
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
|
||||
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
|
||||
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
|
||||
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
|
||||
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
|
||||
|
||||
#ifndef _WIN32 // sizeof(wchar_t) == 2
|
||||
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
|
||||
(ucs >= 0x30000 && ucs <= 0x3fffd) ||
|
||||
#endif
|
||||
0
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
int mk_wcswidth(const wchar_t *pwcs, size_t n)
|
||||
{
|
||||
int w, width = 0;
|
||||
|
||||
for (;*pwcs && n-- > 0; pwcs++)
|
||||
if ((w = mk_wcwidth(*pwcs)) < 0)
|
||||
return -1;
|
||||
else
|
||||
width += w;
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The following functions are the same as mk_wcwidth() and
|
||||
* mk_wcswidth(), except that spacing characters in the East Asian
|
||||
* Ambiguous (A) category as defined in Unicode Technical Report #11
|
||||
* have a column width of 2. This variant might be useful for users of
|
||||
* CJK legacy encodings who want to migrate to UCS without changing
|
||||
* the traditional terminal character-width behaviour. It is not
|
||||
* otherwise recommended for general use.
|
||||
*/
|
||||
int mk_wcwidth_cjk(wchar_t ucs)
|
||||
{
|
||||
/* sorted list of non-overlapping intervals of East Asian Ambiguous
|
||||
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
|
||||
static const struct interval ambiguous[] = {
|
||||
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
|
||||
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
|
||||
{ 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
|
||||
{ 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
|
||||
{ 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
|
||||
{ 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
|
||||
{ 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
|
||||
{ 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
|
||||
{ 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
|
||||
{ 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
|
||||
{ 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
|
||||
{ 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
|
||||
{ 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
|
||||
{ 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
|
||||
{ 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
|
||||
{ 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
|
||||
{ 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
|
||||
{ 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
|
||||
{ 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
|
||||
{ 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
|
||||
{ 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
|
||||
{ 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
|
||||
{ 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
|
||||
{ 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
|
||||
{ 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
|
||||
{ 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
|
||||
{ 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
|
||||
{ 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
|
||||
{ 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
|
||||
{ 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
|
||||
{ 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
|
||||
{ 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
|
||||
{ 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
|
||||
{ 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
|
||||
{ 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
|
||||
{ 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
|
||||
{ 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
|
||||
{ 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
|
||||
{ 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
|
||||
{ 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
|
||||
{ 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
|
||||
{ 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
|
||||
{ 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
|
||||
{ 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
|
||||
{ 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
|
||||
{ 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
|
||||
{ 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
|
||||
{ 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
|
||||
{ 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
|
||||
{ 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
|
||||
{ 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
|
||||
{ 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
|
||||
};
|
||||
|
||||
/* binary search in table of non-spacing characters */
|
||||
if (bisearch(ucs, ambiguous,
|
||||
sizeof(ambiguous) / sizeof(struct interval) - 1))
|
||||
return 2;
|
||||
|
||||
return mk_wcwidth(ucs);
|
||||
}
|
||||
|
||||
|
||||
int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
|
||||
{
|
||||
int w, width = 0;
|
||||
|
||||
for (;*pwcs && n-- > 0; pwcs++)
|
||||
if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
|
||||
return -1;
|
||||
else
|
||||
width += w;
|
||||
|
||||
return width;
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/ridiculousfish/widecharwidth",
|
||||
"license": "Public domain",
|
||||
"version": "Unicode 17",
|
||||
"author": "ridiculousfish"
|
||||
}
|
||||
+1590
File diff suppressed because it is too large
Load Diff
+72
-20
@@ -10,44 +10,96 @@
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
bool ffParseModuleOptions(const char* key, const char* value)
|
||||
{
|
||||
if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) return false;
|
||||
if (value && !*value) value = NULL;
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
const char* subKey = ffOptionTestPrefix(key, baseInfo->name);
|
||||
if (subKey != NULL)
|
||||
{
|
||||
if (subKey[0] == '\0' || subKey[0] == '-') // Key is exactly the module name or has a leading '-'
|
||||
{
|
||||
fprintf(stderr, "Error: unknown module key %s\n", key);
|
||||
exit(477);
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY moduleName = ffStrbufCreateS(baseInfo->name);
|
||||
ffStrbufLowerCase(&moduleName);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY jsonKey = ffStrbufCreate();
|
||||
bool flag = false;
|
||||
for (const char* p = subKey; *p; ++p)
|
||||
{
|
||||
if (*p == '-')
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
fprintf(stderr, "Error: invalid double `-` in module key %s\n", key);
|
||||
exit(477);
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isalpha((unsigned char)*p) && !isdigit((unsigned char)*p))
|
||||
{
|
||||
fprintf(stderr, "Error: invalid character `%c` in module key %s\n", *p, key);
|
||||
exit(477);
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
flag = false;
|
||||
ffStrbufAppendC(&jsonKey, (char) toupper((unsigned char) *p));
|
||||
}
|
||||
else
|
||||
ffStrbufAppendC(&jsonKey, *p);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Error: Unsupported module option: %s\n", key);
|
||||
fputs(" Support of module options has been removed. Please add the flag to the JSON config instead.\n", stderr);
|
||||
fprintf(stderr, " Example (demonstration only): `{ \"modules\": [ { \"type\": \"%s\", \"%s\": %s%s%s } ] }`\n", moduleName.chars, jsonKey.chars, value ? "\"" : "", value ? value : "true", value ? "\"" : "");
|
||||
fputs(" See <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration> for more information.\n", stderr);
|
||||
exit(477);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME, ':'))
|
||||
ffPrepareCPUUsage();
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME))
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
|
||||
ffInitDiskIOOptions(&options);
|
||||
ffPrepareDiskIO(&options);
|
||||
}
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
|
||||
ffInitNetIOOptions(&options);
|
||||
ffPrepareNetIO(&options);
|
||||
}
|
||||
|
||||
if(instance.config.general.multithreading)
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME, ':'))
|
||||
{
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
}
|
||||
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
}
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
}
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@ typedef struct FFdata
|
||||
void ffPrepareCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
bool ffParseModuleOptions(const char* key, const char* value);
|
||||
|
||||
+56
-3
@@ -162,14 +162,67 @@ bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result)
|
||||
return ffDBusGetUint(dbus, &subIter, result);
|
||||
}
|
||||
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg)
|
||||
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int32_t* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
|
||||
if(argType == DBUS_TYPE_INT16)
|
||||
{
|
||||
int16_t value = 0;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
|
||||
*result = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType == DBUS_TYPE_INT32)
|
||||
{
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType == DBUS_TYPE_BYTE)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
|
||||
*result = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType == DBUS_TYPE_UINT16)
|
||||
{
|
||||
uint16_t value = 0;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
|
||||
*result = (int16_t) value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType == DBUS_TYPE_UINT32)
|
||||
{
|
||||
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(argType != DBUS_TYPE_VARIANT)
|
||||
return false;
|
||||
|
||||
DBusMessageIter subIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
|
||||
return ffDBusGetInt(dbus, &subIter, result);
|
||||
}
|
||||
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg1, const char* arg2)
|
||||
{
|
||||
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
|
||||
if(message == NULL)
|
||||
return NULL;
|
||||
|
||||
if (arg)
|
||||
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
|
||||
if (arg1)
|
||||
{
|
||||
if (arg2)
|
||||
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg1, DBUS_TYPE_STRING, &arg2, DBUS_TYPE_INVALID);
|
||||
else
|
||||
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg1, DBUS_TYPE_INVALID);
|
||||
}
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, NULL);
|
||||
|
||||
|
||||
+3
-2
@@ -31,14 +31,15 @@ const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); //Returns an
|
||||
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
|
||||
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
|
||||
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result);
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg);
|
||||
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg1, const char* arg2);
|
||||
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
|
||||
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int32_t* result);
|
||||
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result);
|
||||
|
||||
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface)
|
||||
{
|
||||
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface);
|
||||
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface, NULL);
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -192,6 +194,21 @@ void ffFontInitValues(FFfont* font, const char* name, const char* size)
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
if (name) ffStrbufInitMove(&font->name, name);
|
||||
if (size) ffStrbufInitMove(&font->size, size);
|
||||
if (style)
|
||||
{
|
||||
FFstrbuf* styleBuf = FF_LIST_ADD(FFstrbuf, font->styles);
|
||||
ffStrbufInitMove(styleBuf, style);
|
||||
}
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName)
|
||||
{
|
||||
const char* pspace = strrchr(rawName, ' ');
|
||||
|
||||
@@ -15,6 +15,7 @@ void ffFontInit(FFfont* font);
|
||||
void ffFontInitQt(FFfont* font, const char* data);
|
||||
void ffFontInitPango(FFfont* font, const char* data);
|
||||
void ffFontInitValues(FFfont* font, const char* name, const char* size);
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style);
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName);
|
||||
void ffFontDestroy(FFfont* font);
|
||||
|
||||
|
||||
+2
-2
@@ -32,10 +32,10 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
ffStrbufAppend(buffer, (const FFstrbuf*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_FLOAT:
|
||||
ffStrbufAppendDouble(buffer, *(float*)formatarg->value, instance.config.display.fractionNdigits);
|
||||
ffStrbufAppendDouble(buffer, *(float*)formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_DOUBLE:
|
||||
ffStrbufAppendDouble(buffer, *(double*)formatarg->value, instance.config.display.fractionNdigits);
|
||||
ffStrbufAppendDouble(buffer, *(double*)formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_BOOL:
|
||||
ffStrbufAppendS(buffer, *(bool*)formatarg->value ? "true" : "false");
|
||||
|
||||
@@ -11,7 +11,7 @@ bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result)
|
||||
|
||||
if (ndigits >= 0)
|
||||
{
|
||||
ffStrbufAppendDouble(result, mhz / 1000., ndigits);
|
||||
ffStrbufAppendDouble(result, mhz / 1000., ndigits, true);
|
||||
if (spaceBeforeUnit) ffStrbufAppendC(result, ' ');
|
||||
ffStrbufAppendS(result, "GHz");
|
||||
}
|
||||
|
||||
+15
-12
@@ -30,6 +30,7 @@ static void initState(FFstate* state)
|
||||
ffPlatformInit(&state->platform);
|
||||
state->configDoc = NULL;
|
||||
state->resultDoc = NULL;
|
||||
state->dynamicInterval = 0;
|
||||
|
||||
{
|
||||
// don't enable bright color if the terminal is in light mode
|
||||
@@ -48,7 +49,7 @@ static void defaultConfig(void)
|
||||
|
||||
void ffInitInstance(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendat>
|
||||
setlocale(LC_ALL, ".UTF8");
|
||||
#else
|
||||
@@ -74,6 +75,9 @@ static void resetConsole(void)
|
||||
#if defined(_WIN32)
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if(instance.state.dynamicInterval > 0)
|
||||
fputs("\033[?1049l", stdout); // Disable alternate buffer
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -88,10 +92,6 @@ static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
static void chldSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
{
|
||||
// empty; used to interrupt the poll and read syscalls
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffStart(void)
|
||||
@@ -117,7 +117,10 @@ void ffStart(void)
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
sigaction(SIGCHLD, &(struct sigaction) { .sa_handler = chldSignalHandler }, NULL);
|
||||
sigset_t newmask;
|
||||
sigemptyset(&newmask);
|
||||
sigaddset(&newmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &newmask, NULL);
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
@@ -130,14 +133,17 @@ void ffStart(void)
|
||||
if(ffDisableLinewrap)
|
||||
fputs("\033[?7l", stdout);
|
||||
|
||||
if(instance.state.dynamicInterval > 0)
|
||||
{
|
||||
fputs("\033[?1049h\033[H", stdout); // Enable alternate buffer
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
ffLogoPrint();
|
||||
}
|
||||
|
||||
void ffFinish(void)
|
||||
{
|
||||
if(instance.config.logo.printRemaining)
|
||||
ffLogoPrintRemaining();
|
||||
|
||||
resetConsole();
|
||||
}
|
||||
|
||||
@@ -208,9 +214,6 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_ZLIB
|
||||
"zlib\n"
|
||||
#endif
|
||||
#if FF_HAVE_XFCONF
|
||||
"xfconf\n"
|
||||
#endif
|
||||
#if FF_HAVE_SQLITE3
|
||||
"sqlite3\n"
|
||||
#endif
|
||||
|
||||
+23
-6
@@ -83,6 +83,13 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
FF_C_NONNULL(2, 3)
|
||||
bool ffAppendFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer);
|
||||
|
||||
FF_C_NONNULL(2)
|
||||
static inline bool ffReadFDBuffer(FFNativeFD fd, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufClear(buffer);
|
||||
return ffAppendFDBuffer(fd, buffer);
|
||||
}
|
||||
|
||||
FF_C_NONNULL(1, 2)
|
||||
static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
@@ -171,19 +178,27 @@ static inline void ffUnsuppressIO(bool* suppressed)
|
||||
|
||||
void ffListFilesRecursively(const char* path, bool pretty);
|
||||
|
||||
static inline bool ffIsValidNativeFD(FFNativeFD fd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return fd >= 0;
|
||||
#else
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
return fd != INVALID_HANDLE_VALUE && fd != NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
FF_C_NONNULL(1)
|
||||
static inline bool wrapClose(FFNativeFD* pfd)
|
||||
{
|
||||
assert(pfd);
|
||||
|
||||
#ifndef WIN32
|
||||
if (*pfd < 0)
|
||||
return false;
|
||||
if (!ffIsValidNativeFD(*pfd))
|
||||
return false;
|
||||
|
||||
#ifndef _WIN32
|
||||
close(*pfd);
|
||||
#else
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
if (*pfd == NULL || *pfd == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
CloseHandle(*pfd);
|
||||
#endif
|
||||
|
||||
@@ -241,8 +256,10 @@ static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char*
|
||||
}
|
||||
|
||||
FFNativeFD ffGetNullFD(void);
|
||||
bool ffRemoveFile(const char* fileName);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Only O_RDONLY is supported
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory);
|
||||
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory);
|
||||
#endif
|
||||
|
||||
+20
-11
@@ -15,11 +15,8 @@
|
||||
|
||||
#if FF_HAVE_WORDEXP
|
||||
#include <wordexp.h>
|
||||
#elif FF_HAVE_GLOB
|
||||
#warning "<wordexp.h> is not available, use <glob.h> instead"
|
||||
#include <glob.h>
|
||||
#else
|
||||
#warning "Neither <wordexp.h> nor <glob.h> is available"
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
@@ -136,14 +133,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 +151,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);
|
||||
@@ -367,3 +371,8 @@ FFNativeFD ffGetNullFD(void)
|
||||
hNullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
bool ffRemoveFile(const char* fileName)
|
||||
{
|
||||
return unlink(fileName) == 0;
|
||||
}
|
||||
|
||||
+40
-18
@@ -3,8 +3,8 @@
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "util/windows/nt.h"
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
@@ -102,31 +102,48 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
return ffAppendFDBuffer(handle, buffer);
|
||||
}
|
||||
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
|
||||
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
UNICODE_STRING fileNameW;
|
||||
ret = RtlAnsiStringToUnicodeString(&fileNameW, &(ANSI_STRING) {
|
||||
.Length = (USHORT) strlen(fileName),
|
||||
.Buffer = (PCHAR) fileName
|
||||
}, TRUE);
|
||||
if (!NT_SUCCESS(ret)) return INVALID_HANDLE_VALUE;
|
||||
assert(fileNameLen <= 0x7FFF);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hFile;
|
||||
HANDLE hFile;
|
||||
IO_STATUS_BLOCK iosb = {};
|
||||
ret = NtOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
|
||||
.Length = sizeof(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = dfd,
|
||||
.ObjectName = &fileNameW,
|
||||
}, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE));
|
||||
RtlFreeUnicodeString(&fileNameW);
|
||||
|
||||
if(!NT_SUCCESS(ret) || iosb.Information != FILE_OPENED)
|
||||
if(!NT_SUCCESS(NtOpenFile(&hFile,
|
||||
(directory ? FILE_LIST_DIRECTORY | FILE_TRAVERSE : FILE_READ_DATA | FILE_READ_EA) | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
|
||||
.Length = sizeof(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = dfd,
|
||||
.ObjectName = &(UNICODE_STRING) {
|
||||
.Buffer = (PWSTR) fileName,
|
||||
.Length = fileNameLen * (USHORT) sizeof(wchar_t),
|
||||
.MaximumLength = (fileNameLen + 1) * (USHORT) sizeof(wchar_t),
|
||||
},
|
||||
.Attributes = OBJ_CASE_INSENSITIVE,
|
||||
},
|
||||
&iosb,
|
||||
FILE_SHARE_READ | (directory ? FILE_SHARE_WRITE | FILE_SHARE_DELETE : 0),
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE)
|
||||
)))
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
return hFile;
|
||||
}
|
||||
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
|
||||
{
|
||||
wchar_t fileNameW[MAX_PATH];
|
||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName, -1, fileNameW, ARRAY_SIZE(fileNameW));
|
||||
if (len == 0) return INVALID_HANDLE_VALUE;
|
||||
// Implies `fileNameW[len] = L'\0';` and `len` includes the null terminator
|
||||
|
||||
for (int i = 0; i < len - 1; ++i)
|
||||
{
|
||||
if (fileNameW[i] == L'/')
|
||||
fileNameW[i] = L'\\';
|
||||
}
|
||||
|
||||
return openatW(dfd, fileNameW, (uint16_t)(len - 1), directory);
|
||||
}
|
||||
|
||||
bool ffAppendFileBufferRelative(HANDLE dfd, const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false);
|
||||
@@ -371,3 +388,8 @@ FFNativeFD ffGetNullFD(void)
|
||||
});
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
bool ffRemoveFile(const char* fileName)
|
||||
{
|
||||
return DeleteFileA(fileName) != FALSE;
|
||||
}
|
||||
|
||||
@@ -158,6 +158,16 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
ffPrepareCPUUsage();
|
||||
break;
|
||||
}
|
||||
case 'c': case 'C': {
|
||||
if (ffStrEqualsIgnCase(type, FF_COMMAND_MODULE_NAME))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyCommandOptions))) FFCommandOptions options;
|
||||
ffInitCommandOptions(&options);
|
||||
if (module) ffCommandModuleInfo.parseJsonObject(&options, module);
|
||||
ffPrepareCommand(&options);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd': case 'D': {
|
||||
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME))
|
||||
{
|
||||
|
||||
@@ -89,7 +89,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
|
||||
|
||||
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
|
||||
uint32_t minMetric = UINT32_MAX;
|
||||
int routeCount = 0;
|
||||
FF_MAYBE_UNUSED int routeCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -299,7 +299,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
|
||||
|
||||
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
|
||||
uint32_t minMetric = UINT32_MAX;
|
||||
int routeCount = 0;
|
||||
FF_MAYBE_UNUSED int routeCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
||||
+7
-1
@@ -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;
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
+25
-4
@@ -2,13 +2,30 @@
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h> // pid_t
|
||||
#endif
|
||||
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr);
|
||||
typedef struct FFProcessHandle {
|
||||
#if _WIN32
|
||||
void* pid; // HANDLE
|
||||
void* pipeRead; // HANDLE
|
||||
#else
|
||||
pid_t pid;
|
||||
int pipeRead;
|
||||
#endif
|
||||
} FFProcessHandle;
|
||||
|
||||
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle);
|
||||
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer); // Destroys handle internally
|
||||
|
||||
static inline const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
|
||||
{
|
||||
const char* error = ffProcessAppendOutput(buffer, argv, false);
|
||||
FFProcessHandle handle;
|
||||
const char* error = ffProcessSpawn(argv, false, &handle);
|
||||
if (error) return error;
|
||||
|
||||
error = ffProcessReadOutput(&handle, buffer);
|
||||
if (!error)
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
return error;
|
||||
@@ -16,7 +33,11 @@ static inline const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const ar
|
||||
|
||||
static inline const char* ffProcessAppendStdErr(FFstrbuf* buffer, char* const argv[])
|
||||
{
|
||||
const char* error = ffProcessAppendOutput(buffer, argv, true);
|
||||
FFProcessHandle handle;
|
||||
const char* error = ffProcessSpawn(argv, true, &handle);
|
||||
if (error) return error;
|
||||
|
||||
error = ffProcessReadOutput(&handle, buffer);
|
||||
if (!error)
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
return error;
|
||||
|
||||
@@ -58,11 +58,9 @@ static inline int ffPipe2(int* fds, int flags)
|
||||
|
||||
|
||||
// Not thread-safe
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle)
|
||||
{
|
||||
int pipes[2];
|
||||
const int timeout = instance.config.general.processingTimeout;
|
||||
|
||||
if(ffPipe2(pipes, O_CLOEXEC) == -1)
|
||||
return "pipe() failed";
|
||||
|
||||
@@ -146,7 +144,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
|
||||
if(childPid == 0)
|
||||
{
|
||||
//Child
|
||||
// Child process
|
||||
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
putenv("LANG=C.UTF-8");
|
||||
@@ -157,11 +155,24 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
#endif
|
||||
|
||||
close(pipes[1]);
|
||||
outHandle->pid = childPid;
|
||||
outHandle->pipeRead = pipes[0];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
{
|
||||
assert(handle->pipeRead != -1);
|
||||
assert(handle->pid != -1);
|
||||
|
||||
const int32_t timeout = instance.config.general.processingTimeout;
|
||||
FF_AUTO_CLOSE_FD int childPipeFd = handle->pipeRead;
|
||||
pid_t childPid = handle->pid;
|
||||
handle->pipeRead = -1;
|
||||
handle->pid = -1;
|
||||
char str[FF_PIPE_BUFSIZ];
|
||||
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
if (timeout >= 0)
|
||||
{
|
||||
@@ -173,30 +184,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (pollret < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
{
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error";
|
||||
}
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
else if (pollret < 0 || (pollfd.revents & POLLERR))
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error";
|
||||
return pollret < 0
|
||||
? "poll(&pollfd, 1, timeout) error: pollret < 0"
|
||||
: "poll(&pollfd, 1, timeout) error: pollfd.revents & POLLERR";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,20 +205,15 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (!WIFEXITED(stat_loc))
|
||||
return "child process exited abnormally";
|
||||
if (WEXITSTATUS(stat_loc) == 127)
|
||||
return "command was not found";
|
||||
return "command not found";
|
||||
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else if (nRead < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
return NULL;
|
||||
else
|
||||
break;
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
|
||||
}
|
||||
@@ -284,6 +273,10 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
||||
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSetS(exePath, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "common/processing.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
@@ -45,12 +45,13 @@ static void argvToCmdline(char* const argv[], FFstrbuf* result)
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle)
|
||||
{
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
const int32_t timeout = instance.config.general.processingTimeout;
|
||||
|
||||
wchar_t pipeName[32];
|
||||
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u", GetCurrentProcessId());
|
||||
static unsigned pidCounter = 0;
|
||||
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u-%u", GetCurrentProcessId(), ++pidCounter);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
||||
pipeName,
|
||||
@@ -82,52 +83,67 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
return "CreateFileW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed";
|
||||
|
||||
PROCESS_INFORMATION piProcInfo = {};
|
||||
|
||||
BOOL success;
|
||||
|
||||
STARTUPINFOA siStartInfo = {
|
||||
.cb = sizeof(siStartInfo),
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
};
|
||||
if (useStdErr)
|
||||
{
|
||||
STARTUPINFOA siStartInfo = {
|
||||
.cb = sizeof(siStartInfo),
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
};
|
||||
if (useStdErr)
|
||||
{
|
||||
siStartInfo.hStdOutput = ffGetNullFD();
|
||||
siStartInfo.hStdError = hChildPipeWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
siStartInfo.hStdOutput = hChildPipeWrite;
|
||||
siStartInfo.hStdError = ffGetNullFD();
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
|
||||
argvToCmdline(argv, &cmdline);
|
||||
|
||||
success = CreateProcessA(
|
||||
NULL, // application name
|
||||
cmdline.chars, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo // receives PROCESS_INFORMATION
|
||||
);
|
||||
siStartInfo.hStdOutput = ffGetNullFD();
|
||||
siStartInfo.hStdError = hChildPipeWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
siStartInfo.hStdOutput = hChildPipeWrite;
|
||||
siStartInfo.hStdError = ffGetNullFD();
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
|
||||
argvToCmdline(argv, &cmdline);
|
||||
|
||||
BOOL success = CreateProcessA(
|
||||
NULL, // application name
|
||||
cmdline.chars, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo // receives PROCESS_INFORMATION
|
||||
);
|
||||
|
||||
CloseHandle(hChildPipeWrite);
|
||||
if(!success)
|
||||
{
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
return "command not found";
|
||||
return "CreateProcessA() failed";
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hProcess = piProcInfo.hProcess;
|
||||
FF_MAYBE_UNUSED FF_AUTO_CLOSE_FD HANDLE hThread = piProcInfo.hThread;
|
||||
CloseHandle(piProcInfo.hThread); // we don't need the thread handle
|
||||
outHandle->pid = piProcInfo.hProcess;
|
||||
outHandle->pipeRead = hChildPipeRead;
|
||||
hChildPipeRead = INVALID_HANDLE_VALUE; // ownership transferred, don't close it
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
{
|
||||
assert(handle->pipeRead != INVALID_HANDLE_VALUE);
|
||||
assert(handle->pid != INVALID_HANDLE_VALUE);
|
||||
|
||||
int32_t timeout = instance.config.general.processingTimeout;
|
||||
FF_AUTO_CLOSE_FD HANDLE hProcess = handle->pid;
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = handle->pipeRead;
|
||||
handle->pid = INVALID_HANDLE_VALUE;
|
||||
handle->pipeRead = INVALID_HANDLE_VALUE;
|
||||
|
||||
char str[FF_PIPE_BUFSIZ];
|
||||
DWORD nRead = 0;
|
||||
OVERLAPPED overlapped = { };
|
||||
OVERLAPPED overlapped = {};
|
||||
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
|
||||
do
|
||||
{
|
||||
@@ -164,7 +180,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
break;
|
||||
|
||||
case ERROR_BROKEN_PIPE:
|
||||
return NULL;
|
||||
goto exit;
|
||||
|
||||
default:
|
||||
CancelIo(hChildPipeRead);
|
||||
@@ -175,6 +191,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
ffStrbufAppendNS(buffer, nRead, str);
|
||||
} while (nRead > 0);
|
||||
|
||||
exit:
|
||||
{
|
||||
DWORD exitCode = 0;
|
||||
if (GetExitCodeProcess(hProcess, &exitCode) && exitCode != STILL_ACTIVE && exitCode != 0)
|
||||
return "Child process exited with an error";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+126
-52
@@ -184,7 +184,7 @@ FFvariant ffSettingsGetDConf(const char* key, FFvarianttype type)
|
||||
}
|
||||
#endif //FF_HAVE_DCONF
|
||||
|
||||
FFvariant ffSettingsGet(const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type)
|
||||
FFvariant ffSettingsGetGnome(const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type)
|
||||
{
|
||||
FFvariant gsettings = ffSettingsGetGSettings(gsettingsSchemaName, gsettingsPath, gsettingsKey, type);
|
||||
|
||||
@@ -196,77 +196,151 @@ FFvariant ffSettingsGet(const char* dconfKey, const char* gsettingsSchemaName, c
|
||||
return ffSettingsGetDConf(dconfKey, type);
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_XFCONF
|
||||
#include <xfconf/xfconf.h>
|
||||
|
||||
typedef struct XFConfData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(xfconf_channel_get)
|
||||
FF_LIBRARY_SYMBOL(xfconf_channel_has_property)
|
||||
FF_LIBRARY_SYMBOL(xfconf_channel_get_string)
|
||||
FF_LIBRARY_SYMBOL(xfconf_channel_get_bool)
|
||||
FF_LIBRARY_SYMBOL(xfconf_channel_get_int)
|
||||
FF_LIBRARY_SYMBOL(xfconf_init)
|
||||
|
||||
bool inited;
|
||||
} XFConfData;
|
||||
|
||||
static const XFConfData* getXFConfData(void)
|
||||
{
|
||||
static XFConfData data;
|
||||
|
||||
if (!data.inited)
|
||||
{
|
||||
data.inited = true;
|
||||
FF_LIBRARY_LOAD(libxfconf, NULL, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_channel_get, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_channel_has_property, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_channel_get_string, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_channel_get_bool, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_channel_get_int, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_init, NULL)
|
||||
if(!data.ffxfconf_init(NULL))
|
||||
data.ffxfconf_init = NULL;
|
||||
else
|
||||
libxfconf = NULL;
|
||||
}
|
||||
|
||||
if(!data.ffxfconf_init)
|
||||
return NULL;
|
||||
|
||||
return &data;
|
||||
}
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include "common/dbus.h"
|
||||
|
||||
FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName, FFvarianttype type)
|
||||
{
|
||||
const XFConfData* data = getXFConfData();
|
||||
if(data == NULL)
|
||||
FFDBusData dbus;
|
||||
if (ffDBusLoadData(DBUS_BUS_SESSION, &dbus) != NULL)
|
||||
return FF_VARIANT_NULL;
|
||||
|
||||
XfconfChannel* channel = data->ffxfconf_channel_get(channelName); // Never fails according to documentation but rather returns an empty channel
|
||||
|
||||
if(!data->ffxfconf_channel_has_property(channel, propertyName))
|
||||
DBusMessage* reply = ffDBusGetMethodReply(&dbus, "org.xfce.Xfconf", "/org/xfce/Xfconf", "org.xfce.Xfconf", "GetProperty", channelName, propertyName);
|
||||
if(!reply)
|
||||
return FF_VARIANT_NULL;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!dbus.lib->ffdbus_message_iter_init(reply, &rootIterator))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
|
||||
if(type == FF_VARIANT_TYPE_INT)
|
||||
return (FFvariant) {.intValue = data->ffxfconf_channel_get_int(channel, propertyName, 0)};
|
||||
{
|
||||
int32_t value;
|
||||
if (ffDBusGetInt(&dbus, &rootIterator, &value))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return (FFvariant) { .intValue = value };
|
||||
}
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
|
||||
if(type == FF_VARIANT_TYPE_STRING)
|
||||
return (FFvariant) {.strValue = data->ffxfconf_channel_get_string(channel, propertyName, NULL)};
|
||||
{
|
||||
FFstrbuf value = ffStrbufCreate();
|
||||
if (ffDBusGetString(&dbus, &rootIterator, &value))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return (FFvariant) { .strValue = value.chars }; // Leaks value.chars
|
||||
}
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
|
||||
if(type == FF_VARIANT_TYPE_BOOL)
|
||||
return (FFvariant) {.boolValue = data->ffxfconf_channel_get_bool(channel, propertyName, false), .boolValueSet = true};
|
||||
{
|
||||
bool value;
|
||||
if (ffDBusGetBool(&dbus, &rootIterator, &value))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return (FFvariant) { .boolValue = value, .boolValueSet = true };
|
||||
}
|
||||
}
|
||||
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
#else //FF_HAVE_XFCONF
|
||||
|
||||
#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \
|
||||
{ \
|
||||
if(!(dbus).lib->ffdbus_message_iter_next(iterator)) \
|
||||
break; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
FFvariant ffSettingsGetXFConfFirstMatch(const char* channelName, const char* propertyPrefix, FFvarianttype type, void* data, FFTestXfconfPropCallback* cb)
|
||||
{
|
||||
FFDBusData dbus;
|
||||
if (ffDBusLoadData(DBUS_BUS_SESSION, &dbus) != NULL)
|
||||
return FF_VARIANT_NULL;
|
||||
|
||||
DBusMessage* reply = ffDBusGetMethodReply(&dbus, "org.xfce.Xfconf", "/org/xfce/Xfconf", "org.xfce.Xfconf", "GetAllProperties", channelName, propertyPrefix);
|
||||
if(!reply)
|
||||
return FF_VARIANT_NULL;
|
||||
|
||||
DBusMessageIter rootIterator;
|
||||
if(!dbus.lib->ffdbus_message_iter_init(reply, &rootIterator))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
|
||||
DBusMessageIter arrayIterator;
|
||||
dbus.lib->ffdbus_message_iter_recurse(&rootIterator, &arrayIterator);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(dbus.lib->ffdbus_message_iter_get_arg_type(&arrayIterator) != DBUS_TYPE_DICT_ENTRY)
|
||||
FF_DBUS_ITER_CONTINUE(dbus, &arrayIterator)
|
||||
|
||||
DBusMessageIter dictIterator;
|
||||
dbus.lib->ffdbus_message_iter_recurse(&arrayIterator, &dictIterator);
|
||||
|
||||
const char* key;
|
||||
dbus.lib->ffdbus_message_iter_get_basic(&dictIterator, &key);
|
||||
|
||||
if (cb(data, key)) FF_DBUS_ITER_CONTINUE(dbus, &arrayIterator)
|
||||
dbus.lib->ffdbus_message_iter_next(&dictIterator);
|
||||
|
||||
if(type == FF_VARIANT_TYPE_INT)
|
||||
{
|
||||
int32_t value;
|
||||
if (ffDBusGetInt(&dbus, &dictIterator, &value))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return (FFvariant) { .intValue = value };
|
||||
}
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
|
||||
if(type == FF_VARIANT_TYPE_STRING)
|
||||
{
|
||||
FFstrbuf value = ffStrbufCreate();
|
||||
if (ffDBusGetString(&dbus, &dictIterator, &value))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return (FFvariant) { .strValue = value.chars }; // Leaks value.chars
|
||||
}
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
|
||||
if(type == FF_VARIANT_TYPE_BOOL)
|
||||
{
|
||||
bool value;
|
||||
if (ffDBusGetBool(&dbus, &dictIterator, &value))
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(reply);
|
||||
return (FFvariant) { .boolValue = value, .boolValueSet = true };
|
||||
}
|
||||
}
|
||||
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
#else //FF_HAVE_DBUS
|
||||
FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName, FFvarianttype type)
|
||||
{
|
||||
FF_UNUSED(channelName, propertyName, type)
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
#endif //FF_HAVE_XFCONF
|
||||
FFvariant ffSettingsGetXFConfFirstMatch(const char* channelName, const char* propertyPrefix, FFvarianttype type, void* data, FFTestXfconfPropCallback* cb)
|
||||
{
|
||||
FF_UNUSED(channelName, propertyPrefix, type, data, cb);
|
||||
return FF_VARIANT_NULL;
|
||||
}
|
||||
#endif //FF_HAVE_DBUS
|
||||
|
||||
#ifdef FF_HAVE_SQLITE3
|
||||
#include <sqlite3.h>
|
||||
|
||||
@@ -24,8 +24,10 @@ typedef union FFvariant
|
||||
|
||||
FFvariant ffSettingsGetDConf(const char* key, FFvarianttype type);
|
||||
FFvariant ffSettingsGetGSettings(const char* schemaName, const char* path, const char* key, FFvarianttype type);
|
||||
FFvariant ffSettingsGet(const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type);
|
||||
FFvariant ffSettingsGetGnome(const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type);
|
||||
FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName, FFvarianttype type);
|
||||
typedef bool FFTestXfconfPropCallback(void* data, const char* propertyName); // Return false to break loop
|
||||
FFvariant ffSettingsGetXFConfFirstMatch(const char* channelName, const char* propertyPrefix, FFvarianttype type, void* data, FFTestXfconfPropCallback* cb);
|
||||
|
||||
int ffSettingsGetSQLite3Int(const char* dbPath, const char* query);
|
||||
bool ffSettingsGetSQLite3String(const char* dbPath, const char* query, FFstrbuf* result);
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ static void appendNum(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
|
||||
if (counter == 0)
|
||||
ffStrbufAppendUInt(result, bytes);
|
||||
else
|
||||
ffStrbufAppendDouble(result, size, (int8_t) options->sizeNdigits);
|
||||
ffStrbufAppendDouble(result, size, (int8_t) options->sizeNdigits, true);
|
||||
if (options->sizeSpaceBeforeUnit != FF_SPACE_BEFORE_UNIT_NEVER)
|
||||
ffStrbufAppendC(result, ' ');
|
||||
ffStrbufAppendS(result, prefixes[counter]);
|
||||
|
||||
+39
-2
@@ -63,6 +63,26 @@
|
||||
},
|
||||
"default": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "json",
|
||||
"short": "j",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"default": false,
|
||||
"optional": true
|
||||
},
|
||||
"desc": "Enable or disable JSON output",
|
||||
"remark": "Shortcut for `--format json`"
|
||||
},
|
||||
{
|
||||
"long": "dynamic-interval",
|
||||
"desc": "Keep fastfetch open and update the output every <num> milliseconds",
|
||||
"remark": "0 (default) to disable the behavior; don't work with --json",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"Config": [
|
||||
@@ -70,7 +90,7 @@
|
||||
"short": "c",
|
||||
"long": "config",
|
||||
"desc": "Specify the config file or preset to load",
|
||||
"remark": "The file will be searched according to the order shown by \"fastfetch --list-config-paths\". Use \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for more info",
|
||||
"remark": "The file will be searched according to the order shown by \"fastfetch --list-config-paths\". Use \"-\" to read config from stdin or \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for more info",
|
||||
"arg": {
|
||||
"type": "config"
|
||||
}
|
||||
@@ -555,7 +575,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"
|
||||
}
|
||||
@@ -846,6 +871,18 @@
|
||||
"default": -1
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "fraction-trailing-zeros",
|
||||
"desc": "Set when to keep trailing zeros",
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"default": "Use the behavior defined internally",
|
||||
"always": "Always keep trailing zeros",
|
||||
"never": "Never keep trailing zeros"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "temp-unit",
|
||||
"desc": "Set the temperature unit",
|
||||
|
||||
@@ -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";
|
||||
|
||||
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen")))
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ static const char* detectBluetooth(FFlist* devices, int32_t connectedCount)
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
|
||||
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL, NULL);
|
||||
if(!managedObjects)
|
||||
return "Failed to call GetManagedObjects";
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const cha
|
||||
char objPath[300];
|
||||
snprintf(objPath, sizeof(objPath), "/org/bluez/%s", hciName);
|
||||
|
||||
DBusMessage* properties = ffDBusGetMethodReply(dbus, "org.bluez", objPath, "org.freedesktop.DBus.Properties", "GetAll", "org.bluez.Adapter1");
|
||||
DBusMessage* properties = ffDBusGetMethodReply(dbus, "org.bluez", objPath, "org.freedesktop.DBus.Properties", "GetAll", "org.bluez.Adapter1", NULL);
|
||||
if(!properties)
|
||||
return "Failed to call org.freedesktop.DBus.Properties.GetAll";
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -123,65 +123,100 @@ 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 kIOI2CNoTransactionType;
|
||||
|
||||
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);
|
||||
|
||||
if (types) {
|
||||
if ((1 << kIOI2CDDCciReplyTransactionType) & (uint64_t) types)
|
||||
return kIOI2CDDCciReplyTransactionType;
|
||||
if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types)
|
||||
return kIOI2CSimpleTransactionType;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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) 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)
|
||||
{
|
||||
IOObjectRelease(interface);
|
||||
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0)
|
||||
continue;
|
||||
|
||||
for (IOItemCount bus = 0; bus < count; ++bus)
|
||||
{
|
||||
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 = NULL;
|
||||
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS)
|
||||
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 = transactionType,
|
||||
.replyBytes = ARRAY_SIZE(i2cOut),
|
||||
.replyBuffer = (vm_address_t) i2cOut,
|
||||
};
|
||||
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
|
||||
IOI2CInterfaceClose(connect, kNilOptions);
|
||||
|
||||
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess || request.replyBytes < 10) continue;
|
||||
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue;
|
||||
|
||||
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;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ static const char* detectWithBacklight(FFlist* result)
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufSubstrBeforeLastC(&backlightDir, '/');
|
||||
ffStrbufAppendS(&backlightDir, "/device");
|
||||
ffStrbufInitA(&brightness->name, PATH_MAX + 1);
|
||||
ffStrbufInitA(&brightness->name, PATH_MAX);
|
||||
if(realpath(backlightDir.chars, brightness->name.chars))
|
||||
{
|
||||
ffStrbufRecalculateLength(&brightness->name);
|
||||
|
||||
@@ -8,7 +8,8 @@ typedef struct FFBtrfsDiskUsage
|
||||
uint64_t total;
|
||||
uint64_t used;
|
||||
const char* type;
|
||||
bool dup;
|
||||
const char* profile; // single / dup / raidx
|
||||
uint8_t copies;
|
||||
} FFBtrfsDiskUsage;
|
||||
|
||||
typedef struct FFBtrfsResult
|
||||
|
||||
@@ -73,20 +73,40 @@ static const char* detectAllocation(FFBtrfsResult* item, int dfd, FFstrbuf* buff
|
||||
item->globalReservationUsed = ffStrbufToUInt(buffer, 0);
|
||||
item->globalReservationUsed = item->globalReservationTotal - item->globalReservationUsed;
|
||||
|
||||
#define FF_BTRFS_DETECT_TYPE(index, _type) \
|
||||
if (ffReadFileBufferRelative(subfd, #_type "/total_bytes", buffer)) \
|
||||
item->allocation[index].total = ffStrbufToUInt(buffer, 0); \
|
||||
\
|
||||
if (ffReadFileBufferRelative(subfd, #_type "/bytes_used", buffer)) \
|
||||
item->allocation[index].used = ffStrbufToUInt(buffer, 0); \
|
||||
\
|
||||
item->allocation[index].dup = faccessat(subfd, #_type "/dup/", F_OK, 0) == 0; \
|
||||
\
|
||||
item->allocation[index].type = #_type;
|
||||
#define FF_BTRFS_DETECT_PROFILE(_index, _type, _profile, _copies) \
|
||||
else if (faccessat(subfd, _type "/" _profile "/", F_OK, 0) == 0) { \
|
||||
item->allocation[_index].profile = _profile; \
|
||||
item->allocation[_index].copies = _copies; \
|
||||
}
|
||||
|
||||
FF_BTRFS_DETECT_TYPE(0, data);
|
||||
FF_BTRFS_DETECT_TYPE(1, metadata);
|
||||
FF_BTRFS_DETECT_TYPE(2, system);
|
||||
#define FF_BTRFS_DETECT_TYPE(_index, _type) \
|
||||
do { \
|
||||
item->allocation[_index].type = _type; \
|
||||
if (ffReadFileBufferRelative(subfd, _type "/total_bytes", buffer)) \
|
||||
item->allocation[_index].total = ffStrbufToUInt(buffer, 0); \
|
||||
\
|
||||
if (ffReadFileBufferRelative(subfd, _type "/bytes_used", buffer)) \
|
||||
item->allocation[_index].used = ffStrbufToUInt(buffer, 0); \
|
||||
\
|
||||
if (false) {} \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "single", 1) \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "dup", 2) \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid0", 1) \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1", 2) \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid10", 2) \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c3", 3) \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid1c4", 4) \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid5", 1) /* (n-1)/n */ \
|
||||
FF_BTRFS_DETECT_PROFILE(_index, _type, "raid6", 1) /* (n-2)/n */ \
|
||||
else { \
|
||||
item->allocation[_index].profile = "unknown"; \
|
||||
item->allocation[_index].copies = 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
FF_BTRFS_DETECT_TYPE(0, "data");
|
||||
FF_BTRFS_DETECT_TYPE(1, "metadata");
|
||||
FF_BTRFS_DETECT_TYPE(2, "system");
|
||||
|
||||
#undef FF_BTRFS_DETECT_TYPE
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "common/processing.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "detection/command/command.h"
|
||||
|
||||
typedef struct FFCommandResultBundle
|
||||
{
|
||||
FFProcessHandle handle;
|
||||
const char* error;
|
||||
} FFCommandResultBundle;
|
||||
|
||||
// FIFO, non-thread-safe list of running commands
|
||||
static FFlist commandQueue = {
|
||||
.elementSize = sizeof(FFCommandResultBundle),
|
||||
};
|
||||
|
||||
static const char* spawnProcess(FFCommandOptions* options, FFProcessHandle* handle)
|
||||
{
|
||||
if (options->text.length == 0)
|
||||
return "No command text specified";
|
||||
|
||||
return ffProcessSpawn(options->param.length ? (char* const[]){
|
||||
options->shell.chars,
|
||||
options->param.chars,
|
||||
options->text.chars,
|
||||
NULL
|
||||
} : (char* const[]){
|
||||
options->shell.chars,
|
||||
options->text.chars,
|
||||
NULL
|
||||
}, options->useStdErr, handle);
|
||||
}
|
||||
|
||||
bool ffPrepareCommand(FFCommandOptions* options)
|
||||
{
|
||||
if (!options->parallel) return false;
|
||||
|
||||
FFCommandResultBundle* bundle = ffListAdd(&commandQueue);
|
||||
bundle->error = spawnProcess(options, &bundle->handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* ffDetectCommand(FFCommandOptions* options, FFstrbuf* result)
|
||||
{
|
||||
FFCommandResultBundle bundle = {};
|
||||
if (!options->parallel)
|
||||
bundle.error = spawnProcess(options, &bundle.handle);
|
||||
else if (!ffListShift(&commandQueue, &bundle))
|
||||
return "[BUG] command queue is empty";
|
||||
|
||||
if (bundle.error)
|
||||
return bundle.error;
|
||||
|
||||
bundle.error = ffProcessReadOutput(&bundle.handle, result);
|
||||
if (bundle.error)
|
||||
return bundle.error;
|
||||
|
||||
ffStrbufTrimRightSpace(result);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "modules/command/option.h"
|
||||
|
||||
const char* ffDetectCommand(FFCommandOptions* options, FFstrbuf* result);
|
||||
+35
-63
@@ -132,35 +132,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
#ifdef __linux__
|
||||
#include "common/io/io.h"
|
||||
#include <elf.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#ifndef HWCAP2_SME
|
||||
#define HWCAP2_SME (1UL << 23)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME2
|
||||
#define HWCAP2_SME2 (1UL << 37)
|
||||
#endif
|
||||
#ifndef HWCAP2_CSSC
|
||||
#define HWCAP2_CSSC (1UL << 34)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME2P1
|
||||
#define HWCAP2_SME2P1 (1UL << 38)
|
||||
#endif
|
||||
#ifndef HWCAP2_MOPS
|
||||
#define HWCAP2_MOPS (1UL << 43)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8E4M3
|
||||
#define HWCAP2_F8E4M3 (1UL << 55)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8E5M2
|
||||
#define HWCAP2_F8E5M2 (1UL << 56)
|
||||
#endif
|
||||
#ifndef HWCAP_CMPBR
|
||||
#define HWCAP_CMPBR (1UL << 33)
|
||||
#endif
|
||||
#ifndef HWCAP_FPRCVT
|
||||
#define HWCAP_FPRCVT (1UL << 34)
|
||||
#endif
|
||||
// #include <asm/hwcap.h>
|
||||
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
@@ -188,69 +160,69 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
cpu->march = "unknown";
|
||||
|
||||
// ARMv8-A
|
||||
bool has_fp = (hwcap & HWCAP_FP) != 0;
|
||||
bool has_asimd = (hwcap & HWCAP_ASIMD) != 0;
|
||||
bool has_fp = (hwcap & (1 << 0) /* HWCAP_FP */) != 0;
|
||||
bool has_asimd = (hwcap & (1 << 1) /* HWCAP_ASIMD */) != 0;
|
||||
|
||||
// ARMv8.1-A
|
||||
bool has_atomics = (hwcap & HWCAP_ATOMICS) != 0; // optional from v8.0
|
||||
bool has_crc32 = (hwcap & HWCAP_CRC32) != 0; // optional from v8.0
|
||||
bool has_asimdrdm = (hwcap & HWCAP_ASIMDRDM) != 0; // optional from v8.0
|
||||
bool has_atomics = (hwcap & (1 << 8) /* HWCAP_ATOMICS */) != 0; // optional from v8.0
|
||||
bool has_crc32 = (hwcap & (1 << 7) /* HWCAP_CRC32 */) != 0; // optional from v8.0
|
||||
bool has_asimdrdm = (hwcap & (1 << 12) /* HWCAP_ASIMDRDM */) != 0; // optional from v8.0
|
||||
|
||||
// ARMv8.2-A
|
||||
bool has_fphp = (hwcap & HWCAP_FPHP) != 0; // optional
|
||||
bool has_dcpop = (hwcap & HWCAP_DCPOP) != 0; // DC CVAP, optional from v8.1
|
||||
bool has_fphp = (hwcap & (1 << 9) /* HWCAP_FPHP */) != 0; // optional
|
||||
bool has_dcpop = (hwcap & (1 << 16) /* HWCAP_DCPOP */) != 0; // DC CVAP, optional from v8.1
|
||||
|
||||
// ARMv8.3-A
|
||||
bool has_paca = (hwcap & HWCAP_PACA) != 0; // optional from v8.2
|
||||
bool has_lrcpc = (hwcap & HWCAP_LRCPC) != 0; // optional from v8.2
|
||||
bool has_fcma = (hwcap & HWCAP_FCMA) != 0; // optional from v8.2
|
||||
bool has_jscvt = (hwcap & HWCAP_JSCVT) != 0; // optional from v8.2
|
||||
bool has_paca = (hwcap & (1 << 30) /* HWCAP_PACA */) != 0; // optional from v8.2
|
||||
bool has_lrcpc = (hwcap & (1 << 15) /* HWCAP_LRCPC */) != 0; // optional from v8.2
|
||||
bool has_fcma = (hwcap & (1 << 14) /* HWCAP_FCMA */) != 0; // optional from v8.2
|
||||
bool has_jscvt = (hwcap & (1 << 13) /* HWCAP_JSCVT */) != 0; // optional from v8.2
|
||||
|
||||
// ARMv8.4-A
|
||||
bool has_dit = (hwcap & HWCAP_DIT) != 0; // optional from v8.3
|
||||
bool has_flagm = (hwcap & HWCAP_FLAGM) != 0; // optional from v8.1
|
||||
bool has_ilrcpc = (hwcap & HWCAP_ILRCPC) != 0; // optional from v8.2
|
||||
bool has_dit = (hwcap & (1 << 24) /* HWCAP_DIT */) != 0; // optional from v8.3
|
||||
bool has_flagm = (hwcap & (1 << 27) /* HWCAP_FLAGM */) != 0; // optional from v8.1
|
||||
bool has_ilrcpc = (hwcap & (1 << 26) /* HWCAP_ILRCPC */) != 0; // optional from v8.2
|
||||
|
||||
// ARMv8.5-A
|
||||
bool has_bti = (hwcap2 & HWCAP2_BTI) != 0; // optional from v8.4
|
||||
bool has_sb = (hwcap & HWCAP_SB) != 0; // optional from v8.0
|
||||
bool has_dcpodp = (hwcap2 & HWCAP2_DCPODP) != 0; // optional from v8.1
|
||||
bool has_flagm2 = (hwcap2 & HWCAP2_FLAGM2) != 0; // optional from v8.4
|
||||
bool has_frint = (hwcap2 & HWCAP2_FRINT) != 0; // optional from v8.4
|
||||
bool has_bti = (hwcap2 & (1 << 17) /* HWCAP2_BTI */) != 0; // optional from v8.4
|
||||
bool has_sb = (hwcap & (1 << 29) /* HWCAP_SB */) != 0; // optional from v8.0
|
||||
bool has_dcpodp = (hwcap2 & (1 << 0) /* HWCAP2_DCPODP */) != 0; // optional from v8.1
|
||||
bool has_flagm2 = (hwcap2 & (1 << 7) /* HWCAP2_FLAGM2 */) != 0; // optional from v8.4
|
||||
bool has_frint = (hwcap2 & (1 << 8) /* HWCAP2_FRINT */) != 0; // optional from v8.4
|
||||
|
||||
// ARMv9.0-A
|
||||
bool has_sve2 = (hwcap2 & HWCAP2_SVE2) != 0;
|
||||
bool has_sve2 = (hwcap2 & (1 << 1) /* HWCAP2_SVE2 */) != 0;
|
||||
|
||||
// ARMv9.1-A
|
||||
// ARMv8.6-A
|
||||
bool has_bf16 = (hwcap2 & HWCAP2_BF16) != 0; // optional from v8.2
|
||||
bool has_i8mm = (hwcap2 & HWCAP2_I8MM) != 0; // optional from v8.1
|
||||
bool has_bf16 = (hwcap2 & (1 << 14) /* HWCAP2_BF16 */) != 0; // optional from v8.2
|
||||
bool has_i8mm = (hwcap2 & (1 << 13) /* HWCAP2_I8MM */) != 0; // optional from v8.1
|
||||
|
||||
// ARMv8.7-A
|
||||
bool has_afp = (hwcap2 & HWCAP2_AFP) != 0; // optional from v8.6
|
||||
bool has_afp = (hwcap2 & (1 << 20) /* HWCAP2_AFP */) != 0; // optional from v8.6
|
||||
|
||||
// ARMv9.2-A
|
||||
bool has_sme = (hwcap2 & HWCAP2_SME) != 0;
|
||||
bool has_sme = (hwcap2 & (1 << 23) /* HWCAP2_SME */) != 0;
|
||||
|
||||
// ARMv9.3-A
|
||||
bool has_sme2 = (hwcap2 & HWCAP2_SME2) != 0; // optional from v9.2
|
||||
bool has_sme2 = (hwcap2 & (1UL << 37) /* HWCAP2_SME2 */) != 0; // optional from v9.2
|
||||
|
||||
// ARMv8.8-A
|
||||
bool has_mops = (hwcap2 & HWCAP2_MOPS) != 0; // optional from v8.7
|
||||
bool has_mops = (hwcap2 & (1UL << 43) /* HWCAP2_MOPS */) != 0; // optional from v8.7
|
||||
|
||||
// ARMv8.9-A
|
||||
bool has_cssc = (hwcap2 & HWCAP2_CSSC) != 0; // optional from v8.7
|
||||
bool has_cssc = (hwcap2 & (1UL << 34) /* HWCAP2_CSSC */) != 0; // optional from v8.7
|
||||
|
||||
// ARMv9.4-A
|
||||
bool has_sme2p1 = (hwcap2 & HWCAP2_SME2P1) != 0; // optional from v9.2
|
||||
bool has_sme2p1 = (hwcap2 & (1UL << 38) /* HWCAP2_SME2P1 */) != 0; // optional from v9.2
|
||||
|
||||
// ARMv9.5-A
|
||||
bool has_f8e4m3 = (hwcap2 & HWCAP2_F8E4M3) != 0; // optional from v9.2
|
||||
bool has_f8e5m2 = (hwcap2 & HWCAP2_F8E5M2) != 0; // optional from v9.2
|
||||
bool has_f8e4m3 = (hwcap2 & (1UL << 55) /* HWCAP2_F8E4M3 */) != 0; // optional from v9.2
|
||||
bool has_f8e5m2 = (hwcap2 & (1UL << 56) /* HWCAP2_F8E5M2 */) != 0; // optional from v9.2
|
||||
|
||||
// ARMv9.6-A
|
||||
bool has_cmpbr = (hwcap & HWCAP_CMPBR) != 0; // optional from v9.5
|
||||
bool has_fprcvt = (hwcap & HWCAP_FPRCVT) != 0; // optional from v9.5
|
||||
bool has_cmpbr = (hwcap & (1UL << 33) /* HWCAP_CMPBR */) != 0; // optional from v9.5
|
||||
bool has_fprcvt = (hwcap & (1UL << 34) /* HWCAP_FPRCVT */) != 0; // optional from v9.5
|
||||
|
||||
if (has_sve2 || has_sme) {
|
||||
// ARMv9
|
||||
@@ -457,7 +429,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
|
||||
// ARMv8.4-A
|
||||
// My CPU (Apple M1 Pro in VM) does support LSE2, but Windows doesn't detect it for some reason
|
||||
// bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
|
||||
bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
|
||||
bool has_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); // DotProd, optional from v8.1 (*)
|
||||
|
||||
// ARMv9.0-A
|
||||
@@ -503,7 +475,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
cpu->march = "ARMv8.7-A";
|
||||
} else if (has_i8mm && has_bf16) {
|
||||
cpu->march = "ARMv8.6-A";
|
||||
} else if (has_dp) {
|
||||
} else if (has_dp && has_lse2) {
|
||||
cpu->march = "ARMv8.4-A";
|
||||
} else if (has_lrcpc && has_jscvt) {
|
||||
cpu->march = "ARMv8.3-A";
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef struct FFCPUResult
|
||||
uint16_t coresPhysical;
|
||||
uint16_t coresLogical;
|
||||
uint16_t coresOnline;
|
||||
uint16_t numaNodes;
|
||||
|
||||
uint32_t frequencyBase; // GHz
|
||||
uint32_t frequencyMax; // GHz
|
||||
|
||||
@@ -3,26 +3,34 @@
|
||||
#include "util/apple/smc_temps.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
static double detectCpuTemp(const FFCPUOptions* options, const FFstrbuf* cpuName)
|
||||
{
|
||||
double result = 0;
|
||||
|
||||
const char* error = NULL;
|
||||
if (ffStrbufStartsWithS(cpuName, "Apple M"))
|
||||
{
|
||||
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
|
||||
{
|
||||
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
|
||||
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
|
||||
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
|
||||
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
|
||||
default: error = "Unsupported Apple Silicon CPU";
|
||||
}
|
||||
}
|
||||
else // PPC?
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
|
||||
|
||||
if(error)
|
||||
if (options->tempSensor.length)
|
||||
{
|
||||
error = ffDetectSmcSpecificTemp(options->tempSensor.chars, &result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ffStrbufStartsWithS(cpuName, "Apple M"))
|
||||
{
|
||||
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
|
||||
{
|
||||
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
|
||||
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
|
||||
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
|
||||
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
|
||||
default: error = "Unsupported Apple Silicon CPU";
|
||||
}
|
||||
}
|
||||
else // PPC?
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
|
||||
}
|
||||
|
||||
if (error)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return result;
|
||||
@@ -39,7 +47,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\"";
|
||||
@@ -130,7 +138,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectFrequency(cpu);
|
||||
if (options->showPeCoreCount) detectCoreCount(cpu);
|
||||
|
||||
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
|
||||
cpu->temperature = options->temp ? detectCpuTemp(options, &cpu->name) : FF_CPU_TEMP_UNSET;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -112,8 +112,12 @@ static const char* armPartId2name(uint32_t partId)
|
||||
case 0xd87: return "Cortex-A725";
|
||||
case 0xd88: return "Cortex-A520AE";
|
||||
case 0xd89: return "Cortex-A720AE";
|
||||
case 0xd8a: return "C1-Nano";
|
||||
case 0xd8b: return "C1-Pro";
|
||||
case 0xd8c: return "C1-Ultra";
|
||||
case 0xd8e: return "Neoverse-N3";
|
||||
case 0xd8f: return "Cortex-A320";
|
||||
case 0xd90: return "C1-Premium";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@@ -213,6 +217,7 @@ static const char* nvidiaPartId2name(uint32_t partId)
|
||||
case 0x000: return "Denver";
|
||||
case 0x003: return "Denver 2";
|
||||
case 0x004: return "Carmel";
|
||||
case 0x010: return "Olympus";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+22
-20
@@ -8,22 +8,26 @@
|
||||
#define FF_HAVE_CPUSET 1
|
||||
#endif
|
||||
|
||||
static const char* detectCpuTemp(double* current)
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
|
||||
{
|
||||
int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed";
|
||||
|
||||
// In tenth of degrees Kelvin
|
||||
*current = (double) temp / 10 - 273.15;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectThermalTemp(double* current)
|
||||
{
|
||||
int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed";
|
||||
int temp;
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
temp = ffSysctlGetInt(options->tempSensor.chars, -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(options->tempSensor) failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
{
|
||||
// Thermal zone temperature
|
||||
temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(\"dev.cpu.0.temperature\" or \"hw.acpi.thermal.tz0.temperature\") failed";
|
||||
}
|
||||
}
|
||||
|
||||
// In tenth of degrees Kelvin
|
||||
*current = (double) temp / 10 - 273.15;
|
||||
@@ -94,11 +98,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (detectCpuTemp(&cpu->temperature) != NULL)
|
||||
detectThermalTemp(&cpu->temperature);
|
||||
}
|
||||
if (options->temp) detectCpuTemp(options, &cpu->temperature);
|
||||
|
||||
cpu->numaNodes = (uint16_t) ffSysctlGetInt("vm.ndomains", 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+204
-36
@@ -4,6 +4,7 @@
|
||||
#include "common/properties.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/path.h"
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <stdlib.h>
|
||||
@@ -13,6 +14,22 @@
|
||||
|
||||
#define FF_CPUINFO_PATH "/proc/cpuinfo"
|
||||
|
||||
#ifndef O_PATH
|
||||
#define O_PATH 0
|
||||
#endif
|
||||
|
||||
static double readTempFile(int dfd, const char* filename, FFstrbuf* buffer)
|
||||
{
|
||||
if (filename ? !ffReadFileBufferRelative(dfd, filename, buffer) : !ffReadFDBuffer(dfd, buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET); // millidegree Celsius
|
||||
if (value == FF_CPU_TEMP_UNSET)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return value / 1000.;
|
||||
}
|
||||
|
||||
static double parseTZDir(int dfd, FFstrbuf* buffer)
|
||||
{
|
||||
if (!ffReadFileBufferRelative(dfd, "type", buffer))
|
||||
@@ -26,18 +43,12 @@ static double parseTZDir(int dfd, FFstrbuf* buffer)
|
||||
true
|
||||
) return FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (!ffReadFileBufferRelative(dfd, "temp", buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius
|
||||
if (value == FF_CPU_TEMP_UNSET)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return value / 1000.;
|
||||
return readTempFile(dfd, "temp", buffer);
|
||||
}
|
||||
|
||||
static double parseHwmonDir(int dfd, FFstrbuf* buffer)
|
||||
{
|
||||
//https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||
if (!ffReadFileBufferRelative(dfd, "name", buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
@@ -53,25 +64,64 @@ static double parseHwmonDir(int dfd, FFstrbuf* buffer)
|
||||
true
|
||||
) return FF_CPU_TEMP_UNSET;
|
||||
|
||||
//https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||
if (!ffReadFileBufferRelative(dfd, "temp1_input", buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius
|
||||
if (value == FF_CPU_TEMP_UNSET)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return value / 1000.;
|
||||
return readTempFile(dfd, "temp1_input", buffer);
|
||||
}
|
||||
|
||||
static double detectCPUTemp(void)
|
||||
static double detectCPUTemp(const FFCPUOptions* options)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int subfd = -1;
|
||||
const char* fileName = NULL;
|
||||
if (ffStrbufStartsWithS(&options->tempSensor, "hwmon") && ffCharIsDigit(options->tempSensor.chars[strlen("hwmon")]))
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/hwmon/", O_PATH | O_CLOEXEC);
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp1_input";
|
||||
else
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&options->tempSensor, "thermal_zone") && ffCharIsDigit(options->tempSensor.chars[strlen("thermal_zone")]))
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/thermal/", O_PATH | O_CLOEXEC);
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp";
|
||||
else
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&options->tempSensor, "cputemp.") && ffCharIsDigit(options->tempSensor.chars[strlen("cputemp.")]))
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/platform/", O_PATH | O_CLOEXEC);
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp1_input";
|
||||
else
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
else if (ffIsAbsolutePath(options->tempSensor.chars))
|
||||
{
|
||||
subfd = open(options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp1_input";
|
||||
else
|
||||
subfd = open(options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
if (subfd < 0)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return readTempFile(subfd, fileName, &buffer);
|
||||
}
|
||||
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/hwmon/");
|
||||
if(dirp)
|
||||
{
|
||||
int dfd = dirfd(dirp);
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
@@ -138,6 +188,21 @@ static double detectCPUTemp(void)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
static void detectNumaNodes(FFCPUResult* cpu)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/sys/devices/system/node/");
|
||||
if (!dir) return;
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
if (ffStrStartsWith(entry->d_name, "node") && ffCharIsDigit(entry->d_name[strlen("node")]))
|
||||
cpu->numaNodes++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "common/settings.h"
|
||||
|
||||
@@ -145,11 +210,14 @@ 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;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 8845: name = "8 Gen 5"; break; // ?
|
||||
case 8850: name = "8 Elite Gen 5"; break;
|
||||
case 8735: name = "8s Gen 4"; break;
|
||||
case 8750: name = "8 Elite"; break;
|
||||
case 8635: name = "8s Gen 3"; break;
|
||||
@@ -187,11 +255,13 @@ 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;
|
||||
|
||||
switch (code) // The SOC code of MTK Dimensity series is full of mess
|
||||
{
|
||||
case 6993: name = "9500"; break;
|
||||
case 6991: name = "9400"; break;
|
||||
case 6989:
|
||||
case 8796: name = "9300"; break;
|
||||
@@ -216,25 +286,78 @@ 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)
|
||||
{
|
||||
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);
|
||||
else if (ffStrbufEqualS(&cpu->vendor, "Samsung") && ffStrbufStartsWithS(&cpu->name, "s5e"))
|
||||
{
|
||||
cpu->name.chars[0] = 'S';
|
||||
cpu->name.chars[2] = 'E';
|
||||
detectExynos(cpu);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -353,6 +476,14 @@ static const char* parseCpuInfo(
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "processor 0:", &cpu->name)) ||
|
||||
(cpu->vendor.length == 0 && ffParsePropLine(line, "vendor_id :", &cpu->vendor)) ||
|
||||
(cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz static :", cpuMHz)) || // This one cannot be detected because of early return
|
||||
#elif __ia64__
|
||||
(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)) ||
|
||||
@@ -502,6 +633,8 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
|
||||
if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0)
|
||||
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
|
||||
|
||||
detectNumaNodes(cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -610,19 +743,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__
|
||||
@@ -678,6 +838,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);
|
||||
@@ -699,9 +866,9 @@ FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const c
|
||||
char* pend;
|
||||
unsigned long id = strtoul(p, &pend, 10);
|
||||
if (__builtin_expect(id > 64, false))
|
||||
high |= 1 << (id - 64);
|
||||
high |= 1UL << (id - 64);
|
||||
else
|
||||
low |= 1 << id;
|
||||
low |= 1UL << id;
|
||||
p = pend;
|
||||
}
|
||||
|
||||
@@ -777,6 +944,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
|
||||
detectPhysicalCores(cpu);
|
||||
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
detectNumaNodes(cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -784,7 +952,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
|
||||
cpu->temperature = options->temp ? detectCPUTemp(options) : FF_CPU_TEMP_UNSET;
|
||||
|
||||
#if __x86_64__ || __i386__
|
||||
return detectCPUX86(options, cpu);
|
||||
|
||||
@@ -16,7 +16,7 @@ static void freePropDict(prop_dictionary_t* pdict)
|
||||
prop_object_release(*pdict);
|
||||
}
|
||||
|
||||
static const char* detectCpuTemp(double* current)
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
|
||||
@@ -25,11 +25,21 @@ static const char* detectCpuTemp(double* current)
|
||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
|
||||
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
|
||||
|
||||
prop_array_t array = prop_dictionary_get(root, "coretemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "viac7temp0");
|
||||
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
|
||||
if (!array) return "No temp data found in root dictionary";
|
||||
prop_array_t array;
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
array = prop_dictionary_get(root, options->tempSensor.chars);
|
||||
if (!array) return "No temp data found in specified sensor";
|
||||
}
|
||||
else
|
||||
{
|
||||
array = prop_dictionary_get(root, "coretemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "viac7temp0");
|
||||
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
|
||||
if (!array) return "No temp data found in root dictionary";
|
||||
}
|
||||
|
||||
if (prop_array_count(array) != 2)
|
||||
return "Unexpected `xtemp0` data";
|
||||
@@ -73,7 +83,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp) detectCpuTemp(&cpu->temperature);
|
||||
if (options->temp) detectCpuTemp(options, &cpu->temperature);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/sensors.h>
|
||||
|
||||
static const char* detectCPUTemp(FFCPUResult* cpu)
|
||||
static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
|
||||
|
||||
@@ -23,8 +23,16 @@ static const char* detectCPUTemp(FFCPUResult* cpu)
|
||||
return "sysctl(sensordev) failed";
|
||||
}
|
||||
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu"))
|
||||
continue;
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
if (!ffStrbufEqualS(&options->tempSensor, sensordev.xname))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu"))
|
||||
continue;
|
||||
}
|
||||
|
||||
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
|
||||
{
|
||||
@@ -62,7 +70,7 @@ const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
if (options->temp) detectCPUTemp(cpu);
|
||||
if (options->temp) detectCPUTemp(options, cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
#include "util/stringUtils.h"
|
||||
#include <kstat.h>
|
||||
|
||||
static const char* detectCPUTempByKstat(kstat_ctl_t* kc, FFCPUResult* cpu)
|
||||
static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t* kc, FFCPUResult* cpu)
|
||||
{
|
||||
const char* possibleModules[] = {"temperature", "cpu_temp", "acpi_thermal", NULL};
|
||||
|
||||
if (options->tempSensor.length > 0) {
|
||||
possibleModules[0] = options->tempSensor.chars;
|
||||
possibleModules[1] = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; possibleModules[i] != NULL; i++) {
|
||||
kstat_t* ks = kstat_lookup(kc, possibleModules[i], -1, NULL);
|
||||
if (ks && kstat_read(kc, ks, NULL) >= 0) {
|
||||
@@ -141,7 +146,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (detectCPUTempByKstat(kc, cpu) != NULL)
|
||||
if (detectCPUTempByKstat(options, kc, cpu) != NULL)
|
||||
detectCPUTempByIpmiTool(cpu);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
|
||||
}
|
||||
}
|
||||
|
||||
const char* detectThermalTemp(double* result)
|
||||
const char* detectThermalTemp(const FFCPUOptions* options, double* result)
|
||||
{
|
||||
struct FFPerfQuerySpec
|
||||
{
|
||||
@@ -35,6 +35,14 @@ const char* detectThermalTemp(double* result)
|
||||
.Name = L"\\_TZ.CPUZ", // The standard(?) instance name for CPU temperature in the thermal provider
|
||||
};
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
int written = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, options->tempSensor.chars, (int) options->tempSensor.length, querySpec.Name, (int)(ARRAY_SIZE(querySpec.Name) - 1));
|
||||
if (written == 0)
|
||||
return "Invalid temp sensor string";
|
||||
querySpec.Name[written] = L'\0';
|
||||
}
|
||||
|
||||
DWORD dataSize = 0;
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
|
||||
return "PerfEnumerateCounterSetInstances() failed";
|
||||
@@ -62,6 +70,9 @@ const char* detectThermalTemp(double* result)
|
||||
|
||||
if (dataSize == 0)
|
||||
{
|
||||
if (options->tempSensor.length > 0)
|
||||
return "Unable to find CPU sensor";
|
||||
|
||||
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pHead + sizeof(*pHead));
|
||||
wcscpy(querySpec.Name, instanceName); // Use the first instance name if the specific one is not found
|
||||
}
|
||||
@@ -102,12 +113,16 @@ const char* detectThermalTemp(double* result)
|
||||
if (pCounterData->dwDataSize == sizeof(int32_t))
|
||||
{
|
||||
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
|
||||
int32_t value = *(int32_t*)(pCounterData + 1);
|
||||
if (value == 0)
|
||||
return "Temperature data is zero";
|
||||
|
||||
switch (pCounterIds[iCounter]) {
|
||||
case 0: // Temperature
|
||||
*result = *(int32_t*)(pCounterData + 1) - 273;
|
||||
*result = value - 273;
|
||||
break;
|
||||
case 3: // High Precision Temperature
|
||||
*result = *(int32_t*)(pCounterData + 1) / 10.0 - 273;
|
||||
*result = value / 10.0 - 273;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -226,6 +241,8 @@ static const char* detectNCores(FFCPUResult* cpu)
|
||||
++cpu->coresPhysical;
|
||||
else if (ptr->Relationship == RelationProcessorPackage)
|
||||
++cpu->packages;
|
||||
else if (ptr->Relationship == RelationNumaNode)
|
||||
++cpu->numaNodes;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -238,7 +255,8 @@ static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
||||
|
||||
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||
if (ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL))
|
||||
ffStrbufTrimRightSpace(&cpu->vendor);
|
||||
|
||||
if (cpu->coresLogical == 0)
|
||||
{
|
||||
@@ -294,7 +312,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
|
||||
if(options->temp)
|
||||
detectThermalTemp(&cpu->temperature);
|
||||
detectThermalTemp(options, &cpu->temperature);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result)
|
||||
if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed";
|
||||
|
||||
// macOS provides the global system cache line size
|
||||
uint32_t lineSize = (uint32_t) ffSysctlGetInt("hw.cachelinesize", 0);
|
||||
uint32_t lineSize = (uint32_t) ffSysctlGetInt64("hw.cachelinesize", 0);
|
||||
|
||||
char sysctlKey[128] = "hw.perflevelN.";
|
||||
char* pNum = sysctlKey + strlen("hw.perflevel");
|
||||
|
||||
+25
-26
@@ -1,30 +1,5 @@
|
||||
#include "disk.h"
|
||||
|
||||
bool ffDiskMatchMountpoint(FFstrbuf* folders, const char* mountpoint)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char separator = ';';
|
||||
#else
|
||||
const char separator = ':';
|
||||
#endif
|
||||
|
||||
uint32_t mountpointLength = (uint32_t) strlen(mountpoint);
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < folders->length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(folders, startIndex, separator);
|
||||
|
||||
uint32_t folderLength = colonIndex - startIndex;
|
||||
if (folderLength == mountpointLength && memcmp(folders->chars + startIndex, mountpoint, mountpointLength) == 0)
|
||||
return true;
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
|
||||
{
|
||||
return ffStrbufComp(&disk1->mountpoint, &disk2->mountpoint);
|
||||
@@ -35,7 +10,7 @@ const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
|
||||
const char* error = ffDetectDisksImpl(options, disks);
|
||||
|
||||
if (error) return error;
|
||||
if (disks->length == 0) return "No disks found";
|
||||
if (disks->length == 0) return NULL;
|
||||
|
||||
//We need to sort the disks, so that we can detect, which disk a path resides on
|
||||
// For example for /boot/efi/bootmgr we need to check /boot/efi before /boot
|
||||
@@ -56,3 +31,27 @@ const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <fnmatch.h>
|
||||
|
||||
bool ffDiskMatchesFolderPatterns(FFstrbuf* folders, const char* path, char separator)
|
||||
{
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < folders->length)
|
||||
{
|
||||
uint32_t sepIndex = ffStrbufNextIndexC(folders, startIndex, separator);
|
||||
|
||||
char savedSep = folders->chars[sepIndex]; // Can be '\0' if at end
|
||||
folders->chars[sepIndex] = '\0';
|
||||
|
||||
bool matched = fnmatch(&folders->chars[startIndex], path, 0) == 0;
|
||||
folders->chars[sepIndex] = savedSep;
|
||||
|
||||
if (matched) return true;
|
||||
|
||||
startIndex = sepIndex + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#include "fastfetch.h"
|
||||
#include "modules/disk/option.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FF_DISK_FOLDER_SEPARATOR ';'
|
||||
#else
|
||||
#define FF_DISK_FOLDER_SEPARATOR ':'
|
||||
#endif
|
||||
|
||||
typedef struct FFDisk
|
||||
{
|
||||
FFstrbuf mountFrom;
|
||||
@@ -29,4 +35,7 @@ typedef struct FFDisk
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks /* list of FFDisk */);
|
||||
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks);
|
||||
bool ffDiskMatchMountpoint(FFstrbuf* folders, const char* mountpoint);
|
||||
|
||||
#ifndef _WIN32
|
||||
bool ffDiskMatchesFolderPatterns(FFstrbuf* folders, const char* path, char separator);
|
||||
#endif
|
||||
|
||||
@@ -145,12 +145,18 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
if(__builtin_expect(options->folders.length > 0, 0))
|
||||
{
|
||||
if(!ffDiskMatchMountpoint(&options->folders, fs->f_mntonname))
|
||||
if(!ffStrbufSeparatedContainS(&options->folders, fs->f_mntonname, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(!ffStrEquals(fs->f_mntonname, "/") && !ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs") && !ffStrEquals(fs->f_fstypename, "fusefs.sshfs"))
|
||||
continue;
|
||||
|
||||
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, fs->f_mntonname, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
|
||||
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, fs->f_fstypename, ':'))
|
||||
continue;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
// f_bavail and f_ffree are signed on FreeBSD...
|
||||
if(fs->f_bavail < 0) fs->f_bavail = 0;
|
||||
|
||||
@@ -23,10 +23,16 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, path.Path()))
|
||||
if (!ffStrbufSeparatedContainS(&options->folders, path.Path(), FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, path.Path(), FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
|
||||
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, fs.fsh_name, ':'))
|
||||
continue;
|
||||
|
||||
FFDisk* disk = (FFDisk*) ffListAdd(disks);
|
||||
|
||||
disk->bytesTotal = (uint64_t)fs.total_blocks * (uint64_t) fs.block_size;
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#if defined(STATX_BTIME) && !defined(__ANDROID__)
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef __USE_LARGEFILE64
|
||||
#define stat stat64
|
||||
#define statvfs statvfs64
|
||||
@@ -263,9 +267,9 @@ static void detectStats(FFDisk* disk)
|
||||
}
|
||||
|
||||
disk->createTime = 0;
|
||||
#ifdef FF_HAVE_STATX
|
||||
#ifdef SYS_statx
|
||||
struct statx stx;
|
||||
if (statx(0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME))
|
||||
if (syscall(SYS_statx, 0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec > 685065600 /*birth of Linux*/)
|
||||
disk->createTime = (uint64_t)((stx.stx_btime.tv_sec * 1000) + (stx.stx_btime.tv_nsec / 1000000));
|
||||
#endif
|
||||
|
||||
@@ -287,12 +291,18 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
if (__builtin_expect(options->folders.length > 0, false))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, device->mnt_dir))
|
||||
if (!ffStrbufSeparatedContainS(&options->folders, device->mnt_dir, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(!isPhysicalDevice(device))
|
||||
continue;
|
||||
|
||||
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, device->mnt_dir, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
|
||||
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, device->mnt_type, ':'))
|
||||
continue;
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
disk->type = FF_DISK_VOLUME_TYPE_NONE;
|
||||
|
||||
@@ -113,12 +113,18 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, device.mnt_mountp))
|
||||
if (!ffStrbufSeparatedContainS(&options->folders, device.mnt_mountp, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(!isPhysicalDevice(&device))
|
||||
continue;
|
||||
|
||||
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, device.mnt_mountp, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
|
||||
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, device.mnt_fstype, ':'))
|
||||
continue;
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
disk->type = FF_DISK_VOLUME_TYPE_NONE;
|
||||
|
||||
@@ -47,12 +47,35 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
if (__builtin_expect((long) options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, buffer.chars))
|
||||
if (!ffStrbufSeparatedContain(&options->folders, &buffer, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
continue;
|
||||
|
||||
if (options->hideFolders.length && ffStrbufSeparatedContain(&options->hideFolders, &buffer, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
|
||||
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
|
||||
|
||||
DWORD diskFlags;
|
||||
BOOL volumeInfoAvailable = GetVolumeInformationW(mountpoint,
|
||||
diskName, ARRAY_SIZE(diskName), //Volume name
|
||||
NULL, //Serial number
|
||||
NULL, //Max component length
|
||||
&diskFlags, //File system flags
|
||||
diskFileSystem, ARRAY_SIZE(diskFileSystem)
|
||||
);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY diskFileSystemBuf = ffStrbufCreate();
|
||||
|
||||
if (volumeInfoAvailable)
|
||||
{
|
||||
ffStrbufSetWS(&diskFileSystemBuf, diskFileSystem);
|
||||
if (options->hideFS.length && ffStrbufSeparatedContain(&options->hideFS, &diskFileSystemBuf, ':'))
|
||||
continue;
|
||||
}
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
|
||||
disk->filesUsed = 0;
|
||||
@@ -97,20 +120,9 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
(PULARGE_INTEGER)&disk->bytesFree
|
||||
);
|
||||
|
||||
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
|
||||
|
||||
DWORD diskFlags;
|
||||
BOOL result = GetVolumeInformationW(mountpoint,
|
||||
diskName, ARRAY_SIZE(diskName), //Volume name
|
||||
NULL, //Serial number
|
||||
NULL, //Max component length
|
||||
&diskFlags, //File system flags
|
||||
diskFileSystem, ARRAY_SIZE(diskFileSystem)
|
||||
);
|
||||
|
||||
if(result)
|
||||
if(volumeInfoAvailable)
|
||||
{
|
||||
ffStrbufSetWS(&disk->filesystem, diskFileSystem);
|
||||
ffStrbufInitMove(&disk->filesystem, &diskFileSystemBuf);
|
||||
ffStrbufSetWS(&disk->name, diskName);
|
||||
if(diskFlags & FILE_READ_ONLY_VOLUME)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
|
||||
@@ -45,6 +45,7 @@ FFDisplayResult* ffdsAppendDisplay(
|
||||
display->manufactureYear = 0;
|
||||
display->manufactureWeek = 0;
|
||||
display->serial = 0;
|
||||
display->drrStatus = FF_DISPLAY_DRR_STATUS_UNKNOWN;
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#define FF_WM_PROTOCOL_TTY "TTY"
|
||||
#define FF_WM_PROTOCOL_X11 "X11"
|
||||
#define FF_WM_PROTOCOL_WAYLAND "Wayland"
|
||||
#define FF_WM_PROTOCOL_SURFACEFLINGER "SurfaceFlinger"
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFDisplayType {
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
@@ -59,6 +60,13 @@ typedef enum __attribute__((__packed__)) FFDisplayHdrStatus
|
||||
FF_DISPLAY_HDR_STATUS_ENABLED,
|
||||
} FFDisplayHdrStatus;
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFDisplayVrrStatus
|
||||
{
|
||||
FF_DISPLAY_DRR_STATUS_UNKNOWN,
|
||||
FF_DISPLAY_DRR_STATUS_DISABLED,
|
||||
FF_DISPLAY_DRR_STATUS_ENABLED,
|
||||
} FFDisplayVrrStatus;
|
||||
|
||||
typedef struct FFDisplayResult
|
||||
{
|
||||
uint32_t width; // in px
|
||||
@@ -82,6 +90,7 @@ typedef struct FFDisplayResult
|
||||
uint16_t manufactureYear;
|
||||
uint16_t manufactureWeek;
|
||||
uint32_t serial;
|
||||
FFDisplayVrrStatus drrStatus;
|
||||
} FFDisplayResult;
|
||||
|
||||
typedef struct FFDisplayServerResult
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "displayserver.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/processing.h"
|
||||
#include "linux/displayserver_linux.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -82,13 +83,10 @@ static void detectWithDumpsys(FFDisplayServerResult* ds)
|
||||
|
||||
ffStrbufRecalculateLength(&name);
|
||||
FFDisplayResult* display = ffdsAppendDisplay(ds,
|
||||
(uint32_t)width,
|
||||
(uint32_t)height,
|
||||
(uint32_t)width, (uint32_t)height,
|
||||
refreshRate,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0,
|
||||
0,
|
||||
&name,
|
||||
@@ -121,13 +119,10 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
|
||||
ffStrbufSubstrAfterFirstC(&buffer, ',');
|
||||
double scaleFactor = (double) ffStrbufToUInt(&buffer, 0) / 160.;
|
||||
FFDisplayResult* display = ffdsAppendDisplay(ds,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
(uint32_t) (width / scaleFactor + .5),
|
||||
(uint32_t) (height / scaleFactor + .5),
|
||||
0,
|
||||
width, height,
|
||||
0,
|
||||
(uint32_t) (width / scaleFactor + .5), (uint32_t) (height / scaleFactor + .5),
|
||||
0, 0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
@@ -145,11 +140,79 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool detectDE(FFDisplayServerResult* ds)
|
||||
{
|
||||
if (ffSettingsGetAndroidProperty("ro.vivo.os.build.display.id", &ds->dePrettyName)) // OriginOS 6
|
||||
{
|
||||
ffStrbufAppendC(&ds->dePrettyName, ' ');
|
||||
ffSettingsGetAndroidProperty("ro.vivo.product.version", &ds->dePrettyName); // PD2505D_xxx
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.build.version.magic", &ds->dePrettyName) ||
|
||||
ffSettingsGetAndroidProperty("ro.build.version.emui", &ds->dePrettyName))
|
||||
{
|
||||
ffStrbufReplaceAllC(&ds->dePrettyName, '_', ' ');
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.mi.os.version.name", &ds->dePrettyName))
|
||||
{
|
||||
// MiUI like
|
||||
ffStrbufClear(&ds->dePrettyName);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.incremental", &ds->dePrettyName); // Detail version number
|
||||
if (ffStrbufStartsWithS(&ds->dePrettyName, "OS"))
|
||||
{
|
||||
ds->dePrettyName.chars[0] = 'S';
|
||||
ds->dePrettyName.chars[1] = ' ';
|
||||
ffStrbufPrependS(&ds->dePrettyName, "HyperO");
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&ds->dePrettyName, "V"))
|
||||
{
|
||||
ds->dePrettyName.chars[0] = ' ';
|
||||
ffStrbufPrependS(&ds->dePrettyName, "MiUI");
|
||||
}
|
||||
else
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "MiUI");
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.build.version.oplusrom", &ds->dePrettyName))
|
||||
{
|
||||
if (ffStrbufStartsWithS(&ds->dePrettyName, "V"))
|
||||
ffStrbufSubstrAfter(&ds->dePrettyName, 0);
|
||||
ffStrbufPrependS(&ds->dePrettyName, "ColorOS");
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.oxygen.version", &ds->dePrettyName))
|
||||
{
|
||||
ffStrbufPrependS(&ds->dePrettyName, "OxygenOS");
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.build.display.id", &ds->dePrettyName) && ffStrbufStartsWithS(&ds->dePrettyName, "RedMagicOS"))
|
||||
{
|
||||
ffStrbufInsertNC(&ds->dePrettyName, strlen("RedMagicOS"), 1, ' ');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
{
|
||||
ffStrbufSetStatic(&ds->wmProcessName, "surfaceflinger");
|
||||
ffStrbufSetStatic(&ds->wmPrettyName, "SurfaceFlinger");
|
||||
const char* error = ffdsConnectXcbRandr(ds);
|
||||
if (error)
|
||||
error = ffdsConnectXrandr(ds);
|
||||
if (!error)
|
||||
{
|
||||
ffdsDetectWMDE(ds);
|
||||
return;
|
||||
}
|
||||
|
||||
// https://source.android.com/docs/core/graphics/surfaceflinger-windowmanager
|
||||
ffStrbufSetStatic(&ds->wmProcessName, "system_server");
|
||||
ffStrbufSetStatic(&ds->wmPrettyName, "WindowManager"); // A system service managed by system_server
|
||||
ffStrbufSetStatic(&ds->wmProtocolName, FF_WM_PROTOCOL_SURFACEFLINGER);
|
||||
|
||||
if (!detectWithGetprop(ds))
|
||||
detectWithDumpsys(ds);
|
||||
|
||||
detectDE(ds);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#include "displayserver.h"
|
||||
#include "detection/os/os.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/edidHelper.h"
|
||||
|
||||
#include <dwmapi.h>
|
||||
#include <WinUser.h>
|
||||
#include <winuser.h>
|
||||
#include <wchar.h>
|
||||
|
||||
typedef struct FFMonitorInfo
|
||||
@@ -232,6 +229,7 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
}
|
||||
if (edidLength > 0)
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek);
|
||||
display->drrStatus = path->flags & DISPLAYCONFIG_PATH_BOOST_REFRESH_RATE ? FF_DISPLAY_DRR_STATUS_ENABLED : FF_DISPLAY_DRR_STATUS_DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,27 +252,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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "displayserver_linux.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
FFDisplayType ffdsGetDisplayType(const char* name)
|
||||
{
|
||||
if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-"))
|
||||
return FF_DISPLAY_TYPE_BUILTIN;
|
||||
else if(ffStrStartsWith(name, "HDMI-") ||
|
||||
ffStrStartsWith(name, "DP-") ||
|
||||
ffStrStartsWith(name, "DisplayPort-") ||
|
||||
ffStrStartsWith(name, "DVI-") ||
|
||||
ffStrStartsWith(name, "VGA-"))
|
||||
return FF_DISPLAY_TYPE_EXTERNAL;
|
||||
|
||||
return FF_DISPLAY_TYPE_UNKNOWN;
|
||||
}
|
||||
@@ -95,17 +95,3 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
ffdsDetectWMDE(ds);
|
||||
}
|
||||
}
|
||||
|
||||
FFDisplayType ffdsGetDisplayType(const char* name)
|
||||
{
|
||||
if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-"))
|
||||
return FF_DISPLAY_TYPE_BUILTIN;
|
||||
else if(ffStrStartsWith(name, "HDMI-") ||
|
||||
ffStrStartsWith(name, "DP-") ||
|
||||
ffStrStartsWith(name, "DisplayPort-") ||
|
||||
ffStrStartsWith(name, "DVI-") ||
|
||||
ffStrStartsWith(name, "VGA-"))
|
||||
return FF_DISPLAY_TYPE_EXTERNAL;
|
||||
|
||||
return FF_DISPLAY_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -396,13 +396,10 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
|
||||
}
|
||||
|
||||
FFDisplayResult* item = ffdsAppendDisplay(result,
|
||||
width,
|
||||
height,
|
||||
width, height,
|
||||
refreshRate,
|
||||
0,
|
||||
0,
|
||||
preferredWidth,
|
||||
preferredHeight,
|
||||
0, 0,
|
||||
preferredWidth, preferredHeight,
|
||||
preferredRefreshRate,
|
||||
0,
|
||||
&name,
|
||||
|
||||
@@ -128,8 +128,8 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
|
||||
(uint32_t) display.width,
|
||||
(uint32_t) display.height,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
(uint32_t) (display.width / display.scale + .5),
|
||||
(uint32_t) (display.height / display.scale + .5),
|
||||
(uint32_t) display.preferredWidth,
|
||||
(uint32_t) display.preferredHeight,
|
||||
display.preferredRefreshRate / 1000.0,
|
||||
|
||||
@@ -239,6 +239,11 @@ enum kde_output_device_v2_capability {
|
||||
* @since 17
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_SHARPNESS = 0x1000,
|
||||
/**
|
||||
* if this outputdevice supports custom modes
|
||||
* @since 18
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_CUSTOM_MODES = 0x2000,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
@@ -280,6 +285,10 @@ enum kde_output_device_v2_capability {
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_SHARPNESS_SINCE_VERSION 17
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_CUSTOM_MODES_SINCE_VERSION 18
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_CAPABILITY_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_VRR_POLICY_ENUM
|
||||
@@ -794,6 +803,23 @@ struct kde_output_device_v2_listener {
|
||||
void (*sharpness)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t sharpness);
|
||||
/**
|
||||
* output priority
|
||||
*
|
||||
* Describes the position of the output in the output order list,
|
||||
* with lower values being earlier in the list. There's no specific
|
||||
* value the list has to start at, this value is only used in
|
||||
* sorting outputs.
|
||||
*
|
||||
* Note that the output order protocol is not sufficient for this,
|
||||
* as an output may not be in the output order if it's disabled or
|
||||
* mirroring another screen.
|
||||
* @param priority priority
|
||||
* @since 18
|
||||
*/
|
||||
void (*priority)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t priority);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -943,6 +969,10 @@ kde_output_device_v2_add_listener(struct kde_output_device_v2 *kde_output_device
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_SHARPNESS_SINCE_VERSION 17
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_PRIORITY_SINCE_VERSION 18
|
||||
|
||||
|
||||
/** @ingroup iface_kde_output_device_v2 */
|
||||
@@ -972,6 +1002,18 @@ kde_output_device_v2_destroy(struct kde_output_device_v2 *kde_output_device_v2)
|
||||
wl_proxy_destroy((struct wl_proxy *) kde_output_device_v2);
|
||||
}
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
* mode flags
|
||||
*/
|
||||
enum kde_output_device_mode_v2_flags {
|
||||
KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_CUSTOM = 0x1,
|
||||
KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_REDUCED_BLANKING = 0x2,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM */
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
* @struct kde_output_device_mode_v2_listener
|
||||
@@ -1017,6 +1059,15 @@ struct kde_output_device_mode_v2_listener {
|
||||
*/
|
||||
void (*removed)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2);
|
||||
/**
|
||||
* mode flags
|
||||
*
|
||||
* This event describes the mode's flags.
|
||||
* @since 19
|
||||
*/
|
||||
void (*flags)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2,
|
||||
uint32_t flags);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1046,6 +1097,10 @@ kde_output_device_mode_v2_add_listener(struct kde_output_device_mode_v2 *kde_out
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_REMOVED_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_SINCE_VERSION 19
|
||||
|
||||
|
||||
/** @ingroup iface_kde_output_device_mode_v2 */
|
||||
|
||||
@@ -67,12 +67,13 @@ static const struct wl_message kde_output_device_v2_events[] = {
|
||||
{ "automatic_max_bits_per_color_limit", "15u", kde_output_device_v2_types + 0 },
|
||||
{ "edr_policy", "16u", kde_output_device_v2_types + 0 },
|
||||
{ "sharpness", "17u", kde_output_device_v2_types + 0 },
|
||||
{ "priority", "18u", kde_output_device_v2_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface kde_output_device_v2_interface = {
|
||||
"kde_output_device_v2", 17,
|
||||
"kde_output_device_v2", 19,
|
||||
0, NULL,
|
||||
34, kde_output_device_v2_events,
|
||||
35, kde_output_device_v2_events,
|
||||
};
|
||||
|
||||
static const struct wl_message kde_output_device_mode_v2_events[] = {
|
||||
@@ -80,12 +81,13 @@ static const struct wl_message kde_output_device_mode_v2_events[] = {
|
||||
{ "refresh", "i", kde_output_device_v2_types + 0 },
|
||||
{ "preferred", "", kde_output_device_v2_types + 0 },
|
||||
{ "removed", "", kde_output_device_v2_types + 0 },
|
||||
{ "flags", "19u", kde_output_device_v2_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface kde_output_device_mode_v2_interface = {
|
||||
"kde_output_device_mode_v2", 1,
|
||||
"kde_output_device_mode_v2", 19,
|
||||
0, NULL,
|
||||
4, kde_output_device_mode_v2_events,
|
||||
5, kde_output_device_mode_v2_events,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -178,6 +178,7 @@ static struct kde_output_device_v2_listener outputListener = {
|
||||
.automatic_max_bits_per_color_limit = (void*) stubListener,
|
||||
.edr_policy = (void*) stubListener,
|
||||
.sharpness = (void*) stubListener,
|
||||
.priority = (void*) stubListener,
|
||||
};
|
||||
|
||||
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
@@ -220,8 +221,8 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
|
||||
(uint32_t) display.width,
|
||||
(uint32_t) display.height,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
(uint32_t) (display.width / display.scale + .5),
|
||||
(uint32_t) (display.height / display.scale + .5),
|
||||
(uint32_t) display.preferredWidth,
|
||||
(uint32_t) display.preferredHeight,
|
||||
display.preferredRefreshRate / 1000.0,
|
||||
|
||||
@@ -65,7 +65,7 @@ static const char* parseEnv(void)
|
||||
if(getenv("SWAYSOCK") != NULL)
|
||||
return "Sway";
|
||||
|
||||
#ifdef __linux__
|
||||
#if __linux__ && !__ANDROID__
|
||||
if(
|
||||
getenv("WAYLAND_DISPLAY") != NULL &&
|
||||
ffPathExists("/mnt/wslg/", FF_PATHTYPE_DIRECTORY)
|
||||
@@ -433,6 +433,11 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
|
||||
|
||||
void ffdsDetectWMDE(FFDisplayServerResult* result)
|
||||
{
|
||||
#if __ANDROID__
|
||||
if(ffStrbufIgnCaseEqualS(&result->wmProtocolName, FF_WM_PROTOCOL_SURFACEFLINGER))
|
||||
return; // Only supported when connected to X11
|
||||
#endif
|
||||
|
||||
const char* env = parseEnv();
|
||||
|
||||
if(result->wmProcessName.length > 0)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifdef FF_HAVE_XCB_RANDR
|
||||
|
||||
#include "common/library.h"
|
||||
#include "common/time.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
@@ -56,7 +56,7 @@ static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection,
|
||||
if(requestAtomReply == NULL)
|
||||
return NULL;
|
||||
|
||||
xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 64);
|
||||
xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 8 * 1024);
|
||||
|
||||
FF_AUTO_FREE xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(connection, propertyCookie, NULL);
|
||||
if(propertyReply == NULL)
|
||||
@@ -138,86 +138,9 @@ typedef struct XcbRandrData
|
||||
xcb_connection_t* connection;
|
||||
FFDisplayServerResult* result;
|
||||
XcbPropertyData propData;
|
||||
|
||||
//init per screen
|
||||
xcb_randr_get_screen_resources_current_reply_t* screenResources;
|
||||
} XcbRandrData;
|
||||
|
||||
static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength)
|
||||
{
|
||||
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME);
|
||||
FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL);
|
||||
if(crtcInfoReply == NULL)
|
||||
return false;
|
||||
|
||||
uint32_t rotation;
|
||||
switch (crtcInfoReply->rotation)
|
||||
{
|
||||
case XCB_RANDR_ROTATION_ROTATE_90:
|
||||
rotation = 90;
|
||||
break;
|
||||
case XCB_RANDR_ROTATION_ROTATE_180:
|
||||
rotation = 180;
|
||||
break;
|
||||
case XCB_RANDR_ROTATION_ROTATE_270:
|
||||
rotation = 270;
|
||||
break;
|
||||
default:
|
||||
rotation = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
xcb_randr_mode_info_t* currentMode = NULL;
|
||||
xcb_randr_mode_info_t* preferredMode = NULL;
|
||||
|
||||
if(data->screenResources)
|
||||
{
|
||||
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources);
|
||||
|
||||
if (output->num_preferred > 0)
|
||||
preferredMode = modesIterator.data;
|
||||
|
||||
while (modesIterator.rem > 0)
|
||||
{
|
||||
if (modesIterator.data->id == crtcInfoReply->mode)
|
||||
{
|
||||
currentMode = modesIterator.data;
|
||||
break;
|
||||
}
|
||||
|
||||
data->ffxcb_randr_mode_info_next(&modesIterator);
|
||||
}
|
||||
}
|
||||
|
||||
FFDisplayResult* item = ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
currentMode ? (double) currentMode->dot_clock / (double) ((uint32_t) currentMode->htotal * currentMode->vtotal) : 0,
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
preferredMode ? (uint32_t) preferredMode->width : 0,
|
||||
preferredMode ? (uint32_t) preferredMode->height : 0,
|
||||
preferredMode ? (double) preferredMode->dot_clock / (double) ((uint32_t) preferredMode->htotal * preferredMode->vtotal) : 0,
|
||||
rotation,
|
||||
name,
|
||||
displayType,
|
||||
primary,
|
||||
0,
|
||||
(uint32_t) output->mm_width,
|
||||
(uint32_t) output->mm_height,
|
||||
"xcb-randr-crtc"
|
||||
);
|
||||
if (item && edidLength)
|
||||
{
|
||||
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
|
||||
}
|
||||
|
||||
return !!item;
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType)
|
||||
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, double scaleFactor)
|
||||
{
|
||||
xcb_randr_get_output_info_cookie_t outputInfoCookie = data->ffxcb_randr_get_output_info(data->connection, output, XCB_CURRENT_TIME);
|
||||
FF_AUTO_FREE xcb_randr_get_output_info_reply_t* outputInfoReply = data->ffxcb_randr_get_output_info_reply(data->connection, outputInfoCookie, NULL);
|
||||
@@ -246,12 +169,80 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
|
||||
}
|
||||
}
|
||||
|
||||
bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType, edidData, edidLength);
|
||||
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, outputInfoReply->crtc, XCB_CURRENT_TIME);
|
||||
FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL);
|
||||
if(crtcInfoReply == NULL)
|
||||
return false;
|
||||
|
||||
return res;
|
||||
uint32_t rotation;
|
||||
switch (crtcInfoReply->rotation)
|
||||
{
|
||||
case XCB_RANDR_ROTATION_ROTATE_90:
|
||||
rotation = 90;
|
||||
break;
|
||||
case XCB_RANDR_ROTATION_ROTATE_180:
|
||||
rotation = 180;
|
||||
break;
|
||||
case XCB_RANDR_ROTATION_ROTATE_270:
|
||||
rotation = 270;
|
||||
break;
|
||||
default:
|
||||
rotation = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
xcb_randr_mode_info_t* currentMode = NULL;
|
||||
xcb_randr_mode_info_t* preferredMode = NULL;
|
||||
|
||||
if(screenResources)
|
||||
{
|
||||
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(screenResources);
|
||||
|
||||
if (outputInfoReply->num_preferred > 0)
|
||||
preferredMode = modesIterator.data;
|
||||
|
||||
while (modesIterator.rem > 0)
|
||||
{
|
||||
if (modesIterator.data->id == crtcInfoReply->mode)
|
||||
{
|
||||
currentMode = modesIterator.data;
|
||||
break;
|
||||
}
|
||||
|
||||
data->ffxcb_randr_mode_info_next(&modesIterator);
|
||||
}
|
||||
}
|
||||
|
||||
FFDisplayResult* item = ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) (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),
|
||||
preferredMode ? (uint32_t) preferredMode->width : 0,
|
||||
preferredMode ? (uint32_t) preferredMode->height : 0,
|
||||
preferredMode ? (double) preferredMode->dot_clock / (double) ((uint32_t) preferredMode->htotal * preferredMode->vtotal) : 0,
|
||||
rotation,
|
||||
name,
|
||||
displayType,
|
||||
primary,
|
||||
0,
|
||||
(uint32_t) outputInfoReply->mm_width,
|
||||
(uint32_t) outputInfoReply->mm_height,
|
||||
currentMode ? "xcb-randr-mode" : "xcb-randr-crtc"
|
||||
);
|
||||
if (item && edidLength)
|
||||
{
|
||||
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
|
||||
item->bitDepth = bitDepth;
|
||||
}
|
||||
|
||||
return !!item;
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor)
|
||||
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, double scaleFactor)
|
||||
{
|
||||
//for some reasons, we have to construct this our self
|
||||
xcb_randr_output_iterator_t outputIterator = {
|
||||
@@ -275,18 +266,20 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
|
||||
|
||||
while(outputIterator.rem > 0)
|
||||
{
|
||||
if(xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary, displayType))
|
||||
if(xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary, displayType, screenResources, bitDepth, scaleFactor))
|
||||
foundOutput = true;
|
||||
data->ffxcb_randr_output_next(&outputIterator);
|
||||
};
|
||||
}
|
||||
|
||||
return foundOutput ? true : !!ffdsAppendDisplay(
|
||||
if (foundOutput) return true;
|
||||
|
||||
FFDisplayResult* display = ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) monitor->width,
|
||||
(uint32_t) monitor->height,
|
||||
0,
|
||||
(uint32_t) monitor->width,
|
||||
(uint32_t) monitor->height,
|
||||
(uint32_t) (monitor->width / scaleFactor + .5),
|
||||
(uint32_t) (monitor->height / scaleFactor + .5),
|
||||
0, 0, 0,
|
||||
0,
|
||||
&name,
|
||||
@@ -297,6 +290,8 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
|
||||
(uint32_t) monitor->height_in_millimeters,
|
||||
"xcb-randr-monitor"
|
||||
);
|
||||
if (display) display->bitDepth = bitDepth;
|
||||
return !!display;
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
|
||||
@@ -306,13 +301,27 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
|
||||
if(monitorsReply == NULL)
|
||||
return false;
|
||||
|
||||
//Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
|
||||
xcb_randr_get_screen_resources_current_cookie_t screenResourcesCookie = data->ffxcb_randr_get_screen_resources_current(data->connection, screen->root);
|
||||
FF_AUTO_FREE struct xcb_randr_get_screen_resources_current_reply_t* screenResources = data->ffxcb_randr_get_screen_resources_current_reply(data->connection, screenResourcesCookie, NULL);
|
||||
|
||||
double scaleFactor = 1;
|
||||
FF_AUTO_FREE const char* resourceManager = xcbGetProperty(&data->propData, data->connection, screen->root, "RESOURCE_MANAGER");
|
||||
if (resourceManager)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY dpi = ffStrbufCreate();
|
||||
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpi))
|
||||
scaleFactor = ffStrbufToDouble(&dpi, 96) / 96;
|
||||
}
|
||||
uint8_t bitDepth = (uint8_t) (screen->root_depth / 3);
|
||||
|
||||
xcb_randr_monitor_info_iterator_t monitorInfoIterator = data->ffxcb_randr_get_monitors_monitors_iterator(monitorsReply);
|
||||
|
||||
bool foundMonitor = false;
|
||||
|
||||
while(monitorInfoIterator.rem > 0)
|
||||
{
|
||||
if(xcbRandrHandleMonitor(data, monitorInfoIterator.data))
|
||||
if(xcbRandrHandleMonitor(data, monitorInfoIterator.data, screenResources, bitDepth, scaleFactor))
|
||||
foundMonitor = true;
|
||||
data->ffxcb_randr_monitor_info_next(&monitorInfoIterator);
|
||||
}
|
||||
@@ -322,17 +331,8 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
|
||||
|
||||
static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
|
||||
{
|
||||
//Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
|
||||
xcb_randr_get_screen_resources_current_cookie_t screenResourcesCookie = data->ffxcb_randr_get_screen_resources_current(data->connection, screen->root);
|
||||
|
||||
data->screenResources = data->ffxcb_randr_get_screen_resources_current_reply(data->connection, screenResourcesCookie, NULL);
|
||||
|
||||
//With all the initialisation done, start the detection
|
||||
bool ret = xcbRandrHandleMonitors(data, screen);
|
||||
|
||||
free(data->screenResources);
|
||||
|
||||
if(ret)
|
||||
if(xcbRandrHandleMonitors(data, screen))
|
||||
return;
|
||||
|
||||
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
|
||||
@@ -348,7 +348,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
false,
|
||||
0,
|
||||
(uint64_t) screen->root,
|
||||
(uint32_t) screen->width_in_millimeters,
|
||||
(uint32_t) screen->height_in_millimeters,
|
||||
"xcb-randr-screen"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
|
||||
#include "common/library.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
@@ -70,8 +70,6 @@ static void x11FetchServerVendor(X11PropertyData* data, Display* display, FFDisp
|
||||
if (serverVendor && !ffStrEquals(serverVendor, "The X.Org Foundation")) {
|
||||
ffStrbufSetS(&result->wmProtocolName, serverVendor);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
typedef struct XrandrData
|
||||
@@ -92,18 +90,16 @@ typedef struct XrandrData
|
||||
//Init once
|
||||
Display* display;
|
||||
FFDisplayServerResult* result;
|
||||
|
||||
//Init per screen
|
||||
XRRScreenResources* screenResources;
|
||||
X11PropertyData* propData;
|
||||
} XrandrData;
|
||||
|
||||
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength)
|
||||
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor)
|
||||
{
|
||||
//We do the check here, because we want the best fallback display if this call failed
|
||||
if(data->screenResources == NULL)
|
||||
if(screenResources == NULL)
|
||||
return false;
|
||||
|
||||
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, output->crtc);
|
||||
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, screenResources, output->crtc);
|
||||
if(crtcInfo == NULL)
|
||||
return false;
|
||||
|
||||
@@ -125,27 +121,24 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
|
||||
}
|
||||
|
||||
XRRModeInfo* currentMode = NULL;
|
||||
if (data->screenResources)
|
||||
for(int i = 0; i < screenResources->nmode; i++)
|
||||
{
|
||||
for(int i = 0; i < data->screenResources->nmode; i++)
|
||||
if(screenResources->modes[i].id == crtcInfo->mode)
|
||||
{
|
||||
if(data->screenResources->modes[i].id == crtcInfo->mode)
|
||||
{
|
||||
currentMode = &data->screenResources->modes[i];
|
||||
break;
|
||||
}
|
||||
currentMode = &screenResources->modes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XRRModeInfo* preferredMode = data->screenResources && output->npreferred > 0 ? &data->screenResources->modes[0] : NULL;
|
||||
XRRModeInfo* preferredMode = output->npreferred > 0 ? &screenResources->modes[0] : NULL;
|
||||
|
||||
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,
|
||||
(uint32_t) crtcInfo->height,
|
||||
(uint32_t) (crtcInfo->width / scaleFactor + .5),
|
||||
(uint32_t) (crtcInfo->height / scaleFactor + .5),
|
||||
preferredMode ? (uint32_t) preferredMode->width : 0,
|
||||
preferredMode ? (uint32_t) preferredMode->height : 0,
|
||||
preferredMode ? (double) preferredMode->dotClock / (double) ((uint32_t) preferredMode->hTotal * preferredMode->vTotal) : 0,
|
||||
@@ -156,22 +149,26 @@ 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 && edidLength)
|
||||
if (item)
|
||||
{
|
||||
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
|
||||
if (edidLength)
|
||||
{
|
||||
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
|
||||
}
|
||||
item->bitDepth = bitDepth;
|
||||
}
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
return !!item;
|
||||
}
|
||||
|
||||
static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType)
|
||||
static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor)
|
||||
{
|
||||
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output);
|
||||
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, screenResources, output);
|
||||
if(outputInfo == NULL)
|
||||
return false;
|
||||
|
||||
@@ -195,7 +192,7 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
|
||||
}
|
||||
}
|
||||
|
||||
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength);
|
||||
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength, screenResources, bitDepth, scaleFactor);
|
||||
|
||||
if (edidData)
|
||||
data->ffXFree(edidData);
|
||||
@@ -204,7 +201,7 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor)
|
||||
{
|
||||
bool foundOutput = false;
|
||||
char* xname = data->ffXGetAtomName(data->display, monitorInfo->name);
|
||||
@@ -213,17 +210,19 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
FFDisplayType displayType = ffdsGetDisplayType(name.chars);
|
||||
for(int i = 0; i < monitorInfo->noutput; i++)
|
||||
{
|
||||
if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary, displayType))
|
||||
if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary, displayType, screenResources, bitDepth, scaleFactor))
|
||||
foundOutput = true;
|
||||
}
|
||||
|
||||
return foundOutput ? true : !!ffdsAppendDisplay(
|
||||
if (foundOutput) return true;
|
||||
|
||||
FFDisplayResult* display = ffdsAppendDisplay(
|
||||
data->result,
|
||||
(uint32_t) monitorInfo->width,
|
||||
(uint32_t) monitorInfo->height,
|
||||
0,
|
||||
(uint32_t) monitorInfo->width,
|
||||
(uint32_t) monitorInfo->height,
|
||||
(uint32_t) (monitorInfo->width / scaleFactor + .5),
|
||||
(uint32_t) (monitorInfo->height / scaleFactor + .5),
|
||||
0, 0, 0,
|
||||
0,
|
||||
&name,
|
||||
@@ -234,6 +233,8 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
(uint32_t) monitorInfo->mheight,
|
||||
"xlib-randr-monitor"
|
||||
);
|
||||
if (display) display->bitDepth = bitDepth;
|
||||
return !!display;
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
|
||||
@@ -243,29 +244,36 @@ static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
|
||||
if(monitorInfos == NULL)
|
||||
return false;
|
||||
|
||||
XRRScreenResources* screenResources = data->ffXRRGetScreenResourcesCurrent(data->display, RootWindowOfScreen(screen));
|
||||
|
||||
double scaleFactor = 1;
|
||||
char* resourceManager = (char*) x11GetProperty(data->propData, data->display, screen->root, "RESOURCE_MANAGER");
|
||||
if (resourceManager)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY dpi = ffStrbufCreate();
|
||||
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpi))
|
||||
scaleFactor = ffStrbufToDouble(&dpi, 96) / 96;
|
||||
data->ffXFree(resourceManager);
|
||||
}
|
||||
uint8_t bitDepth = (uint8_t) (screen->root_depth / 3);
|
||||
|
||||
bool foundAMonitor = false;
|
||||
|
||||
for(int i = 0; i < numberOfMonitors; i++)
|
||||
{
|
||||
if(xrandrHandleMonitor(data, &monitorInfos[i]))
|
||||
if(xrandrHandleMonitor(data, &monitorInfos[i], screenResources, bitDepth, scaleFactor))
|
||||
foundAMonitor = true;
|
||||
}
|
||||
|
||||
data->ffXRRFreeMonitors(monitorInfos);
|
||||
data->ffXRRFreeScreenResources(screenResources);
|
||||
|
||||
return foundAMonitor;
|
||||
}
|
||||
|
||||
static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
{
|
||||
//Init screen resources
|
||||
data->screenResources = data->ffXRRGetScreenResourcesCurrent(data->display, RootWindowOfScreen(screen));
|
||||
|
||||
bool ret = xrandrHandleMonitors(data, screen);
|
||||
|
||||
data->ffXRRFreeScreenResources(data->screenResources);
|
||||
|
||||
if(ret)
|
||||
if(xrandrHandleMonitors(data, screen))
|
||||
return;
|
||||
|
||||
//Fallback to screen
|
||||
@@ -281,7 +289,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
NULL,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
false,
|
||||
0,
|
||||
RootWindowOfScreen(screen),
|
||||
(uint32_t) WidthMMOfScreen(screen),
|
||||
(uint32_t) HeightMMOfScreen(screen),
|
||||
"xlib-randr-screen"
|
||||
@@ -312,6 +320,7 @@ const char* ffdsConnectXrandr(FFDisplayServerResult* result)
|
||||
|
||||
X11PropertyData propertyData;
|
||||
bool propertyDataInitialized = x11InitPropertyData(xrandr, &propertyData);
|
||||
data.propData = &propertyData;
|
||||
|
||||
data.display = ffXOpenDisplay(NULL);
|
||||
if(data.display == NULL)
|
||||
|
||||
@@ -28,7 +28,7 @@ const char* ffDetectFontImpl(FFFontResult* result)
|
||||
{
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
|
||||
if(ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY))
|
||||
return "Font isn't supported in TTY";
|
||||
|
||||
FFfont qt;
|
||||
|
||||
+19
-1
@@ -15,11 +15,18 @@ extern const char* FF_GPU_VENDOR_NAME_AMD;
|
||||
extern const char* FF_GPU_VENDOR_NAME_INTEL;
|
||||
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
extern const char* FF_GPU_VENDOR_NAME_MTHREADS;
|
||||
extern const char* FF_GPU_VENDOR_NAME_QUALCOMM;
|
||||
extern const char* FF_GPU_VENDOR_NAME_MTK;
|
||||
extern const char* FF_GPU_VENDOR_NAME_VMWARE;
|
||||
extern const char* FF_GPU_VENDOR_NAME_PARALLEL;
|
||||
extern const char* FF_GPU_VENDOR_NAME_MICROSOFT;
|
||||
extern const char* FF_GPU_VENDOR_NAME_REDHAT;
|
||||
extern const char* FF_GPU_VENDOR_NAME_ORACLE;
|
||||
extern const char* FF_GPU_VENDOR_NAME_BROADCOM;
|
||||
extern const char* FF_GPU_VENDOR_NAME_LOONGSON;
|
||||
extern const char* FF_GPU_VENDOR_NAME_JINGJIA_MICRO;
|
||||
extern const char* FF_GPU_VENDOR_NAME_HUAWEI;
|
||||
extern const char* FF_GPU_VENDOR_NAME_ZHAOXIN;
|
||||
|
||||
typedef struct FFGPUMemory
|
||||
{
|
||||
@@ -58,7 +65,7 @@ typedef struct FFGpuDriverPciBusId
|
||||
uint32_t func;
|
||||
} FFGpuDriverPciBusId;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) || defined(__GNU__)
|
||||
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
|
||||
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
|
||||
|
||||
@@ -73,3 +80,14 @@ const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd);
|
||||
|
||||
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
|
||||
#endif // defined(XXX)
|
||||
|
||||
static inline uint64_t ffGPUPciAddr2Id(uint64_t domain, uint64_t bus, uint64_t device, uint64_t function)
|
||||
{
|
||||
return (domain << 16) | (bus << 8) | (device << 3) | function;
|
||||
}
|
||||
|
||||
static inline uint64_t ffGPUGeneral2Id(uint64_t originalId)
|
||||
{
|
||||
// Note: originalId may already have the MSB set
|
||||
return (1ULL << 63) | originalId;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ static const char* detectFrequency(FFGPUResult* gpu)
|
||||
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID())
|
||||
return "\"voltage-states9-sram\" in \"pmgr\" is not found";
|
||||
|
||||
// voltage-states5-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
|
||||
// voltage-states9-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
|
||||
CFIndex propLength = CFDataGetLength(freqProperty);
|
||||
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0)
|
||||
return "Invalid \"voltage-states9-sram\" length";
|
||||
|
||||
@@ -30,7 +30,7 @@ static void fillGPUTypeGeneric(FFGPUResult* gpu)
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
{
|
||||
// 0000:00:02.0 is reserved for Intel integrated graphics
|
||||
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
case DRM_BUS_PCI:
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
|
||||
gpu->deviceId = (dev->businfo.pci->domain * 100000ull) + (dev->businfo.pci->bus * 1000ull) + (dev->businfo.pci->dev * 10ull) + dev->businfo.pci->func;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func);
|
||||
break;
|
||||
case DRM_BUS_HOST1X:
|
||||
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
|
||||
@@ -179,6 +179,9 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
struct pci_conf* pc = &confs[i];
|
||||
|
||||
if (pc->pc_sel.pc_func > 0 && pc->pc_subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
|
||||
continue; // Likely an auxiliary display controller (#2034)
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pc->pc_vendor));
|
||||
ffStrbufInit(&gpu->name);
|
||||
@@ -191,7 +194,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = (pc->pc_sel.pc_domain * 100000ull) + (pc->pc_sel.pc_bus * 1000ull) + (pc->pc_sel.pc_dev * 10ull) + pc->pc_sel.pc_func;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(pc->pc_sel.pc_domain, pc->pc_sel.pc_bus, pc->pc_sel.pc_dev, pc->pc_sel.pc_func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
|
||||
@@ -153,7 +153,7 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(gpu, renderPath);
|
||||
FF_UNUSED(options, gpu, renderPath);
|
||||
return "Fastfetch is compiled without libdrm support";
|
||||
#endif
|
||||
}
|
||||
@@ -313,7 +313,7 @@ const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
|
||||
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
|
||||
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
|
||||
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
|
||||
gpu->deviceId = paramsGlobal.chip_id;
|
||||
gpu->deviceId = ffGPUGeneral2Id(paramsGlobal.chip_id);
|
||||
|
||||
if (!gpu->name.length)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_slot_match_iterator_create)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_device_next)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_system_cleanup)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_iterator_destroy)
|
||||
|
||||
{
|
||||
// Requires root access
|
||||
@@ -29,6 +30,11 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
if (dev->device_class >> 16 != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
||||
continue;
|
||||
|
||||
uint8_t subclass = (dev->device_class >> 8) & 0xFF;
|
||||
|
||||
if (dev->func > 0 && subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
|
||||
continue; // Likely an auxiliary display controller (#2034)
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->vendor_id));
|
||||
ffStrbufInit(&gpu->name);
|
||||
@@ -40,15 +46,16 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ((uint64_t) dev->domain << 6) | ((uint64_t) dev->bus << 4) | ((uint64_t) dev->dev << 2) | (uint64_t) dev->func;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(dev->domain, dev->bus, dev->dev, dev->func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
ffGPUQueryAmdGpuName(dev->device_id, dev->revision, gpu);
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
ffGPUFillVendorAndName((dev->device_class >> 8) & 0xFF, dev->vendor_id, dev->device_id, gpu);
|
||||
ffGPUFillVendorAndName(subclass, dev->vendor_id, dev->device_id, gpu);
|
||||
}
|
||||
ffpci_iterator_destroy(iter);
|
||||
|
||||
ffpci_system_cleanup();
|
||||
return NULL;
|
||||
|
||||
@@ -19,6 +19,9 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
if (dev.class_base != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
||||
continue;
|
||||
|
||||
if (dev.function > 0 && dev.class_sub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
|
||||
continue; // Likely an auxiliary display controller (#2034)
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev.vendor_id));
|
||||
ffStrbufInit(&gpu->name);
|
||||
@@ -30,7 +33,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ((uint64_t) dev.bus << 4) | ((uint64_t) dev.device << 2) | (uint64_t) dev.function;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, dev.bus, dev.device, dev.function);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "modules/gpu/option.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef FF_HAVE_DRM_AMDGPU
|
||||
#include <amdgpu.h>
|
||||
@@ -120,7 +123,7 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
FF_UNUSED(gpu, drmKey, buffer);
|
||||
FF_UNUSED(options, gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with drm support";
|
||||
#endif
|
||||
}
|
||||
@@ -198,7 +201,7 @@ static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu
|
||||
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
|
||||
|
||||
// 0000:00:02.0 is reserved for Intel integrated graphics
|
||||
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
|
||||
if (!drmKey) return;
|
||||
|
||||
@@ -263,7 +266,7 @@ static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey,
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* pciDetectNouveauSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
if (options->temp)
|
||||
{
|
||||
@@ -306,6 +309,48 @@ static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
|
||||
const uint32_t pciDirLen = pciDir->length;
|
||||
ffStrbufAppendS(pciDir, "/zx_info/eclk");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, FF_GPU_FREQUENCY_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
if (options->driverSpecific)
|
||||
{
|
||||
ffStrbufAppendS(pciDir, "/zx_info/engine_3d_usage");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->coreUsage = ffStrbufToDouble(buffer, FF_GPU_CORE_USAGE_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
ffStrbufAppendS(pciDir, "/zx_info/fb_size");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->shared.total = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
{
|
||||
gpu->shared.total *= 1024 * 1024;
|
||||
|
||||
ffStrbufAppendS(pciDir, "/zx_info/free_fb_mem");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->shared.used = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET)
|
||||
{
|
||||
gpu->shared.used *= 1024 * 1024;
|
||||
gpu->shared.used = gpu->shared.total - gpu->shared.used;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
|
||||
{
|
||||
const uint32_t drmDirPathLength = deviceDir->length;
|
||||
@@ -342,6 +387,9 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
||||
return "Invalid PCI device path";
|
||||
|
||||
if (pciFunc > 0 && subclassId == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
|
||||
return "Likely an auxiliary display controller"; // #2034
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString((uint16_t) vendorId));
|
||||
ffStrbufInit(&gpu->name);
|
||||
@@ -354,7 +402,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = (pciDomain * 100000ull) + (pciBus * 1000ull) + (pciDevice * 10ull) + pciFunc;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(pciDomain, pciBus, pciDevice, pciFunc);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
char drmKeyBuffer[8];
|
||||
@@ -414,10 +462,15 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && ffStrbufEqualS(&gpu->driver, "nouveau"))
|
||||
{
|
||||
pciDetectNouveauSpecific(options, gpu, deviceDir, buffer);
|
||||
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
|
||||
if (options->driverSpecific && drmKey)
|
||||
drmDetectNouveauSpecific(gpu, drmKey, buffer);
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_ZHAOXIN && ffStrbufStartsWithS(&gpu->driver, "zx"))
|
||||
{
|
||||
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
|
||||
pciDetectZxSpecific(options, gpu, deviceDir, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
@@ -552,7 +605,7 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
|
||||
if (ffStrbufStartsWithS(&buffer, "pci:"))
|
||||
detectPci(options, gpus, &buffer, &drmDir, entry->d_name);
|
||||
else if (ffStrbufStartsWithS(&buffer, "of:"))
|
||||
else if (ffStrbufStartsWithS(&buffer, "of:")) // Open Firmware
|
||||
detectOf(gpus, &buffer, &drmDir, entry->d_name);
|
||||
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "gpu.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcidevs.h>
|
||||
#include <dev/pci/pciio.h>
|
||||
|
||||
static inline int pciReadConf(int fd, uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint32_t* result)
|
||||
{
|
||||
struct pciio_bdf_cfgreg bdfr = {
|
||||
.bus = bus,
|
||||
.device = device,
|
||||
.function = func,
|
||||
.cfgreg = {
|
||||
.reg = reg,
|
||||
},
|
||||
};
|
||||
|
||||
if (ioctl(fd, PCI_IOC_BDF_CFGREAD, &bdfr) == -1)
|
||||
return -1;
|
||||
|
||||
*result = bdfr.cfgreg.val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
char pciDevPath[] = "/dev/pciXXX";
|
||||
|
||||
for (uint32_t idev = 0; idev <= 255; idev++)
|
||||
{
|
||||
snprintf(pciDevPath + strlen("/dev/pci"), 4, "%u", idev);
|
||||
|
||||
FF_AUTO_CLOSE_FD int pcifd = open(pciDevPath, O_RDONLY | O_CLOEXEC);
|
||||
if (pcifd < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
break; // No more /dev/pciN devices
|
||||
return "open(\"/dev/pciN\", O_RDONLY | O_CLOEXEC) failed";
|
||||
}
|
||||
|
||||
struct pciio_businfo businfo;
|
||||
if (ioctl(pcifd, PCI_IOC_BUSINFO, &businfo) != 0)
|
||||
continue;
|
||||
|
||||
uint32_t bus = businfo.busno;
|
||||
for (uint32_t dev = 0; dev < businfo.maxdevs; dev++)
|
||||
{
|
||||
uint32_t maxfuncs = 0;
|
||||
for (uint32_t func = 0; func <= maxfuncs; func++)
|
||||
{
|
||||
uint32_t pciid, pciclass;
|
||||
if (pciReadConf(pcifd, bus, dev, func, PCI_ID_REG, &pciid) != 0)
|
||||
continue;
|
||||
|
||||
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0)
|
||||
continue;
|
||||
|
||||
if (pciReadConf(pcifd, bus, dev, func, PCI_CLASS_REG, &pciclass) != 0)
|
||||
continue;
|
||||
|
||||
if (func == 0)
|
||||
{
|
||||
// For some reason, pciReadConf returns success even for non-existing devices.
|
||||
// So we need to check for `PCI_VENDOR(pciid) == PCI_VENDOR_INVALID` above to filter them out.
|
||||
uint32_t bhlcr;
|
||||
if (pciReadConf(pcifd, bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0)
|
||||
continue;
|
||||
|
||||
if (PCI_HDRTYPE_MULTIFN(bhlcr)) maxfuncs = 7;
|
||||
}
|
||||
|
||||
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY)
|
||||
continue;
|
||||
|
||||
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC)
|
||||
continue; // Likely an auxiliary display controller (#2034)
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(PCI_VENDOR(pciid)));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInitS(&gpu->platformApi, pciDevPath);
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
|
||||
if (gpu->name.length == 0)
|
||||
ffGPUFillVendorAndName(PCI_SUBCLASS(pciclass), PCI_VENDOR(pciid), PCI_PRODUCT(pciid), gpu);
|
||||
|
||||
struct pciio_drvname drvname = {
|
||||
.device = dev,
|
||||
.function = func,
|
||||
};
|
||||
if (ioctl(pcifd, PCI_IOC_DRVNAME, &drvname) == 0)
|
||||
ffStrbufInitS(&gpu->driver, drvname.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "gpu.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcidevs.h>
|
||||
#include <sys/pciio.h>
|
||||
|
||||
static inline int pciReadConf(int fd, uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint32_t* result)
|
||||
{
|
||||
struct pci_io bdfr = {
|
||||
.pi_sel = {
|
||||
.pc_bus = bus,
|
||||
.pc_dev = device,
|
||||
.pc_func = func,
|
||||
},
|
||||
.pi_reg = reg,
|
||||
.pi_width = 4,
|
||||
};
|
||||
|
||||
if (ioctl(fd, PCIOCREAD, &bdfr) == -1)
|
||||
return -1;
|
||||
|
||||
*result = bdfr.pi_data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
char pciDevPath[] = "/dev/pci0";
|
||||
FF_AUTO_CLOSE_FD int pcifd = open(pciDevPath, O_RDONLY | O_CLOEXEC);
|
||||
if (pcifd < 0)
|
||||
return "open(\"/dev/pci0\", O_RDONLY | O_CLOEXEC) failed";
|
||||
|
||||
for (uint32_t bus = 0; bus <= 255; bus++)
|
||||
{
|
||||
for (uint32_t dev = 0; dev < 32; dev++)
|
||||
{
|
||||
uint32_t maxfuncs = 0;
|
||||
for (uint32_t func = 0; func <= maxfuncs; func++)
|
||||
{
|
||||
uint32_t pciid, pciclass;
|
||||
if (pciReadConf(pcifd, bus, dev, func, PCI_ID_REG, &pciid) != 0)
|
||||
continue;
|
||||
|
||||
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0)
|
||||
continue;
|
||||
|
||||
if (pciReadConf(pcifd, bus, dev, func, PCI_CLASS_REG, &pciclass) != 0)
|
||||
continue;
|
||||
|
||||
if (func == 0)
|
||||
{
|
||||
// For some reason, pciReadConf returns success even for non-existing devices.
|
||||
// So we need to check for `PCI_VENDOR(pciid) == PCI_VENDOR_INVALID` above to filter them out.
|
||||
uint32_t bhlcr;
|
||||
if (pciReadConf(pcifd, bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0)
|
||||
continue;
|
||||
|
||||
if (PCI_HDRTYPE_MULTIFN(bhlcr)) maxfuncs = 7;
|
||||
}
|
||||
|
||||
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY)
|
||||
continue;
|
||||
|
||||
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC)
|
||||
continue; // Likely an auxiliary display controller (#2034)
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(PCI_VENDOR(pciid)));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInitS(&gpu->platformApi, "/dev/pci0");
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
|
||||
if (gpu->name.length == 0)
|
||||
ffGPUFillVendorAndName(PCI_SUBCLASS(pciclass), PCI_VENDOR(pciid), PCI_PRODUCT(pciid), gpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -95,7 +95,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
{
|
||||
pciDev = (pciAddr >> 16) & 0xFFFF;
|
||||
pciFunc = pciAddr & 0xFFFF;
|
||||
gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc;
|
||||
gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc);
|
||||
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
|
||||
FF_DEBUG("PCI location - Bus: %u, Device: %u, Function: %u, DeviceID: %llu", pciBus, pciDev, pciFunc, gpu->deviceId);
|
||||
}
|
||||
@@ -182,7 +182,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL))
|
||||
{
|
||||
FF_DEBUG("Found adapter LUID: %llu", adapterLuid);
|
||||
if (!gpu->deviceId) gpu->deviceId = adapterLuid;
|
||||
if (!gpu->deviceId) gpu->deviceId = ffGPUGeneral2Id(adapterLuid);
|
||||
}
|
||||
|
||||
uint32_t featureLevel = 0;
|
||||
@@ -449,7 +449,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
FF_DEBUG("Using fallback GPU type detection");
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
{
|
||||
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
FF_DEBUG("Intel GPU type determined: %s", gpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete");
|
||||
}
|
||||
else if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
|
||||
@@ -79,6 +79,13 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
|
||||
gpu->deviceId = 0;
|
||||
ffStrbufInitStatic(&gpu->platformApi, "DXCore");
|
||||
|
||||
LUID luid;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, sizeof(luid), &luid)))
|
||||
{
|
||||
static_assert(sizeof(luid) == sizeof(uint64_t), "LUID size mismatch");
|
||||
gpu->deviceId = ffGPUGeneral2Id(*(uint64_t*)&luid);
|
||||
}
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
uint64_t value = 0;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DriverVersion, sizeof(value), &value)))
|
||||
|
||||
+33
-28
@@ -34,6 +34,13 @@ static inline void applyGTKSettings(FFGTKResult* result, const char* themeName,
|
||||
ffStrbufAppendS(&result->wallpaper, wallpaper);
|
||||
}
|
||||
|
||||
static bool testXfconfWallpaperPropKey(FF_MAYBE_UNUSED void* data, const char* key)
|
||||
{
|
||||
int count = 0;
|
||||
sscanf(key, "/backdrop/screen0/monitor%*[^/]/workspace0/last-image%n", &count);
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
static void detectGTKFromSettings(FFGTKResult* result)
|
||||
{
|
||||
static const char* themeName = NULL;
|
||||
@@ -55,47 +62,45 @@ static void detectGTKFromSettings(FFGTKResult* result)
|
||||
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4) == 0)
|
||||
if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4))
|
||||
{
|
||||
themeName = ffSettingsGetXFConf("xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetXFConf("xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetXFConf("xfce4-desktop", "/backdrop/screen0/monitor0/workspace0/last-image", FF_VARIANT_TYPE_STRING).strValue;
|
||||
if (!wallpaper) // FIXME: find a way to enumerate possible properties
|
||||
wallpaper = ffSettingsGetXFConf("xfce4-desktop", "/backdrop/screen0/monitoreDP-1/workspace0/last-image", FF_VARIANT_TYPE_STRING).strValue;
|
||||
wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, NULL, testXfconfWallpaperPropKey).strValue;
|
||||
}
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON) == 0)
|
||||
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON))
|
||||
{
|
||||
themeName = ffSettingsGet("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGet("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGet("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGet("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGet("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGet("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", NULL, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
themeName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", NULL, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
}
|
||||
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_MATE) == 0)
|
||||
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_MATE))
|
||||
{
|
||||
themeName = ffSettingsGet("/org/mate/interface/gtk-theme", "org.mate.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGet("/org/mate/interface/icon-theme", "org.mate.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGet("/org/mate/interface/font-name", "org.mate.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGet("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGet("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGet("/org/mate/desktop/background", "org.mate.background", NULL, "picture-filename", FF_VARIANT_TYPE_STRING).strValue;
|
||||
themeName = ffSettingsGetGnome("/org/mate/interface/gtk-theme", "org.mate.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/mate/interface/icon-theme", "org.mate.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/mate/interface/font-name", "org.mate.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/mate/desktop/background", "org.mate.background", NULL, "picture-filename", FF_VARIANT_TYPE_STRING).strValue;
|
||||
}
|
||||
else if(
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) == 0 ||
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) == 0 ||
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) == 0 ||
|
||||
ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) == 0
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) ||
|
||||
ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE)
|
||||
) {
|
||||
themeName = ffSettingsGet("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGet("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGet("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGet("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGet("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGet("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", NULL, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
themeName = ffSettingsGetGnome("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
iconsName = ffSettingsGetGnome("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
fontName = ffSettingsGetGnome("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorTheme = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
cursorSize = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue;
|
||||
wallpaper = ffSettingsGetGnome("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", NULL, "picture-uri", FF_VARIANT_TYPE_STRING).strValue;
|
||||
}
|
||||
|
||||
applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper);
|
||||
|
||||
@@ -45,7 +45,8 @@ const char* getOthersByIokit(FFHostResult* host)
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host)
|
||||
{
|
||||
const char* error = ffSysctlGetString("hw.model", &host->family);
|
||||
const char* error = ffSysctlGetString("hw.product", &host->family);
|
||||
if (error) error = ffSysctlGetString("hw.model", &host->family);
|
||||
if (error) return error;
|
||||
|
||||
ffStrbufSetStatic(&host->name, ffHostGetMacProductNameWithHwModel(&host->family));
|
||||
|
||||
@@ -181,7 +181,7 @@ const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
|
||||
#ifdef __x86_64__
|
||||
bool ffHostDetectMac(FFHostResult* host)
|
||||
{
|
||||
if (ffStrbufEqualS(&host->family, "Mac") && ffStrbufEqualS(&host->vendor, "Apple Inc."))
|
||||
if (ffStrbufStartsWithS(&host->family, "Mac") && ffStrbufEqualS(&host->vendor, "Apple Inc."))
|
||||
{
|
||||
const char* productName = ffHostGetMacProductNameWithHwModel(&host->name);
|
||||
if (productName)
|
||||
|
||||
@@ -7,7 +7,7 @@ const char* ffDetectIcons(FFIconsResult* result)
|
||||
{
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
|
||||
if(ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY))
|
||||
return "Icons aren't supported in TTY";
|
||||
|
||||
const FFstrbuf* plasma = &ffDetectQt()->icons;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user