Compare commits

..

39 Commits

Author SHA1 Message Date
Carter Li de18a07938 Release: v2.52.0 2025-09-05 13:04:53 +08:00
李通洲 88147f80ac Doc: update changelog 2025-09-05 12:38:14 +08:00
李通洲 505ff6ff65 Global: renames fractionTrailingZeros enum to always/never for consistance 2025-09-05 12:27:03 +08:00
李通洲 390549394d Fastfetch: removes redundant assignment in display config parsing
found by copilot
2025-09-05 11:08:37 +08:00
Carter Li f7e7d54c16 Release: v2.52.0 2025-09-05 10:46:30 +08:00
Carter Li 5e068d22c8 Btrfs (Linux): refactors Btrfs allocation to use profile string
Fixes #1941
2025-09-05 10:46:23 +08:00
李通洲 b77646f23e Btrfs (Linux): adds tracking of Btrfs data copy counts
Fixes(?) #1941
2025-09-05 00:18:00 +08:00
李通洲 aa40366a49 Terminal: ignores WSL2 unknown process for terminal detection 2025-09-04 22:31:59 +08:00
Carter Li a64a82f215 WMTheme (Linux): supports labwc on XFCE4 2025-09-04 18:50:23 +08:00
Qing Yun 0a4d6220e9 CPU (Linux): add cpu name detection for ia64 2025-09-04 18:34:14 +08:00
李通洲 6b037c595f Doc: update README 2025-09-04 16:36:55 +08:00
李通洲 f628f5c382 Settings: renames GNOME settings accessor for clarity 2025-09-04 16:17:01 +08:00
李通洲 cf713e32e1 Wallpaper (Linux): improves XFCE wallpaper detection via property enumeration 2025-09-04 13:54:49 +08:00
Carter Li 7d08f81075 Settings: removes direct XFConf support in favor of DBus backend 2025-09-04 09:43:57 +08:00
Carter Li 8822653335 DBus: adds function ffDBusGetInt 2025-09-04 09:35:52 +08:00
李通洲 75ff054255 Dbus: adds 2nd argument to ffDBusGetMethodReply 2025-09-04 08:45:09 +08:00
李通洲 c51cc8ce6b CI: bump dependencies 2025-09-03 16:01:09 +08:00
李通洲 44e23412b5 Doc: update changelog 2025-09-03 16:01:09 +08:00
李通洲 59742bca00 Fastfetch: improves frequency display config validation and schema 2025-09-03 16:01:09 +08:00
李通洲 303edb97ce Fastfetch: add option --faction-trailing-zeros 2025-09-03 14:20:23 +08:00
李通洲 37ab380a6f Logo (Chafa): fixes setting logo.width with chafa
Regression in v2.51.0

Fixes #1947
2025-09-03 10:49:58 +08:00
Carter Li a06e245c34 JsonSchema: update 2025-09-03 09:58:50 +08:00
Carter Li 5de432b083 Fastfetch: defaults display.fraction.ndigits to 2 2025-09-03 09:58:40 +08:00
Carter Li 817285ac01 Fastfetch: informs users that module-specific CLI options are no longer supported
... and provides guidance on transitioning to JSON config
2025-09-03 09:36:16 +08:00
李通洲 8687505505 LocalIP (Linux): skips interfaces without IPs unless MAC display is enabled 2025-09-02 15:00:35 +08:00
李通洲 34c34d25c4 JsonConfig: fixes fractionNdigits will be incorrectly set to 0 when specifying null 2025-09-02 14:44:15 +08:00
李通洲 21b15ee944 Display: rearranges default format; removes scaled resolution 2025-09-02 14:15:37 +08:00
李通洲 8e0a65126e LocalIP: honors fractionTrailingZeros 2025-09-02 14:13:37 +08:00
李通洲 54d8b0a95d Global: adds configurable trailing zeros for double formatting 2025-09-02 14:12:58 +08:00
李通洲 48fc72e95c DisplayServer: improves display size rounding and argument clarity 2025-09-02 09:36:19 +08:00
Carter Li e3d6a85888 Display (Linux): detect scale factor for X11 2025-09-01 21:20:34 +08:00
李通洲 7d92da8829 Global (Android): enable X11 related stuff 2025-09-01 16:28:13 +08:00
李通洲 2f3a361b1f CMake: enable zlib on all platforms 2025-09-01 09:59:06 +08:00
李通洲 ac71f21e6c DisplayServer (Android): update WM name accurately
See #1933
2025-08-30 14:14:48 +08:00
李通洲 8d5316f6aa CMake (Android): link to libm
Fix #1939
2025-08-30 13:31:37 +08:00
Carter Li 1242fda66f Merge pull request #1938 from fastfetch-cli/dev
Release: v2.51.1
2025-08-29 14:05:34 +08:00
李通洲 5a2b618d27 Release: v2.51.1 2025-08-29 13:55:52 +08:00
李通洲 d836d7569f CPU (macOS): removes reliance on unavailable ARM capability headers on macOS
Fixes https://github.com/Homebrew/homebrew-core/pull/235425
2025-08-29 13:45:16 +08:00
Carter Li 8a412e6823 Packaging: update debian stuff [ci skip] 2025-08-29 08:56:30 +08:00
58 changed files with 1107 additions and 543 deletions
+13 -13
View File
@@ -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
@@ -83,7 +83,7 @@ jobs:
run: cat /proc/cpuinfo
- 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 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 directx-headers-dev
- name: install linuxbrew packages
run: |
@@ -152,7 +152,7 @@ jobs:
run: cat /proc/cpuinfo
- 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 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 directx-headers-dev libchafa-dev libddcutil-dev rpm
- name: install linuxbrew packages
run: |
@@ -216,7 +216,7 @@ jobs:
# 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
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -252,7 +252,7 @@ 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
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -287,7 +287,7 @@ jobs:
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
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-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
@@ -322,7 +322,7 @@ jobs:
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
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -357,7 +357,7 @@ jobs:
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
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -386,7 +386,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
@@ -560,7 +560,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,7 +596,7 @@ 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
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -665,7 +665,7 @@ 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 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 .
@@ -875,7 +875,7 @@ jobs:
- name: download artifacts
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
uses: actions/download-artifact@v4
uses: actions/download-artifact@v5
- name: create release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
+36
View File
@@ -1,3 +1,39 @@
# 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:
* Fix building on macOS 14 or older; no functional changes (CPU, macOS)
# 2.51.0
Changes:
+36 -24
View File
@@ -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.0
VERSION 2.52.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -60,25 +60,23 @@ 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)
@@ -86,6 +84,7 @@ cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND"
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)
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)
@@ -515,6 +514,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
@@ -575,6 +575,7 @@ if(LINUX)
)
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 +591,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 +599,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 +617,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,20 +627,21 @@ 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
@@ -665,6 +673,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
@@ -759,6 +768,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
@@ -841,6 +851,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
@@ -1069,6 +1080,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
@@ -1220,6 +1232,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
@@ -1525,10 +1538,6 @@ ff_lib_enable(DBUS
"dbus-1"
"DBus"
)
ff_lib_enable(XFCONF
"libxfconf-0"
"XFConf"
)
ff_lib_enable(SQLITE3
"sqlite3"
"SQLite3"
@@ -1728,6 +1737,9 @@ elseif(GNU)
PRIVATE "m"
)
elseif(ANDROID)
target_link_libraries(libfastfetch
PRIVATE "m"
)
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
if(HAVE_LIBANDROID_WORDEXP_STATIC)
target_link_libraries(libfastfetch
+6
View File
@@ -1,3 +1,9 @@
fastfetch (2.51.0) jammy; urgency=medium
* Update to 2.51.0
-- Carter Li <zhangsongcui@live.cn> Fri, 29 Aug 2025 08:55:03 +0800
fastfetch (2.50.2) jammy; urgency=medium
* Update to 2.50.2
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.50.2_source.buildinfo universe/utils optional
fastfetch_2.51.0_source.buildinfo universe/utils optional
+35 -4
View File
@@ -1290,10 +1290,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 +1342,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
}
}
+59
View File
@@ -10,6 +10,65 @@
#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
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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");
+1 -1
View File
@@ -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");
}
-3
View File
@@ -208,9 +208,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
+126 -52
View File
@@ -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>
+3 -1
View File
@@ -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
View File
@@ -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]);
+12
View File
@@ -846,6 +846,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",
+1 -1
View File
@@ -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";
+2 -1
View File
@@ -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
+33 -13
View File
@@ -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
+29 -45
View File
@@ -296,23 +296,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
}
#elif __APPLE__
#include <sys/sysctl.h>
#include <arm/cpu_capabilities_public.h>
#ifndef CAP_BIT_AdvSIMD
#define CAP_BIT_AdvSIMD 49
#endif
#ifndef CAP_BIT_AdvSIMD_HPFPCvt
#define CAP_BIT_AdvSIMD_HPFPCvt 50
#endif
#ifndef CAP_BIT_FEAT_CRC32
#define CAP_BIT_FEAT_CRC32 51
#endif
#ifndef CAP_BIT_FEAT_HBC
#define CAP_BIT_FEAT_HBC 64
#endif
#ifndef CAP_BIT_FEAT_CSSC
#define CAP_BIT_FEAT_CSSC 67
#endif
// #include <arm/cpu_capabilities_public.h> // Not available in macOS 14-
void ffCPUDetectByCpuid(FFCPUResult* cpu)
{
@@ -328,59 +312,59 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
cpu->march = "unknown";
// ARMv8-A
bool has_fp = FF_HAS_CAP(CAP_BIT_AdvSIMD_HPFPCvt); // Full FP16 support (implies FP/ASIMD)
bool has_asimd = FF_HAS_CAP(CAP_BIT_AdvSIMD); // Advanced SIMD (NEON)
bool has_fp = FF_HAS_CAP(50); /* CAP_BIT_AdvSIMD_HPFPCvt */ // Full FP16 support (implies FP/ASIMD)
bool has_asimd = FF_HAS_CAP(49); /* CAP_BIT_AdvSIMD */ // Advanced SIMD (NEON)
// ARMv8.1-A
bool has_lse = FF_HAS_CAP(CAP_BIT_FEAT_LSE); // Large System Extensions, optional in v8.0
bool has_crc32 = FF_HAS_CAP(CAP_BIT_FEAT_CRC32); // CRC32 instructions, optional in v8.0
bool has_rdm = FF_HAS_CAP(CAP_BIT_FEAT_RDM); // AdvSIMD rounding double multiply accumulate, optional in v8.0
bool has_lse = FF_HAS_CAP(6); /* CAP_BIT_FEAT_LSE */ // Large System Extensions, optional in v8.0
bool has_crc32 = FF_HAS_CAP(51); /* CAP_BIT_FEAT_CRC32 */ // CRC32 instructions, optional in v8.0
bool has_rdm = FF_HAS_CAP(5); /* CAP_BIT_FEAT_RDM */ // AdvSIMD rounding double multiply accumulate, optional in v8.0
// ARMv8.2-A
bool has_fp16 = FF_HAS_CAP(CAP_BIT_FEAT_FP16); // Half-precision FP support, optional
bool has_dpb = FF_HAS_CAP(CAP_BIT_FEAT_DPB); // DC CVAP, optional from v8.1
bool has_fp16 = FF_HAS_CAP(34); /* CAP_BIT_FEAT_FP16 */ // Half-precision FP support, optional
bool has_dpb = FF_HAS_CAP(22); /* CAP_BIT_FEAT_DPB */ // DC CVAP, optional from v8.1
// ARMv8.3-A
bool has_pauth = FF_HAS_CAP(CAP_BIT_FEAT_PAuth); // Pointer Authentication (PAC), optional from v8.2
bool has_lrcpc = FF_HAS_CAP(CAP_BIT_FEAT_LRCPC); // LDAPR/LR with RCPC semantics, optional from v8.2
bool has_fcma = FF_HAS_CAP(CAP_BIT_FEAT_FCMA); // Complex number multiply-add, optional from v8.2
bool has_jscvt = FF_HAS_CAP(CAP_BIT_FEAT_JSCVT); // JavaScript-style conversion (FJCVTZS), optional from v8.2
bool has_pauth = FF_HAS_CAP(19); /* CAP_BIT_FEAT_PAuth */ // Pointer Authentication (PAC), optional from v8.2
bool has_lrcpc = FF_HAS_CAP(15); /* CAP_BIT_FEAT_LRCPC */ // LDAPR/LR with RCPC semantics, optional from v8.2
bool has_fcma = FF_HAS_CAP(17); /* CAP_BIT_FEAT_FCMA */ // Complex number multiply-add, optional from v8.2
bool has_jscvt = FF_HAS_CAP(18); /* CAP_BIT_FEAT_JSCVT */ // JavaScript-style conversion (FJCVTZS), optional from v8.2
// ARMv8.4-A
bool has_lse2 = FF_HAS_CAP(CAP_BIT_FEAT_LSE2); // Large System Extensions version 2, optional from v8.2
bool has_dit = FF_HAS_CAP(CAP_BIT_FEAT_DIT); // Data Independent Timing, optional from v8.3
bool has_flagm = FF_HAS_CAP(CAP_BIT_FEAT_FlagM); // Flag manipulation (FMOV/FCVT), optional from v8.1
bool has_lrcpc2 = FF_HAS_CAP(CAP_BIT_FEAT_LRCPC2); // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
bool has_lse2 = FF_HAS_CAP(30); /* CAP_BIT_FEAT_LSE2 */ // Large System Extensions version 2, optional from v8.2
bool has_dit = FF_HAS_CAP(33); /* CAP_BIT_FEAT_DIT */ // Data Independent Timing, optional from v8.3
bool has_flagm = FF_HAS_CAP(0); /* CAP_BIT_FEAT_FlagM */ // Flag manipulation (FMOV/FCVT), optional from v8.1
bool has_lrcpc2 = FF_HAS_CAP(16); /* CAP_BIT_FEAT_LRCPC2 */ // Enhanced RCPC (LDAPUR/LDAPST), optional from v8.2
// ARMv8.5-A
bool has_bti = FF_HAS_CAP(CAP_BIT_FEAT_BTI); // Branch Target Identification, optional from v8.4
bool has_sb = FF_HAS_CAP(CAP_BIT_FEAT_SB); // Speculative Barrier, optional from v8.0
bool has_dpb2 = FF_HAS_CAP(CAP_BIT_FEAT_DPB2); // DC CVADP (DPB2), optional from v8.1
bool has_flagm2 = FF_HAS_CAP(CAP_BIT_FEAT_FlagM2); // Enhanced FlagM, optional from v8.4
bool has_frintts = FF_HAS_CAP(CAP_BIT_FEAT_FRINTTS); // Floating-point to integer instructions, optional from v8.4
bool has_bti = FF_HAS_CAP(36); /* CAP_BIT_FEAT_BTI */ // Branch Target Identification, optional from v8.4
bool has_sb = FF_HAS_CAP(13); /* CAP_BIT_FEAT_SB */ // Speculative Barrier, optional from v8.0
bool has_dpb2 = FF_HAS_CAP(23); /* CAP_BIT_FEAT_DPB2 */ // DC CVADP (DPB2), optional from v8.1
bool has_flagm2 = FF_HAS_CAP(1); /* CAP_BIT_FEAT_FlagM2 */ // Enhanced FlagM, optional from v8.4
bool has_frintts = FF_HAS_CAP(14); /* CAP_BIT_FEAT_FRINTTS */ // Floating-point to integer instructions, optional from v8.4
// ARMv9.0-A
bool has_sve2 = false; // Not exposed and not supported by Apple M4
bool has_sve2 = false; // Not exposed and not supported by Apple M4
// ARMv9.1-A
// ARMv8.6-A
bool has_bf16 = FF_HAS_CAP(CAP_BIT_FEAT_BF16); // Brain float16, optional from v8.2
bool has_i8mm = FF_HAS_CAP(CAP_BIT_FEAT_I8MM); // Int8 Matrix Multiply, optional from v8.1
bool has_bf16 = FF_HAS_CAP(24); /* CAP_BIT_FEAT_BF16 */ // Brain float16, optional from v8.2
bool has_i8mm = FF_HAS_CAP(25); /* CAP_BIT_FEAT_I8MM */ // Int8 Matrix Multiply, optional from v8.1
// ARMv8.7-A
bool has_afp = FF_HAS_CAP(CAP_BIT_FEAT_AFP); // Alternate FP16 (FEXPA), optional from v8.6
bool has_afp = FF_HAS_CAP(29); /* CAP_BIT_FEAT_AFP */ // Alternate FP16 (FEXPA), optional from v8.6
// ARMv9.2-A
bool has_sme = FF_HAS_CAP(CAP_BIT_FEAT_SME); // Scalable Matrix Extension, optional from v9.2
bool has_sme = FF_HAS_CAP(40); /* CAP_BIT_FEAT_SME */ // Scalable Matrix Extension, optional from v9.2
// ARMv9.3-A
bool has_sme2 = FF_HAS_CAP(CAP_BIT_FEAT_SME2); // SME2, optional from v9.2
bool has_sme2 = FF_HAS_CAP(41); /* CAP_BIT_FEAT_SME2 */ // SME2, optional from v9.2
// ARMv8.8-A
bool has_hbc = FF_HAS_CAP(CAP_BIT_FEAT_HBC); // Hinted conditional branches, optional from v8.7
bool has_hbc = FF_HAS_CAP(64); /* CAP_BIT_FEAT_HBC */ // Hinted conditional branches, optional from v8.7
// ARMv8.9-A
bool has_cssc = FF_HAS_CAP(CAP_BIT_FEAT_CSSC); // Common Short String Compare, optional from v8.7
bool has_cssc = FF_HAS_CAP(67); /* CAP_BIT_FEAT_CSSC */ // Common Short String Compare, optional from v8.7
// ARMv9.4-A+ are not exposed yet
+4
View File
@@ -353,6 +353,10 @@ 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)) ||
#else
(cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) ||
(cpu->name.length == 0 && ffParsePropLine(line, "model :", &cpu->name)) ||
@@ -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,
@@ -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,
@@ -147,8 +142,19 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
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);
@@ -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;
}
+3 -6
View File
@@ -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,
@@ -220,8 +220,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,
+6 -1
View File
@@ -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)
+100 -100
View File
@@ -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) crtcInfoReply->width,
(uint32_t) 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,
"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"
+49 -40
View File
@@ -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,
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,
@@ -159,19 +152,23 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
"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)
+1 -1
View File
@@ -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;
+33 -28
View File
@@ -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);
+1 -1
View File
@@ -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;
+7
View File
@@ -414,6 +414,13 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
FF_DEBUG("Processing adapter %s (IPv4 entries: %u, IPv6 entries: %u)",
adapter->mac->ifa_name, adapter->ipv4.length, adapter->ipv6.length);
if (adapter->ipv4.length == 0 && adapter->ipv6.length == 0 &&
!(options->showType & FF_LOCALIP_TYPE_MAC_BIT) )
{
FF_DEBUG("Skipping interface %s (no IP addresses)", adapter->mac->ifa_name);
continue;
}
FFLocalIpResult* item = FF_LIST_ADD(FFLocalIpResult, *results);
ffStrbufInitS(&item->name, adapter->mac->ifa_name);
ffStrbufInit(&item->ipv4);
+1 -1
View File
@@ -191,7 +191,7 @@ static void getBestBus(FFDBusData* data, FFMediaResult* result)
getBusProperties(data, FF_DBUS_MPRIS_PREFIX "plasma-browser-integration", result)
) return;
DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL);
DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL, NULL);
if(reply == NULL)
return;
+1 -1
View File
@@ -266,7 +266,7 @@ static bool detectRio(FFTerminalFontResult* terminalFont)
return true;
}
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont);
bool ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont);
static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
@@ -13,6 +13,12 @@
const char* detectTermux(FFTerminalFontResult* terminalFont)
{
if(!ffPathExists(FF_TERMUX_FONT_PATH, FF_PATHTYPE_FILE))
{
ffFontInitCopy(&terminalFont->font, "monospace");
return NULL;
}
#ifdef FF_HAVE_FREETYPE
FF_LIBRARY_LOAD(freetype, "dlopen libfreetype"FF_LIBRARY_EXTENSION " failed", "libfreetype"FF_LIBRARY_EXTENSION, 2)
@@ -53,19 +59,15 @@ exit:
#endif
}
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
bool ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufCompS(&terminal->processName, "com.termux") != 0)
if(ffStrbufEqualS(&terminal->processName, "com.termux"))
ffStrbufSetS(&terminalFont->error, detectTermux(terminalFont));
else
{
ffStrbufSetS(&terminalFont->error, "Unsupported terminal");
return;
bool ffDetectTerminalFontPlatformLinux(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont);
return ffDetectTerminalFontPlatformLinux(terminal, terminalFont);
}
if(!ffPathExists(FF_TERMUX_FONT_PATH, FF_PATHTYPE_FILE))
{
ffFontInitCopy(&terminalFont->font, "monospace");
return;
}
ffStrbufSetS(&terminalFont->error, detectTermux(terminalFont));
return true;
}
@@ -91,7 +91,7 @@ static void detectWarpTerminal(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, fontName.UTF8String, fontSize.UTF8String);
}
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
bool ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseEqualS(&terminal->processName, "iterm.app") ||
ffStrbufStartsWithIgnCaseS(&terminal->processName, "iTermServer-"))
@@ -100,4 +100,7 @@ void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFo
detectAppleTerminal(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "WarpTerminal"))
detectWarpTerminal(terminalFont);
else
return false;
return true;
}
@@ -16,26 +16,26 @@ static const char* getSystemMonospaceFont(void)
if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, "Cinnamon"))
{
const char* systemMonospaceFont = ffSettingsGet("/org/cinnamon/desktop/interface/monospace-font-name", "org.cinnamon.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue;
const char* systemMonospaceFont = ffSettingsGetGnome("/org/cinnamon/desktop/interface/monospace-font-name", "org.cinnamon.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue;
if(ffStrSet(systemMonospaceFont))
return systemMonospaceFont;
}
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, "Mate"))
{
const char* systemMonospaceFont = ffSettingsGet("/org/mate/interface/monospace-font-name", "org.mate.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue;
const char* systemMonospaceFont = ffSettingsGetGnome("/org/mate/interface/monospace-font-name", "org.mate.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue;
if(ffStrSet(systemMonospaceFont))
return systemMonospaceFont;
}
return ffSettingsGet("/org/gnome/desktop/interface/monospace-font-name", "org.gnome.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue;
return ffSettingsGetGnome("/org/gnome/desktop/interface/monospace-font-name", "org.gnome.desktop.interface", NULL, "monospace-font-name", FF_VARIANT_TYPE_STRING).strValue;
}
static void detectKgx(FFTerminalFontResult* terminalFont)
{
// kgx (gnome console) doesn't support profiles
if(!ffSettingsGet("/org/gnome/Console/use-system-font", "org.gnome.Console", NULL, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue)
if(!ffSettingsGetGnome("/org/gnome/Console/use-system-font", "org.gnome.Console", NULL, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue)
{
FF_AUTO_FREE const char* fontName = ffSettingsGet("/org/gnome/Console/custom-font", "org.gnome.Console", NULL, "custom-font", FF_VARIANT_TYPE_STRING).strValue;
FF_AUTO_FREE const char* fontName = ffSettingsGetGnome("/org/gnome/Console/custom-font", "org.gnome.Console", NULL, "custom-font", FF_VARIANT_TYPE_STRING).strValue;
if(ffStrSet(fontName))
ffFontInitPango(&terminalFont->font, fontName);
else
@@ -53,9 +53,9 @@ static void detectKgx(FFTerminalFontResult* terminalFont)
static void detectPtyxis(FFTerminalFontResult* terminalFont)
{
if(!ffSettingsGet("/org/gnome/Ptyxis/use-system-font", "org.gnome.Ptyxis", NULL, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue)
if(!ffSettingsGetGnome("/org/gnome/Ptyxis/use-system-font", "org.gnome.Ptyxis", NULL, "use-system-font", FF_VARIANT_TYPE_BOOL).boolValue)
{
FF_AUTO_FREE const char* fontName = ffSettingsGet("/org/gnome/Ptyxis/font-name", "org.gnome.Ptyxis", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
FF_AUTO_FREE const char* fontName = ffSettingsGetGnome("/org/gnome/Ptyxis/font-name", "org.gnome.Ptyxis", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue;
if(ffStrSet(fontName))
ffFontInitPango(&terminalFont->font, fontName);
else
@@ -167,7 +167,7 @@ static void detectXFCETerminal(FFTerminalFontResult* terminalFont)
});
}
if(configFound && (useSysFont.length == 0 || ffStrbufIgnCaseCompS(&useSysFont, "false") == 0))
if(configFound && (useSysFont.length == 0 || ffStrbufIgnCaseEqualS(&useSysFont, "false")))
{
if(fontName.length == 0)
ffStrbufAppendF(&terminalFont->error, "Couldn't find FontName in %s", path);
@@ -433,7 +433,13 @@ static void detectHaikuTerminal(FFTerminalFontResult* terminalFont)
}
#endif
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
bool
#ifdef __ANDROID__
ffDetectTerminalFontPlatformLinux
#else
ffDetectTerminalFontPlatform
#endif
(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseEqualS(&terminal->processName, "konsole"))
detectKonsole(terminalFont, "konsolerc");
@@ -477,4 +483,7 @@ void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFo
#endif
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "termite"))
detectFromConfigFile("termite/config", "font =", terminalFont);
else
return false;
return true;
}
@@ -274,7 +274,7 @@ static void detectWarp(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
}
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
bool ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseEqualS(&terminal->processName, "Windows Terminal") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "WindowsTerminal.exe"))
@@ -287,4 +287,7 @@ void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFo
detectConEmu(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "warp"))
detectWarp(terminalFont);
else
return false;
return true;
}
@@ -111,6 +111,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "proot") ||
ffStrbufEqualS(&result->processName, "script") ||
#ifdef __linux__
ffStrbufStartsWithS(&result->processName, "Relay(") || // Unknown process in WSL2
ffStrbufStartsWithS(&result->processName, "flatpak-") || // #707
#endif
ffStrbufEndsWithS(&result->processName, ".sh")
+1 -1
View File
@@ -7,7 +7,7 @@ const char* ffDetectTheme(FFThemeResult* result)
{
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
if(ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY))
return "Theme isn't supported in TTY";
const FFQtResult* plasma = ffDetectQt();
+1 -1
View File
@@ -57,7 +57,7 @@ static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer)
{
FF_DEBUG("Getting device by IP interface name");
DBusMessage* device = ffDBusGetMethodReply(&dbus, "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", "GetDeviceByIpIface", item->inf.description.chars);
DBusMessage* device = ffDBusGetMethodReply(&dbus, "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", "GetDeviceByIpIface", item->inf.description.chars, NULL);
if(!device)
{
FF_DEBUG("GetDeviceByIpIface failed for interface %s", item->inf.description.chars);
+64 -53
View File
@@ -13,6 +13,17 @@ const char* ffDetectWMPlugin(FF_MAYBE_UNUSED FFstrbuf* pluginName)
return "Not supported on this platform";
}
static bool extractCommonWmVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
int count = 0;
sscanf(line, "%*d.%*d.%*d%n", &count);
if (count == 0) return true;
ffStrbufSetNS((FFstrbuf*) userdata, len, line);
return false;
}
#if !__ANDROID__
static bool extractHyprlandVersion(const char* line, uint32_t len, void *userdata)
{
if (line[0] != 'v') return true;
@@ -128,6 +139,48 @@ static const char* getSway(FFstrbuf* result)
return "Failed to run command `sway --version`";
}
static const char* getLabwc(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("labwc", &path);
if (error) return "Failed to find labwc executable path";
ffBinaryExtractStrings(path.chars, extractCommonWmVersion, result, (uint32_t) strlen("0.0.0"));
if (result->length > 0) return NULL;
if (ffProcessAppendStdOut(result, (char* const[]){
path.chars,
"--version",
NULL
}) == NULL)
{ // labwc 0.9.0 (+xwayland +nls +rsvg +libsfdo)
ffStrbufSubstrAfterFirstC(result, ' ');
ffStrbufSubstrBeforeFirstC(result, ' ');
return NULL;
}
return "Failed to run command `labwc --version`";
}
#ifdef __linux__
static const char* getWslg(FFstrbuf* result)
{
if (!ffAppendFileBuffer("/mnt/wslg/versions.txt", result))
return "Failed to read /mnt/wslg/versions.txt";
if (!ffStrbufStartsWithS(result, "WSLg "))
return "Failed to find WSLg version";
ffStrbufSubstrBeforeFirstC(result, '\n');
ffStrbufSubstrBeforeFirstC(result, '+');
ffStrbufSubstrAfterFirstC(result, ':');
ffStrbufTrimLeft(result, ' ');
return NULL;
}
#endif
#endif // !__ANDROID__
static bool extractI3Version(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
int count = 0;
@@ -161,31 +214,6 @@ static const char* getI3(FFstrbuf* result)
return "Failed to run command `i3 --version`";
}
static const char* getWslg(FFstrbuf* result)
{
if (!ffAppendFileBuffer("/mnt/wslg/versions.txt", result))
return "Failed to read /mnt/wslg/versions.txt";
if (!ffStrbufStartsWithS(result, "WSLg "))
return "Failed to find WSLg version";
ffStrbufSubstrBeforeFirstC(result, '\n');
ffStrbufSubstrBeforeFirstC(result, '+');
ffStrbufSubstrAfterFirstC(result, ':');
ffStrbufTrimLeft(result, ' ');
return NULL;
}
static bool extractCommonWmVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
int count = 0;
sscanf(line, "%*d.%*d.%*d%n", &count);
if (count == 0) return true;
ffStrbufSetNS((FFstrbuf*) userdata, len, line);
return false;
}
static const char* getCtwm(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
@@ -255,45 +283,31 @@ static const char* getOpenbox(FFstrbuf* result)
return "Failed to run command `openbox --version`";
}
static const char* getLabwc(FFstrbuf* result)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
const char* error = ffFindExecutableInPath("labwc", &path);
if (error) return "Failed to find labwc executable path";
ffBinaryExtractStrings(path.chars, extractCommonWmVersion, result, (uint32_t) strlen("0.0.0"));
if (result->length > 0) return NULL;
if (ffProcessAppendStdOut(result, (char* const[]){
path.chars,
"--version",
NULL
}) == NULL)
{ // labwc 0.9.0 (+xwayland +nls +rsvg +libsfdo)
ffStrbufSubstrAfterFirstC(result, ' ');
ffStrbufSubstrBeforeFirstC(result, ' ');
return NULL;
}
return "Failed to run command `labwc --version`";
}
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
{
if (!wmName)
return "No WM detected";
#if !__ANDROID__
// Wayland compositors
if (ffStrbufIgnCaseEqualS(wmName, "Hyprland"))
return getHyprland(result);
if (ffStrbufEqualS(wmName, "sway"))
return getSway(result);
if (ffStrbufEqualS(wmName, "i3"))
return getI3(result);
if (ffStrbufEqualS(wmName, "labwc"))
return getLabwc(result);
#if __linux__
if (ffStrbufEqualS(wmName, "WSLg"))
return getWslg(result);
#endif
#endif
// X11 WMs
if (ffStrbufEqualS(wmName, "i3"))
return getI3(result);
if (ffStrbufEqualS(wmName, "ctwm"))
return getCtwm(result);
@@ -304,8 +318,5 @@ const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE
if (ffStrbufEqualS(wmName, "Openbox"))
return getOpenbox(result);
if (ffStrbufEqualS(wmName, "labwc"))
return getLabwc(result);
return "Unsupported WM";
}
+16 -13
View File
@@ -44,7 +44,7 @@ static bool detectWMThemeFromConfigFile(const char* configFile, const char* them
static bool detectWMThemeFromSettings(const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFstrbuf* themeOrError)
{
const char* theme = ffSettingsGet(dconfKey, gsettingsSchemaName, gsettingsPath, gsettingsKey, FF_VARIANT_TYPE_STRING).strValue;
const char* theme = ffSettingsGetGnome(dconfKey, gsettingsSchemaName, gsettingsPath, gsettingsKey, FF_VARIANT_TYPE_STRING).strValue;
if(!ffStrSet(theme))
{
@@ -80,7 +80,7 @@ ok:
static bool detectMutter(FFstrbuf* themeOrError)
{
const char* theme = ffSettingsGet("/org/gnome/shell/extensions/user-theme/name", "org.gnome.shell.extensions.user-theme", NULL, "name", FF_VARIANT_TYPE_STRING).strValue;
const char* theme = ffSettingsGetGnome("/org/gnome/shell/extensions/user-theme/name", "org.gnome.shell.extensions.user-theme", NULL, "name", FF_VARIANT_TYPE_STRING).strValue;
if(ffStrSet(theme))
{
ffStrbufAppendS(themeOrError, theme);
@@ -92,8 +92,8 @@ static bool detectMutter(FFstrbuf* themeOrError)
static bool detectMuffin(FFstrbuf* themeOrError)
{
FF_AUTO_FREE const char* name = ffSettingsGet("/org/cinnamon/theme/name", "org.cinnamon.theme", NULL, "name", FF_VARIANT_TYPE_STRING).strValue;
FF_AUTO_FREE const char* theme = ffSettingsGet("/org/cinnamon/desktop/wm/preferences/theme", "org.cinnamon.desktop.wm.preferences", NULL, "theme", FF_VARIANT_TYPE_STRING).strValue;
FF_AUTO_FREE const char* name = ffSettingsGetGnome("/org/cinnamon/theme/name", "org.cinnamon.theme", NULL, "name", FF_VARIANT_TYPE_STRING).strValue;
FF_AUTO_FREE const char* theme = ffSettingsGetGnome("/org/cinnamon/desktop/wm/preferences/theme", "org.cinnamon.desktop.wm.preferences", NULL, "theme", FF_VARIANT_TYPE_STRING).strValue;
if(name == NULL && theme == NULL)
{
@@ -135,9 +135,9 @@ static bool detectOpenbox(const FFstrbuf* dePrettyName, FFstrbuf* themeOrError)
{
FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateA(64);
const char *configFileSubpath = "openbox/rc.xml";
if (ffStrbufIgnCaseCompS(dePrettyName, "LXQt") == 0)
if (ffStrbufIgnCaseEqualS(dePrettyName, "LXQt"))
configFileSubpath = "openbox/lxqt-rc.xml";
else if (ffStrbufIgnCaseCompS(dePrettyName, "LXDE") == 0)
else if (ffStrbufIgnCaseEqualS(dePrettyName, "LXDE"))
configFileSubpath = "openbox/lxde-rc.xml";
if (!ffSearchUserConfigFile(&instance.state.platform.configDirs, configFileSubpath, &absolutePath))
@@ -197,16 +197,19 @@ bool ffDetectWmTheme(FFstrbuf* themeOrError)
return false;
}
if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_KWIN) == 0)
if(ffStrbufIgnCaseEqualS(&wm->wmPrettyName, FF_WM_PRETTY_KWIN))
return detectWMThemeFromConfigFile("kwinrc", "theme =", "Breeze", themeOrError);
if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_XFWM4) == 0)
if(
ffStrbufIgnCaseEqualS(&wm->wmPrettyName, FF_WM_PRETTY_XFWM4) ||
(ffStrbufIgnCaseEqualS(&wm->wmPrettyName, "labwc") && ffStrbufIgnCaseEqualS(&wm->dePrettyName, FF_DE_PRETTY_XFCE4))
)
return detectXFWM4(themeOrError);
if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_MUTTER) == 0)
if(ffStrbufIgnCaseEqualS(&wm->wmPrettyName, FF_WM_PRETTY_MUTTER))
{
if(
ffStrbufIgnCaseCompS(&wm->dePrettyName, FF_DE_PRETTY_GNOME) == 0 ||
ffStrbufIgnCaseEqualS(&wm->dePrettyName, FF_DE_PRETTY_GNOME) ||
ffStrbufIgnCaseEqualS(&wm->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC)
)
return detectMutter(themeOrError);
@@ -214,13 +217,13 @@ bool ffDetectWmTheme(FFstrbuf* themeOrError)
return detectGTKThemeAsWMTheme(themeOrError);
}
if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_MUFFIN) == 0)
if(ffStrbufIgnCaseEqualS(&wm->wmPrettyName, FF_WM_PRETTY_MUFFIN))
return detectMuffin(themeOrError);
if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_MARCO) == 0)
if(ffStrbufIgnCaseEqualS(&wm->wmPrettyName, FF_WM_PRETTY_MARCO))
return detectWMThemeFromSettings("/org/mate/Marco/general/theme", "org.mate.Marco.general", NULL, "theme", themeOrError);
if(ffStrbufIgnCaseCompS(&wm->wmPrettyName, FF_WM_PRETTY_OPENBOX) == 0)
if(ffStrbufIgnCaseEqualS(&wm->wmPrettyName, FF_WM_PRETTY_OPENBOX))
return detectOpenbox(&wm->dePrettyName, themeOrError);
ffStrbufAppendS(themeOrError, "Unknown WM: ");
+2 -1
View File
@@ -681,7 +681,8 @@ static void parseOption(FFdata* data, const char* key, const char* value)
else if(
ffOptionsParseGeneralCommandLine(&instance.config.general, key, value) ||
ffOptionsParseLogoCommandLine(&instance.config.logo, key, value) ||
ffOptionsParseDisplayCommandLine(&instance.config.display, key, value)
ffOptionsParseDisplayCommandLine(&instance.config.display, key, value) ||
ffParseModuleOptions(key, value)
) {}
else
+2 -2
View File
@@ -114,7 +114,7 @@ static bool ffLogoPrintCharsRaw(const char* data, size_t length, bool printError
static uint32_t logoAppendChars(const char* data, bool doColorReplacement, FFstrbuf* result)
{
FFOptionsLogo* options = &instance.config.logo;
uint32_t currentlineLength = options->width;
uint32_t currentlineLength = options->type == FF_LOGO_TYPE_IMAGE_CHAFA ? 0 : options->width; // For chafa, unit of options->width is pixels
uint32_t logoHeight = 0;
if (result)
@@ -260,7 +260,7 @@ static uint32_t logoAppendChars(const char* data, bool doColorReplacement, FFstr
if(currentlineLength > instance.state.logoWidth)
instance.state.logoWidth = currentlineLength;
return options->height > logoHeight ? options->height : logoHeight;
return options->type != FF_LOGO_TYPE_IMAGE_CHAFA && options->height > logoHeight ? options->height : logoHeight;
}
void ffLogoPrintChars(const char* data, bool doColorReplacement)
+5 -4
View File
@@ -27,9 +27,9 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i
}
uint64_t used = 0, allocated = 0, total = result->totalSize;
for (int i = 0; i < 3; ++i)
for (uint32_t i = 0; i < ARRAY_SIZE(result->allocation); ++i)
{
uint64_t times = result->allocation[i].dup ? 2 : 1;
uint64_t times = result->allocation[i].copies;
used += result->allocation[i].used * times;
allocated += result->allocation[i].total * times;
}
@@ -180,11 +180,12 @@ bool ffGenerateBtrfsJsonResult(FF_MAYBE_UNUSED FFBtrfsOptions* options, yyjson_m
yyjson_mut_obj_add_uint(doc, obj, "sectorSize", btrfs->sectorSize);
yyjson_mut_obj_add_uint(doc, obj, "totalSize", btrfs->totalSize);
yyjson_mut_val* allocation = yyjson_mut_obj_add_arr(doc, obj, "allocation");
for (int i = 0; i < 3; ++i)
for (uint32_t i = 0; i < ARRAY_SIZE(btrfs->allocation); ++i)
{
yyjson_mut_val* item = yyjson_mut_arr_add_obj(doc, allocation);
yyjson_mut_obj_add_str(doc, item, "type", btrfs->allocation[i].type);
yyjson_mut_obj_add_bool(doc, item, "dup", btrfs->allocation[i].dup);
yyjson_mut_obj_add_str(doc, item, "profile", btrfs->allocation[i].profile);
yyjson_mut_obj_add_uint(doc, item, "copies", btrfs->allocation[i].copies);
yyjson_mut_obj_add_uint(doc, item, "used", btrfs->allocation[i].used);
yyjson_mut_obj_add_uint(doc, item, "total", btrfs->allocation[i].total);
}
+16 -12
View File
@@ -101,6 +101,7 @@ bool ffPrintDisplay(FFDisplayOptions* options)
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4;
double scaleFactor = (double) result->height / (double) result->scaledHeight;
if(options->moduleArgs.outputFormat.length == 0)
{
@@ -108,23 +109,28 @@ bool ffPrintDisplay(FFDisplayOptions* options)
ffStrbufAppendF(&buffer, "%ix%i", result->width, result->height);
if(result->refreshRate > 0)
{
const char* space = instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "" : " ";
if(options->preciseRefreshRate)
ffStrbufAppendF(&buffer, " @ %g%sHz", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0, space);
else
ffStrbufAppendF(&buffer, " @ %i%sHz", (uint32_t) (result->refreshRate + 0.5), space);
}
if(
result->scaledWidth > 0 && result->scaledWidth != result->width &&
result->scaledHeight > 0 && result->scaledHeight != result->height)
ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight);
{
ffStrbufAppendS(&buffer, " @ ");
ffStrbufAppendDouble(&buffer, scaleFactor, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros == FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS);
ffStrbufAppendC(&buffer, 'x');
}
if (inch > 1)
ffStrbufAppendF(&buffer, " in %i\"", (uint32_t) (inch + 0.5));
if(result->refreshRate > 0)
{
ffStrbufAppendS(&buffer, ", ");
if(options->preciseRefreshRate)
ffStrbufAppendDouble(&buffer, result->refreshRate, 3, false);
else
ffStrbufAppendSInt(&buffer, (int) (result->refreshRate + 0.5));
ffStrbufAppendS(&buffer, instance.config.display.freqSpaceBeforeUnit == FF_SPACE_BEFORE_UNIT_NEVER ? "Hz" : " Hz");
}
bool flag = false;
if (result->type != FF_DISPLAY_TYPE_UNKNOWN)
{
@@ -185,8 +191,6 @@ bool ffPrintDisplay(FFDisplayOptions* options)
else
buf[0] = '\0';
double scaleFactor = (double) result->height / (double) result->scaledHeight;
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
FF_FORMAT_ARG(result->width, "width"),
FF_FORMAT_ARG(result->height, "height"),
+4 -8
View File
@@ -37,17 +37,13 @@ static void appendSpeed(FFLocalIpResult* ip, FFstrbuf* strbuf)
{
if (ip->speed >= 1000000)
{
if (instance.config.display.fractionNdigits >= 0)
ffStrbufAppendF(strbuf, "%.*f Tbps", instance.config.display.fractionNdigits, ip->speed / 1000000.0);
else
ffStrbufAppendF(strbuf, "%g Tbps", ip->speed / 1000000.0);
ffStrbufAppendDouble(strbuf, ip->speed / 1e6, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros == FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS);
ffStrbufAppendS(strbuf, " Tbps");
}
else if (ip->speed >= 1000)
{
if (instance.config.display.fractionNdigits >= 0)
ffStrbufAppendF(strbuf, "%.*f Gbps", instance.config.display.fractionNdigits, ip->speed / 1000.0);
else
ffStrbufAppendF(strbuf, "%g Gbps", ip->speed / 1000.0);
ffStrbufAppendDouble(strbuf, ip->speed / 1e3, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros == FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS);
ffStrbufAppendS(strbuf, " Gbps");
}
else
ffStrbufAppendF(strbuf, "%u Mbps", (unsigned) ip->speed);
+79 -8
View File
@@ -136,7 +136,15 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
}
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->sizeNdigits = (uint8_t) yyjson_get_uint(ndigits);
if (ndigits)
{
if (!yyjson_is_uint(ndigits))
return "display.size.ndigits must be an unsigned integer";
uint64_t val = yyjson_get_uint(ndigits);
if (val > 9)
return "display.size.ndigits must be between 0 and 9";
options->sizeNdigits = (uint8_t) val;
}
yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit");
if (spaceBeforeUnit)
@@ -177,7 +185,15 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
}
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->tempNdigits = (uint8_t) yyjson_get_uint(ndigits);
if (ndigits)
{
if (!yyjson_is_uint(ndigits))
return "display.temperature.ndigits must be an unsigned integer";
uint64_t val = yyjson_get_uint(ndigits);
if (val > 9)
return "display.temperature.ndigits must be between 0 and 9";
options->tempNdigits = (uint8_t) val;
}
yyjson_val* color = yyjson_obj_get(val, "color");
if (color)
@@ -222,7 +238,15 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
}
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->percentNdigits = (uint8_t) yyjson_get_uint(ndigits);
if (ndigits)
{
if (!yyjson_is_uint(ndigits))
return "display.percent.ndigits must be an unsigned integer";
uint64_t val = yyjson_get_uint(ndigits);
if (val > 9)
return "display.percent.ndigits must be between 0 and 9";
options->percentNdigits = (uint8_t) val;
}
yyjson_val* color = yyjson_obj_get(val, "color");
if (color)
@@ -376,9 +400,33 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
{
if (yyjson_is_null(ndigits))
options->fractionNdigits = -1;
else if (!yyjson_is_int(ndigits))
return "display.fraction.ndigits must be an integer";
options->fractionNdigits = (int8_t) yyjson_get_int(ndigits);
else
{
if (!yyjson_is_int(ndigits))
return "display.fraction.ndigits must be an integer";
int64_t val = yyjson_get_int(ndigits);
if (val < -1 || val > 9)
return "display.fraction.ndigits must be between -1 and 9";
options->fractionNdigits = (int8_t) val;
}
}
yyjson_val* trailingZeros = yyjson_obj_get(val, "trailingZeros");
if (trailingZeros)
{
if (yyjson_is_null(trailingZeros))
options->fractionTrailingZeros = FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT;
else
{
int value;
const char* error = ffJsonConfigParseEnum(trailingZeros, &value, (FFKeyValuePair[]) {
{ "default", FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT },
{ "always", FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS },
{ "never", FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER },
{},
});
if (error) return error;
options->fractionTrailingZeros = (FFFractionTrailingZerosType) value;
}
}
}
else
@@ -431,7 +479,20 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
return "display.freq must be an object";
yyjson_val* ndigits = yyjson_obj_get(val, "ndigits");
if (ndigits) options->freqNdigits = (int8_t) yyjson_get_int(ndigits);
if (ndigits)
{
if (yyjson_is_null(ndigits))
options->freqNdigits = -1;
else
{
if (!yyjson_is_int(ndigits))
return "display.freq.ndigits must be an integer";
int64_t val = yyjson_get_int(ndigits);
if (val < -1 || val > 9)
return "display.freq.ndigits must be between -1 and 9";
options->freqNdigits = (int8_t) val;
}
}
yyjson_val* spaceBeforeUnit = yyjson_obj_get(val, "spaceBeforeUnit");
if (spaceBeforeUnit)
@@ -690,6 +751,15 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key
}
else if(ffStrEqualsIgnCase(key, "--fraction-ndigits"))
options->fractionNdigits = (int8_t) ffOptionParseInt32(key, value);
else if(ffStrEqualsIgnCase(key, "--fraction-trailing-zeros"))
{
options->fractionTrailingZeros = (FFFractionTrailingZerosType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
{ "default", FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT },
{ "always", FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS },
{ "never", FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER },
{},
});
}
else if(ffStrEqualsIgnCase(key, "--no-buffer"))
options->noBuffer = ffOptionParseBoolean(value);
else if(ffStrStartsWithIgnCase(key, "--bar-"))
@@ -809,7 +879,8 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options)
options->freqNdigits = 2;
options->freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
options->fractionNdigits = -1;
options->fractionNdigits = 2;
options->fractionTrailingZeros = FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT;
ffListInit(&options->constants, sizeof(FFstrbuf));
}
+8
View File
@@ -25,6 +25,13 @@ typedef enum __attribute__((__packed__)) FFSpaceBeforeUnitType
FF_SPACE_BEFORE_UNIT_NEVER,
} FFSpaceBeforeUnitType;
typedef enum __attribute__((__packed__)) FFFractionTrailingZerosType
{
FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT,
FF_FRACTION_TRAILING_ZEROS_TYPE_ALWAYS,
FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER,
} FFFractionTrailingZerosType;
typedef struct FFOptionsDisplay
{
//If one of those is empty, ffLogoPrint will set them
@@ -81,6 +88,7 @@ typedef struct FFOptionsDisplay
int8_t freqNdigits;
FFSpaceBeforeUnitType freqSpaceBeforeUnit;
int8_t fractionNdigits;
FFFractionTrailingZerosType fractionTrailingZeros;
FFlist constants; // list of FFstrbuf
} FFOptionsDisplay;
+21 -10
View File
@@ -571,7 +571,7 @@ void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value)
strbuf->length += (uint32_t)(end - start);
}
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision)
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision, bool trailingZeros)
{
assert(precision <= 15); // yyjson_write_number supports up to 15 digits after the decimal point
@@ -598,18 +598,29 @@ void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision)
return;
}
if (precision > 1)
if (trailingZeros)
{
for (char* p = end - 1; *p != '.' && p > start; --p)
--precision;
if (precision > 0)
ffStrbufAppendNC(strbuf, (uint32_t) precision, '0');
if (precision > 1)
{
for (char* p = end - 1; *p != '.' && p > start; --p)
--precision;
if (precision > 0)
ffStrbufAppendNC(strbuf, (uint32_t) precision, '0');
}
else if (precision == 0 || (precision < 0 && end[-1] == '0'))
{
goto removeDecimalPoint;
}
}
else if (precision == 0 || (precision < 0 && end[-1] == '0'))
else
{
// yyjson always appends ".0", so we need to remove it
strbuf->length -= 2;
strbuf->chars[strbuf->length] = '\0';
if (end[-1] == '0')
{
removeDecimalPoint:
// yyjson always appends ".0" to make it a float point number. We need to remove it
strbuf->length -= 2;
strbuf->chars[strbuf->length] = '\0';
}
}
}
+1 -1
View File
@@ -107,7 +107,7 @@ void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value);
void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value);
// Appends a double value to the string buffer with the specified precision (0~15).
// if `precision < 0`, let yyjson decide the precision
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision);
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision, bool trailingZeros);
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
{
+143 -28
View File
@@ -744,115 +744,230 @@ int main(void)
}
{
ffStrbufAppendDouble(&strbuf, 120.0, 0);
ffStrbufAppendDouble(&strbuf, 120.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 1);
ffStrbufAppendDouble(&strbuf, 120.0, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 5);
ffStrbufAppendDouble(&strbuf, 120.0, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.00000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 5);
ffStrbufAppendDouble(&strbuf, 120.123456789, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.888888, 0);
ffStrbufAppendDouble(&strbuf, 120.888888, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.999999, 2);
ffStrbufAppendDouble(&strbuf, 120.999999, 2, true);
VERIFY(ffStrbufEqualS(&strbuf, "121.00"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 0);
ffStrbufAppendDouble(&strbuf, 120.123456789, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, -1);
ffStrbufAppendDouble(&strbuf, 120.123456789, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123, 5);
ffStrbufAppendDouble(&strbuf, 120.123, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.12300"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 0);
ffStrbufAppendDouble(&strbuf, -120.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 1);
ffStrbufAppendDouble(&strbuf, -120.0, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 5);
ffStrbufAppendDouble(&strbuf, -120.0, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.00000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 5);
ffStrbufAppendDouble(&strbuf, -120.123456789, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 0);
ffStrbufAppendDouble(&strbuf, -120.123456789, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, -1);
ffStrbufAppendDouble(&strbuf, -120.123456789, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123, 5);
ffStrbufAppendDouble(&strbuf, -120.123, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.12300"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.888888, 0);
ffStrbufAppendDouble(&strbuf, -120.888888, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.999999, 2);
ffStrbufAppendDouble(&strbuf, -120.999999, 2, true);
VERIFY(ffStrbufEqualS(&strbuf, "-121.00"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 1);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 1);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 0);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 0);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, -1);
ffStrbufAppendDouble(&strbuf, 1.2345e50, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, -1);
ffStrbufAppendDouble(&strbuf, -1.2345e50, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e20, 1);
ffStrbufAppendDouble(&strbuf, 1.2345e20, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "123450000000000000000.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e20, 1);
ffStrbufAppendDouble(&strbuf, -1.2345e20, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-123450000000000000000.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, +0.0, 0);
ffStrbufAppendDouble(&strbuf, +0.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -0.0, 0);
ffStrbufAppendDouble(&strbuf, -0.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-0"));
ffStrbufDestroy(&strbuf);
}
{
ffStrbufAppendDouble(&strbuf, 120.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.888888, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.999999, 2, false);
VERIFY(ffStrbufEqualS(&strbuf, "121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "120.123"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120.123"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.888888, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.999999, 2, false);
VERIFY(ffStrbufEqualS(&strbuf, "-121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e20, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "123450000000000000000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e20, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-123450000000000000000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, +0.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -0.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-0"));
ffStrbufDestroy(&strbuf);