Compare commits

...

276 Commits

Author SHA1 Message Date
Carter Li a9f43ff466 Packaging: update debian stuff 2025-12-18 15:00:51 +08:00
Carter Li 924d78d3c4 Release: v2.56.1 (#2097)
* Logo (Builtin): drop opak

Ref: #1070

* Swap (Windows): adds `K32GetPerformanceInfo` fallback

* Platform (Windows): fixes if checks

* Platform (Windows): adds a null check

* Packages (Windows): improves performance for directory enumeration

* Util (Windows): fixes / adds a new Unicode conversion function

* Packaging: update debian stuff [ci skip]

* IO (Windows): enhances `openat`

* CPU: adds option `tempSensor`

* CPU (macOS): supports `tempSensor`

* CPU (Windows): supports `tempSensor`

* CPU (Linux): supports `tempSensor`

* CPU (FreeBSD): supports `tempSensor`

* CPU (NetBSD): supports `tempSensor`

* CPU (OpenBSD): supports `tempSensor`

* CPU (Linux): prevents variables from integer overflow

* GPU (Linux): add comments

* CPU (SunOS): supports `tempSensor`

* Doc: clarifies that we supports illumos only

* JsonSchema: documents `cpu.tempSensor`

Fixes #2073

* CPUCache (macOS): fixes cache line size detection

* CPU(Linux): Fix build on GNU.

* Chore: refines usage of `PATH_MAX`

* DisplayServer (Linux): upgrades kde-output-device-v2 wayland protocol files (again)

Fixes #2093

* Logo (Builtin): adds gxde logo (#2094)

* add gxde-logo

* add gxdeos

* add gxdeos

* add gxdeos

* Release: v2.56.1

* Memory (macOS): uses `hw.memsize_usable`

* Chore (Windows): Standardize windows header casing. (#2096) [ci skip]

Followup to 0b6ca158ea.

Co-authored-by: Dariqq <dariqq@noreply.codeberg.org>

* IO (Windows): removes unneeded null terminator appending

* CPU (SunOS): adds `const` for consistancy

* Host (macOS): prefers `hw.product` than `hw.model`

... because `HW_MODEL` is deprecated

* Doc: update changelog

* Memory (macOS): Refines Memory usage detection on macOS to match Activity Monitor more closely

* Packages (Windows): fixes possible UB

Reported by Github Copilot

* JsonSchema: refines comments [ci skip]

---------

Co-authored-by: Yelninei <yelninei@tutamail.com>
Co-authored-by: gitee-zeqi <a202128502@163.com>
Co-authored-by: Dariqq <77271900+Dariqq@users.noreply.github.com>
Co-authored-by: Dariqq <dariqq@noreply.codeberg.org>
2025-12-18 14:46:24 +08:00
李通洲 fa92bb84ae JsonSchema: refines comments [ci skip] 2025-12-18 14:35:21 +08:00
李通洲 288d25e17c Packages (Windows): fixes possible UB
Reported by Github Copilot
2025-12-18 14:21:55 +08:00
李通洲 610fc2ea36 Memory (macOS): Refines Memory usage detection on macOS to match Activity Monitor more closely 2025-12-18 13:36:38 +08:00
李通洲 716c0e2b5c Doc: update changelog 2025-12-18 10:00:05 +08:00
李通洲 945aed7160 Host (macOS): prefers hw.product than hw.model
... because `HW_MODEL` is deprecated
2025-12-18 10:00:05 +08:00
李通洲 1d4d68f6e0 CPU (SunOS): adds const for consistancy 2025-12-17 14:30:07 +08:00
李通洲 3e1167260d IO (Windows): removes unneeded null terminator appending 2025-12-17 14:30:07 +08:00
Dariqq 0130f610e9 Chore (Windows): Standardize windows header casing. (#2096) [ci skip]
Followup to 0b6ca158ea.

Co-authored-by: Dariqq <dariqq@noreply.codeberg.org>
2025-12-16 18:53:26 -06:00
李通洲 94941daf4f Memory (macOS): uses hw.memsize_usable 2025-12-16 10:41:27 +08:00
李通洲 2bbd723321 Release: v2.56.1 2025-12-16 10:16:36 +08:00
gitee-zeqi 608382109c Logo (Builtin): adds gxde logo (#2094)
* add gxde-logo

* add gxdeos

* add gxdeos

* add gxdeos
2025-12-15 13:30:47 +08:00
李通洲 bdc5174f68 DisplayServer (Linux): upgrades kde-output-device-v2 wayland protocol files (again)
Fixes #2093
2025-12-15 13:25:26 +08:00
李通洲 bc869f1be9 Chore: refines usage of PATH_MAX 2025-12-12 09:03:18 +08:00
Yelninei dc69e44829 CPU(Linux): Fix build on GNU. 2025-12-11 21:32:45 +08:00
李通洲 d236850119 CPUCache (macOS): fixes cache line size detection 2025-12-11 14:38:06 +08:00
李通洲 60ec8c9097 JsonSchema: documents cpu.tempSensor
Fixes #2073
2025-12-11 14:37:28 +08:00
李通洲 42e7a7d2f7 Doc: clarifies that we supports illumos only 2025-12-11 14:28:12 +08:00
李通洲 e766809e3a CPU (SunOS): supports tempSensor 2025-12-11 14:24:07 +08:00
Carter Li cb1f0300b9 GPU (Linux): add comments 2025-12-11 09:52:50 +08:00
Carter Li f2a29309f3 CPU (Linux): prevents variables from integer overflow 2025-12-11 09:52:50 +08:00
李通洲 6e7b4bab75 CPU (OpenBSD): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 b4f39e251c CPU (NetBSD): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 af6196fe6e CPU (FreeBSD): supports tempSensor 2025-12-11 09:52:50 +08:00
Carter Li bca56b2049 CPU (Linux): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 f4401f172e CPU (Windows): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 c11b88fee5 CPU (macOS): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 88b1b558d7 CPU: adds option tempSensor 2025-12-11 09:52:50 +08:00
李通洲 ba6cdc77c9 IO (Windows): enhances openat 2025-12-11 09:52:50 +08:00
Carter Li b952772902 Packaging: update debian stuff [ci skip] 2025-12-11 09:52:50 +08:00
李通洲 7a322154fa Util (Windows): fixes / adds a new Unicode conversion function 2025-12-08 20:11:14 +08:00
李通洲 0b6ca158ea Packages (Windows): improves performance for directory enumeration 2025-12-08 16:42:14 +08:00
李通洲 100cd9a72b Platform (Windows): adds a null check 2025-12-08 09:49:54 +08:00
李通洲 98fb810f1f Platform (Windows): fixes if checks 2025-12-08 09:49:54 +08:00
李通洲 c613e558fd Swap (Windows): adds K32GetPerformanceInfo fallback 2025-12-08 09:49:41 +08:00
Carter Li c324f83826 Logo (Builtin): drop opak
Ref: #1070
2025-12-08 09:03:28 +08:00
Carter Li e50421a6ce Merge pull request #2083 from fastfetch-cli/dev
Release: v2.56.0
2025-12-05 22:42:51 +08:00
李通洲 417b944e1c Doc: updates changelog 2025-12-05 21:12:11 +08:00
李通洲 cb8b4b335d FFstrbuf: removes an unnecessary return 2025-12-05 21:10:19 +08:00
李通洲 c0160537b0 Zpool: fixes inconsistant CMake variables 2025-12-05 21:09:00 +08:00
李通洲 4cb7a6424a Logo (Builtin): tidy 2025-12-05 21:08:28 +08:00
李通洲 7d6c79d73e Doc: documents -c - 2025-12-05 10:41:18 +08:00
李通洲 8652737f64 Fastfetch: enhances config file loading with support for config directory
Fixes #2080
2025-12-05 10:32:42 +08:00
李通洲 d6ac89ea8d Release: v2.56.0 2025-12-04 16:15:20 +08:00
李通洲 2b620cf487 CI (SunOS): fixes a CI error 2025-12-04 16:15:20 +08:00
李通洲 f644df481c CPU: exposes numa node count in custom format 2025-12-04 15:21:27 +08:00
李通洲 e99ecacb52 Chore: adds ffIsValidNativeFD and uses it 2025-12-03 09:26:32 +08:00
李通洲 3e22dd4b0e Chore: uses _WIN32 always 2025-12-03 09:26:32 +08:00
Noa Himesaka 19f30ec687 Logo (Builtin): updates Codex Linux new logo (#2071)
* fix: Codex Linux new logo

reMarkable changed their logo so reflecting that change here too

* Modify ASCII art in codex.txt

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-12-03 09:09:07 +08:00
Alxhr0 76bee78200 Chore: fixes comment for AerynOS in builtin.c (#2078) 2025-12-03 09:00:09 +08:00
李通洲 ce7455d8f0 Zpool: allows disabling module 2025-12-01 17:20:50 +08:00
李通洲 5e27ee0f57 Shell: fixes ksh version detection on Linux 2025-12-01 10:04:40 +08:00
全てずんだもんの所爲です 84a5c6ebe8 Packages (Linux): add kiss packages count (#2072) 2025-11-30 19:10:07 -06:00
李通洲 ad7e23f64c TerminalFont: supports the newest Alacritty config format
Fixes #2070
2025-11-28 16:35:14 +08:00
李通洲 2738f20eea GPU (Linux): detect driver specific info for zhaoxin 2025-11-28 03:06:23 +00:00
李通洲 09362b236c Util (Windows): fixes compiling 2025-11-25 19:10:43 +08:00
Carter Li 3cfef81877 Users (Linux): always report the newest session info 2025-11-25 19:04:36 +08:00
Carter Li 3a04ae2542 Users (Linux): adds systemd fallback for user detection on Linux
Fixes #2064
2025-11-25 16:40:52 +08:00
Carter Li dbaf8a319d FFstrbuf: adds ffStrbufGetdelim(Restore) 2025-11-25 15:08:42 +08:00
Carter Li 2fe2a21bfe Terminal: reports sshd if $SSH_TTY is not available 2025-11-25 14:33:35 +08:00
Carter Li 37639c3582 Utils: inlines ffIsAbsolutePath 2025-11-25 14:33:35 +08:00
李通洲 9a74e6d7bc Users (Linux): adds missing endutxent 2025-11-25 14:32:36 +08:00
Carter Li 5d13389827 TerminalShell: uses absolute path when detecting version if available
Closes #2067
2025-11-25 09:10:30 +08:00
李通洲 1c2c6644d5 DE: adds Android OEM UI detection
Ref #1900
2025-11-24 15:17:52 +08:00
李通洲 ffcddf30e3 Logo: improve builtin logo printing for piping and buffering
Fixes #2065
2025-11-24 14:18:45 +08:00
李通洲 22c92c7b05 Doc: recommand Ubuntu PPA [ci skip] 2025-11-21 15:56:43 +08:00
李通洲 b569048010 CMake (SunOS): remove static link of libzfs 2025-11-21 15:56:43 +08:00
李通洲 f703d9ac89 Zpool: simplifies implementation by dropping platform-specific code 2025-11-20 18:18:25 +08:00
Steve Gilissen ed6abfd626 Logo (Builtin): adds OS/2 Warp logo (#2062)
* Add OS2 Warp logo

* Update ASCII art in os2warp.txt

* Refactor OS/2 Warp logo names for consistency

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-11-19 20:16:19 -06:00
李通洲 50388efc78 Zpool: uses runtime lookup for zpool properties to ensure portability
Fixes #2051
2025-11-19 20:26:18 +08:00
李通洲 7e8fb0fa14 Zpool: simplifies impl; exposes allocated/guid/readOnly 2025-11-19 19:27:19 +08:00
Steve Gilissen 9d70469665 Logo (Builtin): adds Amiga logo (#2061)
* Add Amiga logo

* Update ASCII art in amiga.txt

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-11-17 19:52:07 -06:00
李通洲 a94f0efb5b CPU: adds NUMA node detection 2025-11-18 09:30:47 +08:00
Carter Li da3a9be7c6 Packaging: update debian stuff [ci skip] 2025-11-18 09:11:54 +08:00
李通洲 cd8ab8e55a Command: Adds splitLines option 2025-11-17 11:01:32 +08:00
李通洲 1b5b32afad GPU (macOS): fixes a comment [ci skip] 2025-11-17 08:59:39 +08:00
Carter Li 917f784438 Merge pull request #2060 from fastfetch-cli/dev
Release: v2.55.1
2025-11-16 09:56:42 +08:00
李通洲 c2d5d5cca1 Release: v2.55.1 2025-11-16 09:29:24 +08:00
Carter Li b435738c34 CMake (macOS): corrects rpath addition for dlopen builds 2025-11-16 09:15:11 +08:00
apocelipes 934905e63a GPU: silence unused parameter warnings 2025-11-16 08:28:28 +08:00
apocelipes d15bb8a232 Display: fix an uninitialized FFDisplayOptions field 2025-11-15 22:34:33 +08:00
李通洲 c22bca1f87 Processing (Linux): blocks SIGCHLD and simplify poll error handling
Partially reverts e9ab67b380

Fixes #2056 & unfixes #1418
2025-11-15 19:34:13 +08:00
Carter Li e04cc9c9d5 Packaging: update debian changelog [ci skip] 2025-11-12 09:24:50 +08:00
Carter Li 7a2bf4e0ac Merge pull request #2049 from fastfetch-cli/dev
Releases: v2.55.0
2025-11-11 18:51:24 +08:00
李通洲 662f5127fa Shell: makes fish shell version detection more robust (v2) 2025-11-11 15:38:53 +08:00
李通洲 fb9117553b Shell: makes fish shell version detection more robust 2025-11-11 15:19:40 +08:00
李通洲 9f24e4363f Media (Linux): handles invalid percent-encoding in cover metadata 2025-11-11 15:16:12 +08:00
李通洲 084f9294f2 Media: updates naming convention from mediacover to media-cover for media cover logo sources 2025-11-11 14:42:55 +08:00
李通洲 a9f1f9a647 Doc: update changelog 2025-11-11 14:31:23 +08:00
李通洲 0aed89036b Chore: silenses some compiler warnings 2025-11-11 14:24:32 +08:00
李通洲 df15bbc5f2 Media: moves media cover cleanup logic to media detection 2025-11-11 14:00:43 +08:00
李通洲 e6b0bd3817 Media: fixes album cover serialization in JSON result 2025-11-11 13:58:45 +08:00
李通洲 11cd7153a2 Logo (Builtin): tidy [ci skip] 2025-11-11 13:53:34 +08:00
李通洲 f8bc1cb605 Releases: v2.55.0 2025-11-11 11:01:54 +08:00
李通洲 8b8eb6f290 TerminalShell (Linux): ignores run-parts
Ref: #2048
2025-11-11 10:10:47 +08:00
李通洲 056fe21ee2 Examples/25: removes parallel: true since we had it enabled by default [ci skip] 2025-11-11 10:07:58 +08:00
Carter Li cb0a88df22 [Command] enables parallel command execution by default 2025-11-11 09:28:44 +08:00
Carter Li 298c0431c3 Examples: improves clang version extraction method in 25.jsonc [ci skip] 2025-11-11 09:00:01 +08:00
Carter Li 448de9afa5 Command: makes compiler happy 2025-11-10 22:48:22 +08:00
Carter Li 9401a4b9ad Processing: adds a missing header 2025-11-10 18:09:19 +08:00
李通洲 ea92ad3785 Command: adds parallel and useStdErr options
Fixes #2045
2025-11-10 16:34:23 +08:00
李通洲 7aaad5e03e Processing: refactors process execution to separate spawning and reading 2025-11-10 16:34:23 +08:00
李通洲 645bf5c839 Disk: moves disk hiding by folder and FS type to detection code
Don't probe if hided

Fixes #2043
2025-11-06 13:39:30 +08:00
李通洲 7638e0e4a1 CMake: improves wordexp/glob detection and messaging 2025-11-05 10:21:05 +08:00
李通洲 302b8a7b1b CommandLine: adds dynamic output refresh support with interval option 2025-11-05 10:21:05 +08:00
李通洲 dbb9d8a660 Display: adds missing #include 2025-11-05 09:59:27 +08:00
李通洲 c51a164042 PublicIP / Weather: cleans up states after detection 2025-11-05 09:56:23 +08:00
李通洲 6b8a62da6e Linux (Host): improves Mac family detection by using prefix match 2025-11-04 09:12:35 +08:00
李通洲 578ca23e75 GPU (Hurd): adds support (requires libpciaccess) 2025-11-01 09:57:52 +00:00
李通洲 2e73a90835 GPU (OpenBSD): adds native GPU detection support 2025-11-01 17:23:59 +08:00
李通洲 cc6273fecc GPU (NetBSD): don't use system function name 2025-11-01 17:19:25 +08:00
李通洲 e63b777916 GPU: handles missing GPU type as null in JSON output 2025-11-01 16:44:36 +08:00
李通洲 907567f511 GPU (NetBSD): improves performance; drops libpciaccess dependency 2025-11-01 16:42:19 +08:00
李通洲 e0fd7308be Logo (Builtin): add Vincent OS
Fixes #2030
2025-10-31 11:04:18 +08:00
李通洲 b761034aae OS (Linux): prints debian version on Raspbery Pi OS
Fixes #2032
2025-10-31 11:04:18 +08:00
李通洲 04d6b1453d GPU (NetBSD): adds native GPU detection support 2025-10-31 11:04:18 +08:00
Carter Li 11d1754686 GPU: skips auxiliary display controllers
Fixes #2034
2025-10-30 14:46:30 +08:00
Carter Li 25e84decff GPU: unifies non-pci GPU device ID formatting across platforms 2025-10-30 11:01:06 +08:00
Carter Li 7d665b203f GPU: unifies GPU PCI device ID calculation logic across different platforms 2025-10-30 10:26:35 +08:00
李通洲 ac62442798 CMake: refines yyjson config and Apple rpath handling
Fixes #1998
2025-10-28 09:30:46 +08:00
李通洲 758f96de60 Icons (Windows): hides module when no icons are found
Fixes #2023
2025-10-24 14:46:09 +08:00
李通洲 db623b9c86 CI (Linux): adds Debian i386 packaging and verify deb package in CI
Fixes #2019
2025-10-22 17:45:50 +08:00
李通洲 c353bf3c96 Logo: adds automatic cleanup of temporary media cover files 2025-10-22 13:51:36 +08:00
李通洲 338b552499 Logo: adds support for using media cover as logo source 2025-10-21 15:05:25 +08:00
李通洲 5d73cc1232 Media: save media cover to temp file 2025-10-21 14:36:35 +08:00
李通洲 faddef7a3b Media (Windows): adds media cover extraction 2025-10-21 14:01:26 +08:00
Carter Li 2d9bbc8049 Media (Linux): adds media cover extraction 2025-10-21 09:44:36 +08:00
李通洲 64afaa07e7 Media (macOS): adds media cover extraction 2025-10-21 09:44:36 +08:00
李通洲 5cf3ab23b0 Utils (macOS): adds ffCfDictGetDataAsString 2025-10-21 08:49:34 +08:00
李通洲 3fe926d3a0 Doc: adds code-signing credit and privacy statement in README [ci skip]
As required by signpath
2025-10-20 23:43:32 +08:00
李通洲 f71bb682de Logo (Builtin): adds MacaroniOS
Fixes #2018
2025-10-20 15:12:11 +08:00
Carter Li 904f860f3c Packaging: builds for all Ubuntu versions [ci skip] 2025-10-20 14:58:23 +08:00
Carter Li 8f15c9604c Merge remote-tracking branch 'origin/master' into dev 2025-10-20 14:57:59 +08:00
李通洲 ff28f5807b Shell: supports brush version detection 2025-10-19 10:25:28 +08:00
李通洲 6a317366d7 Shell: fix fish version detection when LC_ALL is set
Fixes #2014
2025-10-19 10:25:28 +08:00
李通洲 dc3e4a2d18 JsonSchema: fixes copy-paste errors [ci skip]
Fixes #2013
2025-10-18 18:38:39 +08:00
Carter Li 46c4a71ba3 Merge pull request #2012 from fastfetch-cli/dev
Release: v2.54.0
2025-10-18 10:15:23 +08:00
Carter Li f0759acd11 Brightness (macOS): tidy 2025-10-18 09:35:34 +08:00
李通洲 96c7c2966d Brightness (macOS): prioritizes DDC/CI reply over simple I²C transaction 2025-10-18 01:11:03 +08:00
李通洲 554e7bce4a Logo (Builtin): adds Zraxyl
Fixes #1860
2025-10-18 00:56:14 +08:00
李通洲 70377a8afd Release: v2.54.0 2025-10-18 00:47:35 +08:00
李通洲 51bc6d421a CI (Windows): switches CI to use the release signing policy on the master branch 2025-10-18 00:47:35 +08:00
李通洲 be0756f8ba CMake: adds a new build option to gate wordexp usage and detection 2025-10-16 15:29:24 +08:00
李通洲 71a2cb4e1b Doc: adds security warning for Command module in README 2025-10-16 14:34:51 +08:00
李通洲 2eba761bed IO (OpenBSD): fixes incorrect glob usage 2025-10-16 14:33:53 +08:00
李通洲 4b5e1a816b Display (Windows): rename VRR to DRR 2025-10-16 13:24:44 +08:00
Dariqq a92e4b2d67 Chore (Windows): standardize more windows header casing.
Followup to 25353261d0
2025-10-14 15:49:06 +08:00
李通洲 a32404ba98 Doc: updates changelog 2025-10-14 14:51:44 +08:00
李通洲 0a792e4935 CPU (Android): adds detection support for Samsung Exynos SoCs 2025-10-14 14:49:29 +08:00
李通洲 05108977e8 CPU (Android): improves Android SoC vendor and model detection 2025-10-14 14:49:29 +08:00
李通洲 25353261d0 Chore (Windows): standardizes Windows header include casing. NOOP.
Fixes #2006
2025-10-14 09:10:24 +08:00
李通洲 4b517263d0 Chore (macOS): refactors code for better resource management 2025-10-13 14:27:23 +08:00
李通洲 98a65966e7 Doc: update changelog [ci skip] 2025-10-13 10:19:22 +08:00
李通洲 32dcf9487f Option: adds configurable spacing between icon and string keys
Fixes #2004
2025-10-13 09:54:34 +08:00
Carter Li e3a698f7b1 Brightness (macOS): fixes detection for external monitor on Intel platform 2025-10-11 21:26:37 +08:00
李通洲 1631f74700 Disk (Linux): revisits 78c6d71049 2025-10-11 18:20:56 +08:00
李通洲 78c6d71049 Disk (Linux): adds glob pattern matching for hidden disk folders
Fixes #1999
2025-10-11 16:19:11 +08:00
李通洲 0b9ecdeade Doc: adds Chinese README [ci skip] 2025-10-11 09:31:59 +08:00
李通洲 185a9211f1 Doc: update changelog 2025-10-10 15:09:25 +08:00
李通洲 24459b2fbf Brightness (macOS): enhance DDC/CI detection by enumerating all I2C buses 2025-10-10 14:24:11 +08:00
Carter Li 88c8dcb3e8 CPU (Linux): improves detection for T-Head CPU vendor
Ref: #1997
2025-10-10 10:55:12 +08:00
Carter Li f3a8fedf0a CPU (Linux): improves SoC name detection from device tree
Fixes #1997
2025-10-10 10:50:20 +08:00
李通洲 6b8b7c1a62 CI (Windows): signs PE files 2025-10-08 00:39:22 +08:00
李通洲 af26828f91 CPU (Linux): adds support for HP PA‑RISC & SuperH CPU architecture detection 2025-10-05 09:22:06 +08:00
李通洲 f4c43abbf7 Display (Windows): adds VRR status detection support 2025-10-05 09:17:30 +08:00
李通洲 e84739bff0 Logo (Builtin): update T2 2025-10-05 09:15:59 +08:00
李通洲 66aad0e4f1 Revert "Display (Windows): fixes incorrect refresh rate when VRR is enabled"
Doesn't work

This reverts commit 31ae7a642a.
2025-10-05 00:16:49 +08:00
Carter Li 77c43c0214 Display (Linux): prefer resolutions reported by randr mode info 2025-10-04 22:19:25 +08:00
李通洲 31ae7a642a Display (Windows): fixes incorrect refresh rate when VRR is enabled
Fixes #1994
2025-10-03 23:42:57 +08:00
Carter Li 1bbb21486c Disk (Linux): f* Android
Fixes #1993
2025-10-03 16:53:09 +08:00
李通洲 316d8ddf9b CI (Linux): disables post operations for polyfilled binaries
Fixes #1990
2025-10-03 12:16:15 +08:00
Carter Li 5d8c21a5ca Memory (Linux): fallbacks to calcuate ourselves when MemAvailable seems unreasonable
Fixes #1988
2025-10-02 07:39:20 +08:00
李通洲 240ba5c00c Platform (Windows): adds missing else for Wine version detection 2025-10-01 16:45:13 +08:00
Carter Li 554184ec72 OS (Windows): restores compatibility with WINE
Revert "OS (Windows): hard linking winbrand"

This reverts commit 4146bb6731.
2025-10-01 16:12:45 +08:00
李通洲 7a055a2254 CI: upgrades compiler versions 2025-10-01 10:07:28 +08:00
Carter Li 0a807ac1a3 TerminalFont (Linux): fixes default font size for ghostty
Fixes #1986
2025-10-01 08:09:04 +08:00
Carter Li 4d831c8c73 OS (Linux): don't change prettyName on Ubuntu development branch
Ref: #1483
2025-09-30 15:24:52 +08:00
李通洲 e6e78a7aae OS (macOS): improves OS detection accuracy and sets pretty name 2025-09-30 13:35:48 +08:00
李通洲 09bef5f41d OS (macOS): removes fallback parsing of legacy macOS license file
Doesn't work on Tahoe anymore
2025-09-30 13:22:00 +08:00
李通洲 e394efdd85 OS (macOS): trims whitespace from full user name 2025-09-30 13:19:58 +08:00
李通洲 c10b652a2e Swap (Windows): prevents integer overflow in swap size
Regression from 7ec0c664c5
2025-09-30 10:05:08 +08:00
李通洲 1594a69d6c Kernel (Windows): move kernel.displayVersion to OS.codeName 2025-09-30 10:01:01 +08:00
李通洲 9b1e318bd1 OS (Linux): sets code name for Ubuntu 2025-09-30 09:09:36 +08:00
李通洲 e292bf1dee OS (Linux): sets point release for Debian
Fixes #1985
2025-09-30 09:06:12 +08:00
李通洲 55a0c6e97d Logo (Builtin): adds EmperorOS
Fixes #1963
2025-09-29 10:07:26 +08:00
Rain Xelelo 8b8e4a40a4 Logo (Builtin): adds PrismLinux
Fixes #1983
2025-09-28 21:01:03 -05:00
李通洲 8be070998f Theme (Windows): moves Windows theme detection logic from DE to dedicated module
Like the last commit
2025-09-29 09:40:10 +08:00
李通洲 093f56a03d Theme (macOS): moves macOS theme detection logic from DE to dedicated module
The old behavior was inherited from neofetch. However `Aqua` and `Liquid Glass` are actually design language, not a DE. There is no DE on macOS.
2025-09-29 09:25:24 +08:00
李通洲 bd9744c27c CommandLine: adds --json flag as a shortcut for enabling JSON output 2025-09-28 15:07:45 +08:00
李通洲 adc25f4420 CI: adds Debian libc6 dependency to package config
Fixes #1981
2025-09-28 14:43:38 +08:00
李通洲 229fe7c7bf CMake: update contact info 2025-09-28 14:43:38 +08:00
李通洲 5d571752ae Chore: updates FUNDING info 2025-09-28 14:43:38 +08:00
李通洲 512ddfae6b Doc: adds padding check to logo request template 2025-09-28 09:40:48 +08:00
李通洲 7b689f94df Logo (Builtin): adds secureblue
Fixes #1979
2025-09-28 09:40:21 +08:00
李通洲 9eed149b09 CMake (Linux): adds i686 CI build and unify processor naming
Fixes #1978
2025-09-25 16:30:59 +08:00
李通洲 0f5d321df8 Chore: updates comments to use English descriptions 2025-09-24 10:11:02 +08:00
李通洲 4e84094fd8 CI (OpenBSD): updates CI workflow to upgrade packages before install 2025-09-23 16:41:18 +08:00
李通洲 7b9fce0189 CI (Linux): adds GCC 13 toolchain to CI build environment 2025-09-23 16:00:45 +08:00
李通洲 9ab5c33008 CI: fix release action 2025-09-23 10:19:55 +08:00
Carter Li 613b1d63f1 Packaging: updates debian stuff [ci skip] 2025-09-23 10:03:30 +08:00
Carter Li 8c86cafec7 Merge pull request #1976 from fastfetch-cli/dev
Release: v2.53.0
2025-09-23 09:55:28 +08:00
李通洲 4098cf51b3 Release: v2.53.0 2025-09-23 09:27:52 +08:00
李通洲 bfc23232f8 CPU (Android): adds support for new Qualcomm and MediaTek SoC codes 2025-09-23 09:13:10 +08:00
李通洲 483fba44dc Doc: update changelog [ci skip] 2025-09-22 16:40:10 +08:00
李通洲 851751f99d CPU (Linux): adds support for new ARM C1 series CPU part IDs
Follows changes of util-linux
2025-09-22 16:24:36 +08:00
李通洲 3e86130ddd Zpool: increase libzfs so version to 6
Fixes #1973
2025-09-22 14:32:19 +08:00
李通洲 350ffced13 CI: upgrades runner of intel macOS 2025-09-22 14:13:41 +08:00
李通洲 cdcdb78b97 CPU (Windows): refines ARMv8.4-A detection to require LSE2 2025-09-22 14:08:29 +08:00
Osama Albahrani 2ae9d01200 OS (Linux): Better Ubuntu flavor detection
- Fixes https://github.com/fastfetch-cli/fastfetch/issues/1974
2025-09-22 10:04:45 +08:00
李通洲 e95393750b Wifi (macOS): add (B)SSID detection back for Tohoe 26.0
Fixes #1874
2025-09-22 09:37:07 +08:00
李通洲 de9229697a TerminalFont: improve ghostty with command ghostty +show-config
Ref: #1972
2025-09-20 23:34:07 +08:00
NEOAPPS 9d23d28594 Logo (Builtin): update ObsidianOS logo (#1970)
* feat(logos): add new ObsidianOS logo

* feat(logos): update colors

* chore: remove internal paddings since they're not allowed
2025-09-20 23:02:25 +08:00
李通洲 57a4b9b6ed Disk: refactors mountpoint matching to use shared string utilities 2025-09-19 14:54:13 +08:00
李通洲 ef3989d18d CommandOption: refactors code with ffStrbufSeparatedContainIgnCaseS 2025-09-19 14:51:31 +08:00
李通洲 3079b44f63 FFstrbuf: adds more functions to match separated strings
1. ffStrbufMatchSeparatedIgnCaseNS
2. ffStrbufSeparatedContainNS
3. ffStrbufSeparatedContainNS
2025-09-19 14:34:27 +08:00
李通洲 403900639c Gamepad / Keyboard / Mouse: improves device error handling and memory cleanup 2025-09-19 13:36:02 +08:00
李通洲 0bb5b4cc9c Gamepad / Keyboard / Mouse: adds support to ignore input devices by name prefix
Fixes #1950
2025-09-19 11:00:18 +08:00
李通洲 1180eb55a4 Logo (Builtin): adds TempleOS
Fixes #1969
2025-09-19 09:46:23 +08:00
李通洲 f0e9caaf04 Disk: allows array input for disk folder and filesystem options 2025-09-18 14:51:00 +08:00
李通洲 2c22c3b0c0 CI (Windows): add chafa dependency 2025-09-18 13:44:51 +08:00
李通洲 e9065e15e8 TerminalFont: Improves Ghostty font config parsing with fallback font detection
Fixes #1967
2025-09-18 10:30:28 +08:00
李通洲 9e7816069b Revert "Logo (Builtin): add Starry Linux"
Ref: #1963

This reverts commit 4df4a1de78.
2025-09-17 16:09:05 +08:00
李通洲 82cdc4cd91 Disk (Linux): avoids invalid disk creation times before Linux epoch
Prevent fastfetch from printing invalid create date on Android
2025-09-17 15:37:51 +08:00
Carter Li 822ddc6dc6 Disk (Linux): replace statx(2) call to syscall(2) 2025-09-17 15:09:39 +08:00
李通洲 8bd171a9ff CI: adds glibc polyfill step for compatibility 2025-09-17 14:28:40 +08:00
李通洲 509d6bf30c CI: merge more jobs 2025-09-17 14:00:23 +08:00
李通洲 ab8a13b2d3 CI: update cmake version 2025-09-17 10:39:59 +08:00
Carter Li 3bcdcc5dbf CI: merge amd64 and aarch64 code with matrix 2025-09-16 16:28:45 +08:00
李通洲 38f4215a94 CPU (Windows): trims vendor string read from registry 2025-09-16 10:55:17 +08:00
李通洲 e3eec3f62a CPU (Windows): handles zero temperature data and refactors value use
Fixes #1960
2025-09-14 19:39:17 +08:00
李通洲 e025f28cdc Wifi (macOS): removes wdutil-based Wi-Fi detection code
Let's stop this hide and seek game.
2025-09-12 14:28:01 +08:00
李通洲 3ece4e3b4d Presets: add a new example [ci skip] 2025-09-12 14:11:41 +08:00
Carter Li 6d72a32d1d 3rdparty: upgrade widecharwidth 2025-09-11 14:54:25 +08:00
Carter Li 45be29bad3 CPU (Linux): replaces HWCAP defines with explicit bitmasks for ARM 2025-09-11 14:02:41 +08:00
李通洲 6f5e618341 CPU (Linux): add new ARM part numbers 2025-09-10 14:32:07 +08:00
李通洲 1abfa70237 LocalIP: adds IPv6 type selection for local IP display
`{ "type": "localip", "showIpv6": "ula" /* Show ULA only */ }`

Fixes #1459
2025-09-10 13:42:48 +08:00
李通洲 baaeef5ab5 Separator: uses widecharwidth for Unicode wcwidth and fixes issue that wchar_t on Windows is 2-byte length 2025-09-10 10:34:07 +08:00
李通洲 8eafec479e Separator: rename property length with times 2025-09-09 09:52:10 +08:00
李通洲 5f9e7c799a OpenGL (Windows): simplifies code by removing custom window proc
Adds more cleanups
2025-09-08 00:06:49 +08:00
Carter Li aeb1722eb9 Packaging: update debian stuff [ci skip] 2025-09-05 15:12:49 +08:00
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
216 changed files with 7315 additions and 2807 deletions
+3
View File
@@ -0,0 +1,3 @@
github: LinusDierheimer
ko_fi: carterli
custom: https://paypal.me/zhangsongcui
+2
View File
@@ -36,3 +36,5 @@ body:
required: true
- label: The ASCII art contains color codes, or the color codes are available in `os-release`
required: true
- label: The ASCII art contains no internal paddings (spaces at the start and the end of lines)
required: true
+152 -252
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
@@ -61,12 +61,19 @@ jobs:
- name: run tests
run: ctest --output-on-failure
linux-amd64:
name: Linux-amd64
runs-on: ubuntu-22.04
linux-hosts:
name: Linux-${{ matrix.arch }}
runs-on: ${{ matrix.runs-on }}
permissions:
security-events: write
contents: read
strategy:
matrix:
include:
- arch: amd64
runs-on: ubuntu-22.04
- arch: aarch64
runs-on: ubuntu-22.04-arm
outputs:
ffversion: ${{ steps.ffversion.outputs.ffversion }}
steps:
@@ -82,26 +89,31 @@ jobs:
- name: cat /proc/cpuinfo
run: cat /proc/cpuinfo
- name: add gcc-13 repo
run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev directx-headers-dev
run: sudo apt-get update && sudo apt-get install -y gcc-13 g++-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libchafa-dev directx-headers-dev rpm ninja-build
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
- name: Initialize CodeQL
if: matrix.arch == 'amd64'
uses: github/codeql-action/init@v3
with:
languages: c
- name: configure project
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
run: CC=gcc-13 CXX=g++-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
- name: build project
run: cmake --build . --target package --verbose -j4
- name: perform CodeQL analysis
if: matrix.arch == 'amd64'
uses: github/codeql-action/analyze@v3
- name: list features
@@ -126,15 +138,27 @@ jobs:
id: ffversion
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
- name: polyfill glibc
run: |
wget https://github.com/CarterLi/polyfill-glibc/releases/download/v0.0.1/polyfill-glibc-${{ matrix.arch }} -O polyfill-glibc
chmod +x polyfill-glibc
strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17
strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17
echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake
echo 'set(CPACK_PACKAGE_RELOCATABLE OFF)' >> CPackConfig.cmake
echo 'set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)")' >> CPackConfig.cmake
echo 'set(CPACK_RPM_SPEC_MORE_DEFINE "%global __os_install_post %{nil}")' >> CPackConfig.cmake
cpack -V
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-amd64
name: fastfetch-linux-${{ matrix.arch }}
path: ./fastfetch-*.*
linux-aarch64:
name: Linux-aarch64
runs-on: ubuntu-22.04-arm
linux-i686:
name: Linux-i686
runs-on: ubuntu-22.04
permissions:
security-events: write
contents: read
@@ -151,20 +175,29 @@ jobs:
- name: cat /proc/cpuinfo
run: cat /proc/cpuinfo
- name: add gcc-13 repo
run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev libchafa-dev libddcutil-dev rpm
run: sudo apt-get update && sudo apt-get install -y gcc-13 gcc-13-multilib libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev rpm ninja-build
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
- name: cmake version
run: cmake --version
- name: configure project
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
run: CC=gcc-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DCMAKE_C_FLAGS="-m32 -march=i686 -mtune=i686" -DCMAKE_SYSTEM_PROCESSOR_OVERRIDE=i686 -DCPACK_DEBIAN_PACKAGE_ARCHITECTURE=i386 -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_DIRECTX_HEADERS=Off .
- name: build project
run: cmake --build . --target package --verbose -j4
- name: check deb package
run: dpkg -I fastfetch-*.deb
- name: list features
run: ./fastfetch --list-features
@@ -183,14 +216,10 @@ jobs:
- name: run tests
run: ctest --output-on-failure
- name: get fastfetch version
id: ffversion
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-aarch64
name: fastfetch-linux-i686
path: ./fastfetch-*.*
linux-armv7l:
@@ -212,12 +241,13 @@ jobs:
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y wget
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
dpkg -i *.deb
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
apt-get update && apt-get install -y software-properties-common ca-certificates gpg curl
add-apt-repository -y ppa:ubuntu-toolchain-r/test
curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
echo -e 'Acquire::https::Verify-Peer "false";\nAcquire::https::Verify-Host "false";' >> /etc/apt/apt.conf.d/99ignore-certificates
apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
@@ -252,8 +282,8 @@ jobs:
run: |
uname -a
apt-get update && apt-get install -y wget
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
apt-get install -y cmake make gcc libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
@@ -268,12 +298,18 @@ jobs:
name: fastfetch-linux-armv6l
path: ./fastfetch-*.*
linux-riscv64:
name: Linux-riscv64
runs-on: ubuntu-24.04
linux-vms:
name: Linux-${{ matrix.arch }}
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
strategy:
matrix:
include:
- arch: riscv64
- arch: ppc64le
- arch: s390x
steps:
- name: checkout repository
uses: actions/checkout@v5
@@ -282,13 +318,15 @@ jobs:
uses: uraimo/run-on-arch-action@v3
id: runcmd
with:
arch: riscv64
arch: ${{ matrix.arch }}
distro: ubuntu22.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
apt-get update && apt-get install -y software-properties-common
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev rpm
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
@@ -300,77 +338,7 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-riscv64
path: ./fastfetch-*.*
linux-ppc64le:
name: Linux-ppc64le
runs-on: ubuntu-24.04
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v5
- name: run VM
uses: uraimo/run-on-arch-action@v3
id: runcmd
with:
arch: ppc64le
distro: ubuntu20.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-ppc64le
path: ./fastfetch-*.*
linux-s390x:
name: Linux-s390x
runs-on: ubuntu-24.04
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v5
- name: run VM
uses: uraimo/run-on-arch-action@v3
id: runcmd
with:
arch: s390x
distro: ubuntu20.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-linux-s390x
name: fastfetch-linux-${{ matrix.arch }}
path: ./fastfetch-*.*
musl-amd64:
@@ -386,7 +354,7 @@ jobs:
run: |
cat /etc/alpine-release
uname -a
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
shell: alpine.sh --root {0}
- name: build
@@ -411,12 +379,19 @@ jobs:
name: fastfetch-musl-amd64
path: ./fastfetch-*.*
macos-amd64:
name: macOS-amd64
runs-on: macos-13
macos-hosts:
name: macOS-${{ matrix.arch }}
runs-on: ${{ matrix.runs-on }}
permissions:
security-events: write
contents: read
strategy:
matrix:
include:
- arch: amd64
runs-on: macos-15-intel
- arch: aarch64
runs-on: macos-latest
steps:
- name: checkout repository
uses: actions/checkout@v5
@@ -455,54 +430,7 @@ jobs:
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-macos-amd64
path: ./fastfetch-*.*
macos-aarch64:
name: macOS-aarch64
runs-on: macos-latest
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v5
- name: uname -a
run: uname -a
- name: install required packages
run: |
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --target package --verbose -j4
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: otool -L fastfetch
- name: run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-macos-aarch64
name: fastfetch-macos-${{ matrix.arch }}
path: ./fastfetch-*.*
sunos-amd64:
@@ -518,7 +446,6 @@ jobs:
usesh: true
prepare: |
uname -a
pkg install pkg:/package/pkg
pkg update --accept
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick
@@ -560,7 +487,7 @@ jobs:
run: |
uname -a
sudo pkg update
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -596,8 +523,9 @@ jobs:
version: '7.7'
run: |
uname -a
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
sudo pkg_add -u
sudo pkg_add -r llvm-19.1.7p3 cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa
CC=clang-19 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
@@ -632,8 +560,8 @@ jobs:
version: '10.1'
run: |
uname -a
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
@@ -665,10 +593,10 @@ jobs:
prepare: |
uname -a
pkg update
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa libelf
pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
@@ -718,12 +646,25 @@ jobs:
name: fastfetch-haiku-amd64
path: ./fastfetch-*.*
windows-amd64:
name: Windows-amd64
runs-on: windows-latest
windows-hosts:
name: Windows-${{ matrix.arch }}
runs-on: ${{ matrix.runs-on }}
permissions:
security-events: write
contents: read
strategy:
matrix:
include:
- arch: amd64
runs-on: windows-latest
msystem: CLANG64
msystem-lower: clang64
msys-arch: x86_64
- arch: aarch64
runs-on: windows-11-arm
msystem: CLANGARM64
msystem-lower: clangarm64
msys-arch: aarch64
defaults:
run:
shell: msys2 {0}
@@ -734,21 +675,21 @@ jobs:
- name: setup-msys2
uses: msys2/setup-msys2@v2
with:
msystem: CLANG64
msystem: ${{ matrix.msystem }}
update: true
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-opencl-headers mingw-w64-clang-x86_64-cppwinrt mingw-w64-clang-x86_64-imagemagick
install: git mingw-w64-clang-${{ matrix.msys-arch }}-7zip mingw-w64-clang-${{ matrix.msys-arch }}-cmake mingw-w64-clang-${{ matrix.msys-arch }}-clang mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-loader mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-headers mingw-w64-clang-${{ matrix.msys-arch }}-opencl-icd mingw-w64-clang-${{ matrix.msys-arch }}-opencl-headers mingw-w64-clang-${{ matrix.msys-arch }}-cppwinrt mingw-w64-clang-${{ matrix.msys-arch }}-imagemagick mingw-w64-clang-${{ matrix.msys-arch }}-chafa
- name: print msys version
run: uname -a
- name: configure project
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
run: env PKG_CONFIG_PATH=/${{ matrix.msystem-lower }}/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --verbose -j4
- name: copy necessary dlls
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
run: cp /${{ matrix.msystem-lower }}/bin/{OpenCL,vulkan-1}.dll .
- name: list features
run: ./fastfetch --list-features
@@ -768,102 +709,61 @@ jobs:
- name: run tests
run: ctest --output-on-failure
- name: create zip archive
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: upload artifacts
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
id: upload-unsigned-artifact
name: upload artifacts for signing
uses: actions/upload-artifact@v4
with:
name: fastfetch-windows-amd64
path: ./fastfetch-windows-amd64.*
name: fastfetch-windows-${{ matrix.arch }}
path: |
*.dll
fastfetch.exe
flashfetch.exe
windows-aarch64:
name: Windows-aarch64
runs-on: windows-11-arm
permissions:
security-events: write
contents: read
defaults:
run:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v5
- name: setup-msys2
uses: msys2/setup-msys2@v2
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
name: submit signing request
uses: signpath/github-action-submit-signing-request@v1
with:
msystem: CLANGARM64
update: true
install: git mingw-w64-clang-aarch64-7zip mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-vulkan-loader mingw-w64-clang-aarch64-vulkan-headers mingw-w64-clang-aarch64-opencl-icd mingw-w64-clang-aarch64-opencl-headers mingw-w64-clang-aarch64-cppwinrt mingw-w64-clang-aarch64-imagemagick
- name: print msys version
run: uname -a
- name: configure project
run: env PKG_CONFIG_PATH=/clangarm64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --verbose -j4
- name: copy necessary dlls
run: cp /clangarm64/bin/{OpenCL,vulkan-1}.dll .
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: ldd fastfetch
- name: run tests
run: ctest --output-on-failure
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
project-slug: 'fastfetch'
signing-policy-slug: ${{ github.ref == 'refs/heads/master' && 'release-signing' || 'test-signing' }}
github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '.'
- name: create zip archive
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-aarch64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-aarch64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: upload artifacts
- name: upload true artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-windows-aarch64
path: ./fastfetch-windows-aarch64.*
name: fastfetch-windows-${{ matrix.arch }}
path: ./fastfetch-windows-${{ matrix.arch }}.*
overwrite: true
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
name: Release
runs-on: ubuntu-latest
needs:
- linux-amd64
- linux-aarch64
- linux-hosts
- linux-i686
- linux-armv7l
- linux-armv6l
- linux-riscv64
- linux-ppc64le
- linux-s390x
- linux-vms
- musl-amd64
- macos-amd64
- macos-aarch64
- macos-hosts
- freebsd-amd64
- openbsd-amd64
- netbsd-amd64
- dragonfly-amd64
- sunos-amd64
- haiku-amd64
- windows-amd64
- windows-aarch64
- windows-hosts
permissions:
contents: write
steps:
@@ -874,29 +774,29 @@ jobs:
repository: ${{ github.repository }}
- name: download artifacts
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
uses: actions/download-artifact@v4
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
uses: actions/download-artifact@v5
- name: create release
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ needs.linux-amd64.outputs.ffversion }}
tag: ${{ needs.linux-hosts.outputs.ffversion }}
commit: ${{ github.sha }}
artifactErrorsFailBuild: true
artifacts: fastfetch-*/fastfetch-*
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details."
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-hosts.outputs.ffversion }}/CHANGELOG.md) for details."
- name: download source tarballs
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
run: |
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-amd64.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-hosts.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
ls fastfetch-*/*
- name: generate release notes
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
run: |
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-hosts.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
@@ -905,10 +805,10 @@ jobs:
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
- name: update release body
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ needs.linux-amd64.outputs.ffversion }}
tag: ${{ needs.linux-hosts.outputs.ffversion }}
commit: ${{ github.sha }}
bodyFile: fastfetch-release-notes.md
allowUpdates: true
+215
View File
@@ -1,3 +1,218 @@
# 2.56.1
Features:
* Improves compatibility with KDE Plasma 6.5 (#2093, Display)
* Adds a `tempSensor` option to specify the sensor name used for CPU temperature detection (CPU)
* Example: `{ "type": "cpu", "tempSensor": "hwmon0" /* Use /sys/class/hwmon/hwmon0 for temperature detection */ }`
* Refines Memory usage detection on macOS to match Activity Monitor more closely (Memory, macOS)
* Minor optimizations
Bugfixes:
* Fixes cache line size detection (CPU, macOS)
Logos:
* Removes Opak
* Updates GXDE
# 2.56.0
Features:
* Enhances config file loading. `--config` and `-c` with relative path now also searches paths defined in `fastfetch --list-config-paths` (typically `~/.config/fastfetch/`)
* This allows users to use `fastfetch -c my-config` without needing to specify the full path.
* Adds NUMA node count detection (CPU)
* Exposed via `{numa-nodes}` in custom format
* Supported on Linux, FreeBSD and Windows
* Supports the newest Alacritty config format (#2070, TerminalFont)
* Detects driver specific info for Zhaoxin GPUs (GPU, Linux)
* Detects Android OEM UI for certain OSes (DE, Android)
* Improves users detection on Linux (#2064, Users, Linux)
* Adds systemd fallback when utmp is unavailable
* Fixes resource leaks
* Always reports the newest session info
* Adds kiss package manager support (#2072, Packages, Linux)
* Reports `sshd` if `$SSH_TTY` is not available (Terminal)
* Zpool module rewrite (#2051, Zpool)
* Adds new Zpool properties: allocated, guid, readOnly
* Zpool module now uses runtime lookup for properties to ensure portability
* Adds NetBSD (requires `sudo`) and macOS support
* Adds `splitLines` option for Command module, which splits the output into sub modules, each containing one line of the output (Command)
```
* Command output:
Line 1
Line 2
Line 3
* Old behavior:
Command: Line 1
Line 2
Line 3
* With `"splitLines": true`:
Command 1: Line 1
Command 2: Line 2
Command 3: Line 3
```
Bugfixes:
* Fixes {m,o}ksh version detection on Linux (Shell)
* Fixes Alacritty config parsing for TOML format (#2070, TerminalFont)
* Improves builtin logo printing for piping and buffering (#2065, Logo)
* Uses absolute path when detecting shell and terminal version if available (#2067, TerminalShell)
Logos:
* Updates Codex Linux logo (#2071)
* Adds OS/2 Warp logo (#2062)
* Adds Amiga logo (#2061)
# 2.55.1
Bugfixes:
* Fix parallel command execution breaks randomly (#2056 / #2058, Command)
* Regression from v2.55.0
* Fix `dylib` searching path on macOS (macOS)
* Regression from v2.55.0
* Fix an uninitialized field (#2057, Display)
# 2.55.0
Changes:
* Commands are now executed in parallel by default to improve performance (#2045, Command)
* This behavior can be disabled in the config file with `"parallel": false` if it causes problems with certain scripts
* Folder/filesystem hiding is moved to the detection stage; hidden entries are no longer probed, improving performance (#2043, Disk)
Features:
* Adds `command.parallel` and `command.useStdErr` config options (Command)
* `parallel`: set to `false` to disable parallel execution (see Changes above)
* `useStdErr`: set to `true` to use stderr output instead of stdout
* Adds the command-line flag `--dynamic-interval <interval-in-ms>` to enable dynamic output auto-refresh (#2041)
* Due to internal limitations, some modules do not support dynamic updates (notably Display and Media)
* Adds support for using the current playing media's cover art as a logo source (Media / Logo)
* Usage: `"logo": { "type": "<image-protocol>", "source": "media-cover" }` in JSON config; or `--<image-protocol> media-cover` in command line
* Supports local sources only
* Adds native GPU detection support on OpenBSD and NetBSD (instead of depending on `libpciaccess`) (GPU)
* No functional changes
* Root privileges are required to access PCI config space on OpenBSD (as always)
* Adds GPU detection support on GNU/Hurd (GPU)
* Requires building with `libpciaccess`
* Shows Debian point release on Raspberry Pi OS (#2032, OS, Linux)
* Adds `Brush` shell version detection (Shell)
* Improves Mac family detection via prefix matching (Host)
Bugfixes:
* Ignores `run-parts` during terminal/shell detection (#2048, Terminal / Shell, Linux)
* Fixes fish version detection when `LC_ALL` is set (#2014, Shell, Linux)
* Hides the module when no desktop icons are found (#2023, Icons, Windows)
* Skips auxiliary display controllers to prevent the module from reporting duplicate entries (#2034, GPU, Linux)
* Refines Apple rpath handling; fixes building for the Homebrew version on macOS (#1998, CMake)
Logos:
* Adds Vincent OS and MacaroniOS
# 2.54.0
Windows binaries in Release page are now signed by SignPath.
Changes:
* Moves macOS and Windows design language detection from the DE module to the Theme module
Features:
* Adds `--json` and `-j` command line flags as a shortcut for `--format json`
* Various improvements to the OS module (OS)
* Displays point releases for Debian
* Displays code names for Ubuntu
* Displays build ID for macOS
* Displays code names for Windows (previously shown in the Kernel module)
* Adds basic support for Wine (Windows)
* Adds basic support for hppa and sh architectures (CPU, Linux)
* Improves T-Head SoC name detection from the device tree (#1997, CPU, Linux)
* Supports glob patterns in `Disk.hideFolders` (Disk)
* For example, `/boot/*` will match both `/boot/efi` and `/boot/firmware`
* Adds brightness-level detection for external monitor support on Intel macOS (Brightness, macOS)
* Adds configurable spacing between icon and text in keys
* `display.key.type: "both-N"` where N is `0-4`
* Useful for non-monospaced Nerd Fonts
* Adds detection support for modern Samsung Exynos SoCs (CPU, Android)
* Adds a new CMake option `-DENABLE_WORDEXP=<ON|OFF>` to enable or disable using `wordexp(3)` for acquiring logo file paths (`logo.source`)
* Enabled by default for compatibility
* Disabling this option reverts to using `glob(3)`, which is less functional but more secure
Bugfixes:
* Avoids integer overflow when calculating swap size (#1988, Swap, Windows)
* Trims whitespace from full user name (Title, macOS)
* Fixes default font size for Ghostty (#1986, TerminalFont, Linux)
* Works around an issue that could report impossibly high memory usage in rare cases (#1988, Memory, Linux)
* Fixes incorrect glibc dependency in polyfilled DEB packages (#1983, Linux)
* Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux)
* Fixes crashes on ancient Android kernels (#1993, Disk, Android)
* Fixes incorrect usage of `glob(3)` (OpenBSD)
* Prefers resolutions reported by RandR mode info, fixing incorrect resolutions on XFCE when DPI scaling is enabled (Display, Linux)
* Various code cleanups and minor fixes
Logos:
* Adds secureblue, PrismLinux, EmperorOS and Zraxyl
* Updates T2
# 2.53.0
Changes:
* JSON property `length` in `Separator` module has been renamed to `times` for clarity (Separator)
Features:
* Adds IPv6 type selection (#1459, LocalIP)
* For example: `{ "type": "localip", "showIpv6": "ula" /* Show ULA only */ }`
* Adds more ARM CPU part IDs (CPU, Linux)
* Improves Ghostty font config parsing with fallback font detection (#1967, TerminalFont)
* Replaces statx(2) call with syscall(2) for better compatibility (Disk, Linux)
* Allows array input for disk folder and filesystem options (Disk)
* For example: `{ "type": "disk", "folders": ["/", "/home"] }`
* Adds support for ignoring input devices by name prefix (#1950, Keyboard / Mouse / Gamepad)
* For example: `{ "type": "keyboard", "ignores": ["Apple ", "Corsair "] }`
* Adds support for (B)SSID detection on macOS Tahoe (Wifi, macOS)
* Please don't expect it to work on later macOS versions
* Improves Ubuntu flavor detection (#1975, OS, Linux)
* Refines ARMv8.4-A detection to require LSE2 (CPU, Windows)
* Detects the latest Dimensity & Snapdragon SoC names (CPU, Android)
Bugfixes:
* Handles zero temperature data (#1960, CPU, Windows)
* Fixes `dlopen libzfs.so failed` error on Proxmox 9 (#1973, Zpool, Linux)
Logos:
* Removes Starry Linux
* Adds TempleOS
* Updates ObsidianOS
# 2.52.0
Changes:
* New optional build dependencies on Android
* main: chafa dbus glib imagemagick libelf libxcb libxrandr pulseaudio zlib
* x11: dconf (Optional)
* Dependency on `libxfconf` is removed. XFCE related detection now uses `libdbus` instead (Linux)
* The default format of `Display` module is updated to `{width}x{height} @ {scale-factor}x in {inch}", {refresh-rate} Hz`
* Replaced scaled resolution with scale factor for shorter texts and avoiding potential confusion.
Bugfixes:
* Fixes linking on 32-bit Android (#1939)
* Skips network interfaces without IPs unless MAC address is requested (#1949, LocalIP)
* Fixes unexpected padding when setting `logo.width` with chafa logos (#1947, Logo)
* Regression from v2.51.0
* Improves Wallpaper detection on XFCE4 (Wallpaper, Linux)
* Ignores process `Relay(xxx)` when detecting terminal on WSL2 (Terminal, Linux)
Features:
* Enables X11-related info (i.e., WM/DE) detection on Android (Global, Android)
* This requires many dependencies. See above.
* Adds scale factors detection for X11 (Display, Linux)
* X11 doesn't natively report scale factor as Wayland does. Instead, Fastfetch tries to detect `Xft.dpi` (DPI used by X FreeType for scaling fonts), which is usually set by the WM when DPI scaling is enabled.
* It's not always accurate. For example, XFCE4 has a separate config for text scaling, which is unaffected by the global DPI scaling setting.
* Adds `display.fraction.trailingZeros: [always|never]` option for fraction formatting
* The default value of `display.fraction.ndigits` is changed from `-1` (unlimited) to `2` for usability.
* Used for displaying scale factor in Display module mentioned above, alongside other places for printing raw fraction numbers.
* Informs users that module-specific CLI options are no longer supported and provide guidance for transitioning to JSON config
* Adds CPU name detection support for IA64 (CPU, Linux)
* Support Btrfs allocation profile detection (#1941, Btrfs, Linux)
# 2.51.1
Bugfixes:
+99 -100
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.1
VERSION 2.56.1
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -9,6 +9,17 @@ project(fastfetch
set(PROJECT_LICENSE "MIT license")
if(DEFINED CMAKE_SYSTEM_PROCESSOR_OVERRIDE) # Used by github actions for i686 build
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR_OVERRIDE} CACHE INTERNAL "")
endif()
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" CMAKE_SYSTEM_PROCESSOR)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(CMAKE_SYSTEM_PROCESSOR "amd64")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
endif()
message(STATUS "Build for system processor: ${CMAKE_SYSTEM_PROCESSOR}")
###################
# Target Platform #
###################
@@ -60,32 +71,30 @@ include(CMakeDependentOption)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR GNU" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD OR GNU" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX OR GNU" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR ANDROID OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR GNU" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR ANDROID OR GNU" OFF)
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku OR GNU" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD" OFF)
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "GNU" OFF)
option(ENABLE_ZLIB "Enable zlib" ON)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
@@ -96,6 +105,8 @@ option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON)
option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF)
option(ENABLE_EMBEDDED_AMDGPUIDS "Embed amdgpu.ids into fastfetch, requires `python`" OFF)
option(ENABLE_WORDEXP "Enable using of wordexp(3) if available, instead of glob(3)" ON)
option(ENABLE_LIBZFS "Enable libzfs" ON)
set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
@@ -378,6 +389,7 @@ set(LIBFASTFETCH_SRC
src/detection/chassis/chassis.c
src/detection/cpu/cpu.c
src/detection/cpuusage/cpuusage.c
src/detection/command/command.c
src/detection/disk/disk.c
src/detection/diskio/diskio.c
src/detection/displayserver/displayserver.c
@@ -398,6 +410,7 @@ set(LIBFASTFETCH_SRC
src/detection/version/version.c
src/detection/vulkan/vulkan.c
src/detection/weather/weather.c
src/detection/zpool/zpool.c
src/logo/builtin.c
src/logo/image/im6.c
src/logo/image/im7.c
@@ -515,6 +528,7 @@ if(LINUX)
src/detection/physicalmemory/physicalmemory_linux.c
src/detection/diskio/diskio_linux.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
@@ -569,12 +583,12 @@ if(LINUX)
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/detection/zpool/zpool_linux.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
src/common/netif/netif_linux.c
src/common/networking/networking_linux.c
@@ -590,7 +604,7 @@ elseif(ANDROID)
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_linux.c
src/detection/cpucache/cpucache_linux.c
src/detection/cursor/cursor_nosupport.c
src/detection/cursor/cursor_linux.c
src/detection/cpuusage/cpuusage_linux.c
src/detection/disk/disk_linux.c
src/detection/dns/dns_linux.c
@@ -598,10 +612,16 @@ elseif(ANDROID)
src/detection/physicalmemory/physicalmemory_nosupport.c
src/detection/diskio/diskio_linux.c
src/detection/displayserver/displayserver_android.c
src/detection/font/font_nosupport.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/gtk_qt/gtk.c
src/detection/gtk_qt/qt.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_android.c
src/detection/host/host_android.c
src/detection/icons/icons_nosupport.c
src/detection/icons/icons_linux.c
src/detection/initsystem/initsystem_linux.c
src/detection/keyboard/keyboard_nosupport.c
src/detection/libc/libc_android.c
@@ -610,7 +630,7 @@ elseif(ANDROID)
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_nosupport.c
src/detection/media/media_nosupport.c
src/detection/media/media_linux.c
src/detection/memory/memory_linux.c
src/detection/mouse/mouse_nosupport.c
src/detection/netio/netio_linux.c
@@ -620,22 +640,22 @@ elseif(ANDROID)
src/detection/packages/packages_nix.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_linux.c
src/detection/sound/sound_nosupport.c
src/detection/sound/sound_linux.c
src/detection/swap/swap_linux.c
src/detection/terminalfont/terminalfont_android.c
src/detection/terminalfont/terminalfont_linux.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/terminalsize/terminalsize_linux.c
src/detection/theme/theme_nosupport.c
src/detection/theme/theme_linux.c
src/detection/tpm/tpm_nosupport.c
src/detection/uptime/uptime_linux.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_nosupport.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_android.c
src/detection/wm/wm_nosupport.c
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_nosupport.c
src/detection/wm/wm_linux.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_android.c
src/detection/zpool/zpool_nosupport.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
@@ -665,6 +685,7 @@ elseif(FreeBSD)
src/detection/physicalmemory/physicalmemory_linux.c
src/detection/diskio/diskio_bsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
@@ -717,7 +738,6 @@ elseif(FreeBSD)
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/detection/zpool/zpool_linux.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
@@ -759,6 +779,7 @@ elseif(NetBSD)
src/detection/physicalmemory/physicalmemory_linux.c
src/detection/diskio/diskio_nbsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
@@ -772,7 +793,7 @@ elseif(NetBSD)
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_general.c
src/detection/gpu/gpu_nbsd.c
src/detection/gpu/gpu_pci.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_nbsd.c
@@ -810,7 +831,6 @@ elseif(NetBSD)
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/detection/zpool/zpool_linux.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
@@ -841,6 +861,7 @@ elseif(OpenBSD)
src/detection/physicalmemory/physicalmemory_linux.c
src/detection/diskio/diskio_obsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
@@ -855,7 +876,7 @@ elseif(OpenBSD)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_pci.c
src/detection/gpu/gpu_general.c
src/detection/gpu/gpu_obsd.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_obsd.c
src/detection/lm/lm_nosupport.c
@@ -892,7 +913,6 @@ elseif(OpenBSD)
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/detection/zpool/zpool_nosupport.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
src/util/smbiosHelper.c
@@ -952,7 +972,7 @@ elseif(APPLE)
src/detection/terminalfont/terminalfont_apple.m
src/detection/terminalshell/terminalshell_linux.c
src/detection/terminalsize/terminalsize_linux.c
src/detection/theme/theme_nosupport.c
src/detection/theme/theme_apple.c
src/detection/tpm/tpm_apple.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
@@ -962,7 +982,6 @@ elseif(APPLE)
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_apple.m
src/detection/camera/camera_apple.m
src/detection/zpool/zpool_nosupport.c
src/util/apple/cf_helpers.c
src/util/apple/osascript.m
src/util/apple/smc_temps.c
@@ -1013,7 +1032,7 @@ elseif(WIN32)
src/detection/physicalmemory/physicalmemory_linux.c
src/detection/netio/netio_windows.c
src/detection/opengl/opengl_windows.c
src/detection/os/os_windows.c
src/detection/os/os_windows.cpp
src/detection/packages/packages_windows.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_windows.c
@@ -1022,7 +1041,7 @@ elseif(WIN32)
src/detection/terminalfont/terminalfont_windows.c
src/detection/terminalshell/terminalshell_windows.c
src/detection/terminalsize/terminalsize_windows.c
src/detection/theme/theme_nosupport.c
src/detection/theme/theme_windows.c
src/detection/tpm/tpm_windows.c
src/detection/uptime/uptime_windows.c
src/detection/users/users_windows.c
@@ -1032,7 +1051,6 @@ elseif(WIN32)
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_windows.c
src/detection/camera/camera_windows.cpp
src/detection/zpool/zpool_nosupport.c
src/util/windows/getline.c
src/util/windows/com.cpp
src/util/windows/registry.c
@@ -1069,6 +1087,7 @@ elseif(SunOS)
src/detection/physicalmemory/physicalmemory_linux.c
src/detection/diskio/diskio_sunos.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
@@ -1120,7 +1139,6 @@ elseif(SunOS)
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_nosupport.c
src/detection/zpool/zpool_linux.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
@@ -1189,7 +1207,6 @@ elseif(Haiku)
src/detection/de/de_nosupport.c
src/detection/wmtheme/wmtheme_nosupport.c
src/detection/camera/camera_nosupport.c
src/detection/zpool/zpool_nosupport.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
src/util/haiku/version.cpp
@@ -1220,6 +1237,7 @@ elseif(GNU)
src/detection/physicalmemory/physicalmemory_nosupport.c
src/detection/diskio/diskio_nosupport.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/common.c
src/detection/displayserver/linux/drm.c
src/detection/displayserver/linux/wayland/wayland.c
src/detection/displayserver/linux/wayland/global-output.c
@@ -1229,7 +1247,7 @@ elseif(GNU)
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_nosupport.c
src/detection/gpu/gpu_general.c
src/detection/gpu/gpu_pci.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_nosupport.c
@@ -1268,7 +1286,6 @@ elseif(GNU)
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_nosupport.c
src/detection/zpool/zpool_nosupport.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
@@ -1291,10 +1308,7 @@ endif()
include(CheckFunctionExists)
check_function_exists(wcwidth HAVE_WCWIDTH)
if(NOT HAVE_WCWIDTH)
list(APPEND LIBFASTFETCH_SRC src/3rdparty/mk_wcwidch/wcwidth.c)
endif()
if(LINUX)
check_function_exists(statx HAVE_STATX)
list(APPEND LIBFASTFETCH_SRC src/util/wcwidth.c)
endif()
if(NOT WIN32)
check_function_exists(pipe2 HAVE_PIPE2)
@@ -1318,15 +1332,15 @@ add_library(libfastfetch OBJECT
)
if(yyjson_FOUND)
target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON)
target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON=1)
target_link_libraries(libfastfetch PUBLIC yyjson::yyjson)
# `target_link_libraries(yyjson::yyjson)` sets rpath implicitly
else()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
endif()
endif()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE AND BINARY_LINK_TYPE STREQUAL "dlopen")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
endif()
if(ANDROID)
@@ -1411,10 +1425,6 @@ if(FreeBSD OR OpenBSD OR NetBSD)
unset(CMAKE_REQUIRED_DEFINITIONS)
endif()
if(HAVE_STATX)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_STATX)
endif()
if(HAVE_WCWIDTH)
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WCWIDTH)
endif()
@@ -1525,10 +1535,6 @@ ff_lib_enable(DBUS
"dbus-1"
"DBus"
)
ff_lib_enable(XFCONF
"libxfconf-0"
"XFConf"
)
ff_lib_enable(SQLITE3
"sqlite3"
"SQLite3"
@@ -1596,24 +1602,6 @@ ff_lib_enable(PCIACCESS
"pciaccess"
"pciaccess"
)
# The system <libzfs.h> is only usable on SunOS. We provide our local copy of it so it's always available.
if(ENABLE_LIBZFS)
if(BINARY_LINK_TYPE STREQUAL "dlopen")
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
else()
set(CMAKE_REQUIRED_LIBRARIES_BACKUP ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} zfs)
check_function_exists("libzfs_init" LIBZFS_FOUND)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_BACKUP})
if(NOT LIBZFS_FOUND)
message(STATUS "Library: missing: LIBZFS")
else()
message(STATUS "Library: found LIBZFS")
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
target_link_libraries(libfastfetch PRIVATE zfs)
endif()
endif()
endif()
if(ENABLE_THREADS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
@@ -1628,6 +1616,15 @@ endif()
if(ENABLE_EMBEDDED_AMDGPUIDS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
endif()
if(ENABLE_LIBZFS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
target_link_libraries(libfastfetch
PRIVATE "zfs"
)
endif()
endif()
if(LINUX)
target_link_libraries(libfastfetch
@@ -1676,11 +1673,10 @@ elseif(WIN32)
PRIVATE "wtsapi32"
PRIVATE "imagehlp"
PRIVATE "cfgmgr32"
PRIVATE "winbrand"
PRIVATE "propsys"
PRIVATE "secur32"
)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
# WoA only works on Windows 10 or higher
target_link_libraries(libfastfetch
PRIVATE "mincore"
@@ -1719,8 +1715,6 @@ elseif(SunOS)
PRIVATE "socket"
PRIVATE "kstat"
PRIVATE "proc"
PRIVATE "zfs"
PRIVATE "nvpair"
PRIVATE "devinfo"
)
elseif(GNU)
@@ -1728,17 +1722,23 @@ elseif(GNU)
PRIVATE "m"
)
elseif(ANDROID)
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
if(HAVE_LIBANDROID_WORDEXP_STATIC)
target_link_libraries(libfastfetch
PRIVATE -l:libandroid-wordexp.a
)
else()
CHECK_LIBRARY_EXISTS(android-wordexp wordexp "" HAVE_LIBANDROID_WORDEXP)
if(HAVE_LIBANDROID_WORDEXP)
target_link_libraries(libfastfetch
PRIVATE "m"
)
if(ENABLE_WORDEXP)
# https://github.com/termux/termux-packages/pull/7056
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
if(HAVE_LIBANDROID_WORDEXP_STATIC)
target_link_libraries(libfastfetch
PRIVATE android-wordexp
PRIVATE -l:libandroid-wordexp.a
)
else()
CHECK_LIBRARY_EXISTS(android-wordexp wordexp "" HAVE_LIBANDROID_WORDEXP)
if(HAVE_LIBANDROID_WORDEXP)
target_link_libraries(libfastfetch
PRIVATE android-wordexp
)
endif()
endif()
endif()
elseif(Haiku)
@@ -1800,13 +1800,17 @@ if(NOT WIN32)
if(HAVE_UTMPX)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX=1)
endif()
CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
if(HAVE_WORDEXP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1)
if(ENABLE_WORDEXP)
CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
if(HAVE_WORDEXP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1)
message(STATUS "wordexp.h found, wordexp support enabled")
else()
set(ENABLE_WORDEXP OFF)
endif()
endif()
CHECK_INCLUDE_FILE("glob.h" HAVE_GLOB)
if(HAVE_GLOB)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLOB=1)
if(NOT ENABLE_WORDEXP)
message(STATUS "wordexp.h not found or disabled, glob used instead")
endif()
if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT)
CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
@@ -2015,11 +2019,6 @@ install(
##################
set(CPACK_GENERATOR "TGZ;ZIP")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
set(CMAKE_SYSTEM_PROCESSOR "amd64")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
endif()
if(APPLE)
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) # use macos instead of darwin
elseif(IS_MUSL)
@@ -2066,7 +2065,7 @@ endif()
set(CPACK_SET_DESTDIR ON)
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
set(CPACK_PACKAGE_CONTACT "Carter Li <zhangsongcui@live.cn>")
set(CPACK_PACKAGE_DESCRIPTION "\
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
It is written mostly in C to achieve much better performance.\
+75
View File
@@ -0,0 +1,75 @@
# Fastfetch
Fastfetch 是一款类似 neofetch 的系统信息展示工具,主要用 C 编写,强调性能和可定制性。支持 Linux、macOS、Windows 7+、Android、FreeBSD、OpenBSD、NetBSD、DragonFly、Haiku、SunOS。
示例配置见 presets/examples,更多截图与平台说明见 Wiki。
## 安装
Linux(部分):
- Debian 13+ / Ubuntu: apt install fastfetch
- Arch: pacman -S fastfetch
- Fedora: dnf install fastfetch
- openSUSE: zypper install fastfetch
- Linuxbrewbrew install fastfetch
- 各发行版打包状态:https://repology.org/project/fastfetch/versions
macOS
- Homebrewbrew install fastfetch
- MacPortssudo port install fastfetch
Windows
- scoop install fastfetch
- choco install fastfetch
- winget install fastfetch
- MSYS2pacman -S mingw-w64-<subsystem>-<arch>-fastfetch
BSD
- FreeBSDpkg install fastfetch
- NetBSDpkgin in fastfetch
- OpenBSDpkg_add fastfetch
AndroidTermux):
- pkg install fastfetch
Nightly 构建:
- https://nightly.link/fastfetch-cli/fastfetch/workflows/ci/dev?preview
## 源码构建
基本上是 `cmake . && make`。详见 Wikihttps://github.com/fastfetch-cli/fastfetch/wiki/Building
## 使用
- 默认运行:`fastfetch`
- 查看所有可用模块示例:`fastfetch -c all.jsonc`
- 以 JSON 输出指定模块:`fastfetch -s <module1>[:<module2>] --format json`
- 完整命令行帮助:`fastfetch --help`
- 生成最小配置:`fastfetch --gen-config [</path/to/config.jsonc>]`
- 生成完整配置:`fastfetch --gen-config-full`
- 请使用支持 JSON schema 的编辑器(如 VSCode)编辑配置文件!
- 如果你连接 Github 有网络困难(智能提示不生效),可将配置文件中的 `$schema` 的值替换为 `https://gitee.com/carterl/fastfetch/raw/dev/doc/json_schema.json`
## 定制
- 配置使用 JSONC,语法与选项见 Wikihttps://github.com/fastfetch-cli/fastfetch/wiki/Configuration
- 预设示例位于 presets,可用 `-c <filename>` 加载
- Logo 选项与图像显示见文档:https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options
- 模块格式化(示例,仅显示 GPU 名称):
```jsonc
{
"modules": [
{ "type": "gpu", "format": "{name}" }
]
}
```
详见:https://github.com/fastfetch-cli/fastfetch/wiki/Format-String-Guide
## 反馈与支持
- 使用问题:Discussions https://github.com/fastfetch-cli/fastfetch/discussions
- 疑似缺陷:Issues https://github.com/fastfetch-cli/fastfetch/issues(请填写模版)
## 赞助
<img src="https://github.com/user-attachments/assets/a36a6501-e8b0-4a10-9061-b9206d12ffba" width="220">
+13 -2
View File
@@ -11,8 +11,9 @@
[![latest packaged version(s)](https://repology.org/badge/latest-versions/fastfetch.svg)](https://repology.org/project/fastfetch/versions)
[![Packaging status](https://repology.org/badge/tiny-repos/fastfetch.svg)](https://repology.org/project/fastfetch/versions)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/fastfetch-cli/fastfetch)
[![中文README](https://img.shields.io/badge/%E4%B8%AD%E6%96%87-README-red)](README-cn.md)
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and SunOS.
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and illumos (SunOS).
<img src="screenshots/example1.png" width="49%" align="left" />
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
@@ -36,7 +37,8 @@ Some distributions package outdated versions of fastfetch. Older versions receiv
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
</a>
* Debian: `apt install fastfetch` (for Debian 13 or newer)
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (Ubuntu 22.04 or newer; latest version)
* Debian / Ubuntu: `apt install fastfetch` (Debian 13 or newer; Ubuntu 25.04 or newer)
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
* Arch Linux: `pacman -S fastfetch`
* Fedora: `dnf install fastfetch`
@@ -103,6 +105,10 @@ Fastfetch uses JSONC (JSON with comments) for configuration. [See the Wiki for d
Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
### WARNING
Fastfetch supports a `Command` module that can run arbitrary shell commands. If you copy-paste a config file from an untrusted source, it may contain malicious commands that can harm your system or compromise your privacy. Please always review the config file before using it.
## FAQ
### Q: Neofetch is good enough. Why do I need fastfetch?
@@ -317,6 +323,11 @@ If you find Fastfetch useful, please consider donating.
* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui)
* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer)
## Code signing
* Free code signing provided by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/)
* This program will not transfer any information to other networked systems unless specifically requested by the user or the person installing or operating it
## Star History
Give us a star to show your support!
+49 -1
View File
@@ -1,3 +1,52 @@
fastfetch (2.56.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.56.1
-- Carter Li <zhangsongcui@live.cn> Thu, 18 Dec 2025 14:57:36 +0800
fastfetch (2.56.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.56.0
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Dec 2025 09:21:58 +0800
fastfetch (2.55.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.55.1
-- Carter Li <zhangsongcui@live.cn> Mon, 17 Nov 2025 10:15:44 +0800
fastfetch (2.55.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.55.0
-- Carter Li <zhangsongcui@live.cn> Wed, 12 Nov 2025 09:15:24 +0800
fastfetch (2.54.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Fix building on plucky
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 14:27:02 +0800
fastfetch (2.54.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.54.0
* Test independent changelog entries for different Ubuntu releases
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 10:47:02 +0800
fastfetch (2.53.0) jammy; urgency=medium
* Update to 2.53.0
-- Carter Li <zhangsongcui@live.cn> Tue, 23 Sep 2025 09:58:48 +0800
fastfetch (2.52.0) jammy; urgency=medium
* Update to 2.52.0
-- Carter Li <zhangsongcui@live.cn> Fri, 05 Sep 2025 14:59:44 +0800
fastfetch (2.51.0) jammy; urgency=medium
* Update to 2.51.0
@@ -423,4 +472,3 @@ fastfetch (2.7.1) jammy; urgency=medium
* Initial release.
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
+1 -1
View File
@@ -2,7 +2,7 @@ Source: fastfetch
Section: universe/utils
Priority: optional
Maintainer: Carter Li <zhangsongcui@live.cn>
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Build-Depends: libelf-dev, libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build, python3-setuptools
Standards-Version: 4.0.0
Homepage: https://github.com/fastfetch-cli/fastfetch
-1
View File
@@ -1 +0,0 @@
fastfetch_2.51.0_source.buildinfo universe/utils optional
+74 -2
View File
@@ -1,4 +1,76 @@
#!/usr/bin/env bash
# WARNING: DO NOT RUN THIS SCRIPT UNLESS YOU KNOW WHAT YOU ARE DOING.
debuild -S -i -I
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
set -euo pipefail
command -v debuild >/dev/null 2>&1 || { echo "debuild not found. Install devscripts." >&2; exit 1; }
command -v dput >/dev/null 2>&1 || { echo "dput not found." >&2; exit 1; }
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
OUT_DIR="$(dirname "$ROOT_DIR")"
PPA="ppa:zhangsongcui3371/fastfetch"
CODENAMES=( jammy noble plucky questing resolute )
DRY_RUN=0
if [[ -d "$OUT_DIR/build" ]]; then
echo "Output directory exists: $OUT_DIR/build" >&2
echo "Please move or delete it before proceeding." >&2
exit 1
fi
TEMPLATE="$ROOT_DIR/debian/changelog.tpl"
CHANGELOG_DEBIAN="$ROOT_DIR/debian/changelog"
if [[ ! -f "$TEMPLATE" ]]; then
echo "Template not found: $TEMPLATE" >&2
exit 1
fi
if ! grep -q '#UBUNTU_CODENAME#' "$TEMPLATE"; then
echo "Template missing placeholder: #UBUNTU_CODENAME#" >&2
exit 1
fi
echo "IMPORTANT: Before proceeding, please ensure that 'debian/changelog.tpl' is up-to-date"
echo " with the correct version number, release notes, and maintainer information."
echo
echo " The template must contain a placeholder like '#UBUNTU_CODENAME#' for the codename."
echo
read -p "Have you reviewed and updated 'debian/changelog.tpl'? (y/N): " -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
cleanup() {
rm -f "$CHANGELOG_DEBIAN"
rm -f "$ROOT_DIR/debian/files"
}
trap cleanup EXIT
shopt -s nullglob
for codename in "${CODENAMES[@]}"; do
echo "==> Publishing distro: $codename"
sed "s/#UBUNTU_CODENAME#/${codename}/g" "$TEMPLATE" > "$CHANGELOG_DEBIAN"
( cd "$ROOT_DIR" && debuild -S -i -I )
changes=( "$OUT_DIR"/fastfetch_*~${codename}_source.changes )
if [[ ${#changes[@]} -ne 1 ]]; then
echo "Unable to uniquely identify .changes for '$codename' in: $OUT_DIR" >&2
printf 'Found:\n'; printf ' %s\n' "${changes[@]}" >&2 || true
exit 1
fi
if [[ $DRY_RUN -eq 1 ]]; then
echo "[DRY-RUN] dput \"$PPA\" \"${changes[0]}\""
else
dput "$PPA" "${changes[0]}"
fi
rm -f "$OUT_DIR"/fastfetch_*~${codename}_source.{changes,dsc,tar.*}
echo "<== Done: $codename"
done
+182 -17
View File
@@ -1008,7 +1008,7 @@
},
"type": {
"type": "string",
"description": "Set whether to show icon before string keys",
"description": "Set whether to show builtin icon before string keys",
"oneOf": [
{
"const": "none",
@@ -1020,11 +1020,31 @@
},
{
"const": "icon",
"description": "Show icon keys (requires newest nerd font)"
"description": "Show builtin icon (requires newest nerd font)"
},
{
"const": "both",
"description": "Show both icon and string keys"
"description": "Show both icon and string keys (alias of `both-1`)"
},
{
"const": "both-0",
"description": "Show both icon and string with no spaces between them"
},
{
"const": "both-1",
"description": "Show both icon and string with a space between them"
},
{
"const": "both-2",
"description": "Show both icon and string with 2 spaces between them"
},
{
"const": "both-3",
"description": "Show both icon and string with 3 spaces between them"
},
{
"const": "both-4",
"description": "Show both icon and string with 4 spaces between them"
}
],
"default": "string"
@@ -1290,10 +1310,19 @@
"description": "Set how frequency values should be displayed",
"properties": {
"ndigits": {
"type": "integer",
"description": "Set the number of digits to keep after the decimal point when formatting frequency values\nA positive value will show the frequency in GHz with decimal\n-1 will show the frequency in MHz",
"minimum": -1,
"maximum": 9,
"description": "Set the number of decimal places to display when formatting frequency values",
"oneOf": [
{
"type": "integer",
"minimum": 0,
"maximum": 9,
"description": "Integer value displays the frequency in GHz with specified decimal places"
},
{
"type": "null",
"description": "Null value display the frequency as integer MHz"
}
],
"default": 2
},
"spaceBeforeUnit": {
@@ -1333,6 +1362,28 @@
"description": "The number of digits will be automatically determined based on the value"
}
],
"default": 2
},
"trailingZeros": {
"description": "Set when to keep trailing zeros",
"oneOf": [
{
"type": "null",
"description": "Same as `default`"
},
{
"const": "default",
"description": "Use the behavior defined internally"
},
{
"const": "always",
"description": "Always keep trailing zeros"
},
{
"const": "never",
"description": "Never keep trailing zeros"
}
],
"default": null
}
}
@@ -1829,6 +1880,10 @@
"temp": {
"$ref": "#/$defs/temperature"
},
"tempSensor": {
"description": "Set the temperature sensor to use for CPU temperature detection\n* Linux: `hwmon` or `thermal` path name (eg. `hwmon0`, `thermal_zone0)`\n* macOS: SMC sensor key (eg. `Tp01`)\n* Windows: thermal zone key (eg. `\\_TZ.CPUZ`)\n* FreeBSD: sysctl key (eg. `dev.cpu.0.temperature`)\n* NetBSD: sysmon sensor key (eg. `coretemp0`)",
"type": "string"
},
"showPeCoreCount": {
"description": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported",
"type": "boolean",
@@ -2050,6 +2105,21 @@
"description": "Set the command text to be executed",
"type": "string"
},
"useStdErr": {
"description": "Set if stderr should be used instead of stdout for command output",
"type": "boolean",
"default": false
},
"parallel": {
"description": "Set if the command should be executed in parallel with other commands\nImprove performance when using multiple commands, but may cause issues with some commands",
"type": "boolean",
"default": true
},
"splitLines": {
"description": "Set if the command output should be split into multiple lines",
"type": "boolean",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
@@ -2276,17 +2346,60 @@
"const": "disk"
},
"folders": {
"type": "string",
"description": "A colon (semicolon on Windows) separated list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options"
"description": "A list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options",
"oneOf": [
{
"type": "string",
"description": "A colon (semicolon on Windows) separated list of folder paths to get disk usage from",
"default": "/"
},
{
"type": "array",
"description": "An array of folder paths to get disk usage from",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
]
},
"hideFolders": {
"type": "string",
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output",
"default": "/efi:/boot:/boot/efi:/boot/firmware"
"description": "A list of folder paths (or glob patterns) to hide from the disk output",
"oneOf": [
{
"type": "string",
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output"
},
{
"type": "array",
"description": "An array of folder paths to hide from the disk output",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
],
"default": "/efi:/boot:/boot/*"
},
"hideFS": {
"type": "string",
"description": "A colon separated file systems to hide from the disk output"
"description": "A list of file systems to hide from the disk output",
"oneOf": [
{
"type": "string",
"description": "A colon separated list of file systems to hide from the disk output"
},
{
"type": "array",
"description": "An array of file systems to hide from the disk output",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
]
},
"showRegular": {
"type": "boolean",
@@ -2562,6 +2675,15 @@
"const": "gamepad",
"description": "List connected gamepads"
},
"ignores": {
"type": "array",
"description": "An array of case-insensitive device name prefixes to ignore",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"percent": {
"$ref": "#/$defs/percent"
},
@@ -2821,6 +2943,15 @@
"const": "keyboard",
"description": "List (connected) keyboards"
},
"ignores": {
"type": "array",
"description": "An array of case-insensitive device name prefixes to ignore",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"key": {
"$ref": "#/$defs/key"
},
@@ -2889,7 +3020,32 @@
},
"showIpv6": {
"description": "Show IPv6 addresses",
"type": "boolean",
"oneOf": [
{
"const": true,
"description": "Show the most useful IPv6 addresses"
},
{
"const": false,
"description": "Do not show IPv6 addresses"
},
{
"const": "gua",
"description": "Show only global unicast IPv6 addresses (2000::/3)"
},
{
"const": "ula",
"description": "Show only unique local IPv6 addresses (fc00::/7)"
},
{
"const": "lla",
"description": "Show only link-local IPv6 addresses (fe80::/10)"
},
{
"const": "unknown",
"description": "Show only IPv6 addresses that are not gua, ula or lla"
}
],
"default": false
},
"showSpeed": {
@@ -3119,6 +3275,15 @@
"const": "mouse",
"description": "List connected mouses"
},
"ignores": {
"type": "array",
"description": "An array of case-insensitive device name prefixes to ignore",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"key": {
"$ref": "#/$defs/key"
},
@@ -3656,8 +3821,8 @@
"description": "Set the color of the separator line",
"$ref": "#/$defs/outputColor"
},
"length": {
"description": "Set the length of the separator line, or 0 to auto-detect",
"times": {
"description": "Set the times of separator string to repeat, or 0 to auto-detect",
"type": "integer",
"minimum": 0,
"default": 0
+1 -1
View File
@@ -183,7 +183,7 @@
},
"keyIcon": "",
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
"text": "clang --version | head -1 | awk '{print $NF}'",
"text": "clang --version | sed -n 's/.*version \\([0-9][0-9.]*\\).*/\\1/p'",
"format": "clang {}"
},
{
+1 -1
View File
@@ -1,6 +1,6 @@
// #1887
{
"$schema": "file:///Users/carter/fastfetch/doc/json_schema.json",
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": null,
"display": {
"constants": [
+87
View File
@@ -0,0 +1,87 @@
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": null,
"display": {
"key": {
"type": "both",
"paddingLeft": 6,
"width": 17
}
},
"modules": [
{
"type": "custom",
"format": "|---------------------: {#1}Hardware{#} : ---------------------|"
},
"break",
{
"keyColor": "green",
"type": "host"
},
{
"keyColor": "green",
"type": "cpu"
},
{
"keyColor": "yellow",
"type": "memory"
},
{
"keyColor": "yellow",
"type": "swap"
},
{
"type": "custom",
"keyIcon": "",
"key": "Disks"
},
{
"type": "disk",
"key": " ",
"format": " [{mountpoint}] - {size-used} / {size-total} ({size-percentage})"
},
"break",
{
"type": "title",
"format": "|-------------------------------------------------------|\u001b[40D: {#1}{user-name} @ {host-name}{#} :"
},
"break",
{
"type": "os",
"keyColor": "cyan"
},
{
"type": "kernel",
"keyColor": "cyan"
},
{
"type": "packages",
"keyColor": "red",
"key": "Pkgs"
},
{
"type": "shell",
"keyColor": "red"
},
{
"type": "terminal",
"key": "Term",
"keyColor": "red"
},
{
"type": "locale",
"keyColor": "magenta"
},
"break",
{
"type": "custom",
"format": "|---------------------: {#1}Software{#} : ---------------------|"
},
"break",
{
"type": "colors",
"symbol": "circle",
"paddingLeft": 8
}
]
}
-7
View File
@@ -1,7 +0,0 @@
{
"home": "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c",
"license": "MIT compatible (embed in source)",
"version": "2007-05-26 (Unicode 5.0)",
"author": "Markus Kuhn",
"modified": "CarterLi"
}
-314
View File
@@ -1,314 +0,0 @@
/*
* This is an implementation of wcwidth() and wcswidth() (defined in
* IEEE Std 1002.1-2001) for Unicode.
*
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
*
* In fixed-width output devices, Latin characters all occupy a single
* "cell" position of equal width, whereas ideographic CJK characters
* occupy two such cells. Interoperability between terminal-line
* applications and (teletype-style) character terminals using the
* UTF-8 encoding requires agreement on which character should advance
* the cursor by how many cell positions. No established formal
* standards exist at present on which Unicode character shall occupy
* how many cell positions on character terminals. These routines are
* a first attempt of defining such behavior based on simple rules
* applied to data provided by the Unicode Consortium.
*
* For some graphical characters, the Unicode standard explicitly
* defines a character-cell width via the definition of the East Asian
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
* In all these cases, there is no ambiguity about which width a
* terminal shall use. For characters in the East Asian Ambiguous (A)
* class, the width choice depends purely on a preference of backward
* compatibility with either historic CJK or Western practice.
* Choosing single-width for these characters is easy to justify as
* the appropriate long-term solution, as the CJK practice of
* displaying these characters as double-width comes from historic
* implementation simplicity (8-bit encoded characters were displayed
* single-width and 16-bit ones double-width, even for Greek,
* Cyrillic, etc.) and not any typographic considerations.
*
* Much less clear is the choice of width for the Not East Asian
* (Neutral) class. Existing practice does not dictate a width for any
* of these characters. It would nevertheless make sense
* typographically to allocate two character cells to characters such
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
* represented adequately with a single-width glyph. The following
* routines at present merely assign a single-cell width to all
* neutral characters, in the interest of simplicity. This is not
* entirely satisfactory and should be reconsidered before
* establishing a formal standard in this area. At the moment, the
* decision which Not East Asian (Neutral) characters should be
* represented by double-width glyphs cannot yet be answered by
* applying a simple rule from the Unicode database content. Setting
* up a proper standard for the behavior of UTF-8 character terminals
* will require a careful analysis not only of each Unicode character,
* but also of each presentation form, something the author of these
* routines has avoided to do so far.
*
* http://www.unicode.org/unicode/reports/tr11/
*
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted. The author
* disclaims all warranties with regard to this software.
*
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
#include <wchar.h>
struct interval {
int first;
int last;
};
/* auxiliary function for binary search in interval table */
static int bisearch(wchar_t ucs, const struct interval *table, int max) {
int min = 0;
int mid;
if (ucs < table[0].first || ucs > table[max].last)
return 0;
while (max >= min) {
mid = (min + max) / 2;
if (ucs > table[mid].last)
min = mid + 1;
else if (ucs < table[mid].first)
max = mid - 1;
else
return 1;
}
return 0;
}
/* The following two functions define the column width of an ISO 10646
* character as follows:
*
* - The null character (U+0000) has a column width of 0.
*
* - Other C0/C1 control characters and DEL will lead to a return
* value of -1.
*
* - Non-spacing and enclosing combining characters (general
* category code Mn or Me in the Unicode database) have a
* column width of 0.
*
* - SOFT HYPHEN (U+00AD) has a column width of 1.
*
* - Other format characters (general category code Cf in the Unicode
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
*
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
* have a column width of 0.
*
* - Spacing characters in the East Asian Wide (W) or East Asian
* Full-width (F) category as defined in Unicode Technical
* Report #11 have a column width of 2.
*
* - All remaining characters (including all printable
* ISO 8859-1 and WGL4 characters, Unicode control characters,
* etc.) have a column width of 1.
*
* This implementation assumes that wchar_t characters are encoded
* in ISO 10646.
*/
int mk_wcwidth(wchar_t ucs)
{
/* sorted list of non-overlapping intervals of non-spacing characters */
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
static const struct interval combining[] = {
{ 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
{ 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
{ 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
{ 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
{ 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
{ 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
{ 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
{ 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
{ 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
{ 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
{ 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
{ 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
{ 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
{ 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
{ 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
{ 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
{ 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
{ 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
{ 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
{ 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
{ 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
{ 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
{ 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
{ 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
{ 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
{ 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
{ 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
{ 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
{ 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
{ 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
{ 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
{ 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
{ 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
{ 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
{ 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
{ 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
{ 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
{ 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
{ 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
{ 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
{ 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
{ 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
{ 0xE0100, 0xE01EF }
};
/* test for 8-bit control characters */
if (ucs == 0)
return 0;
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
return -1;
/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining,
sizeof(combining) / sizeof(struct interval) - 1))
return 0;
/* if we arrive here, ucs is not a combining or C0/C1 control character */
return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
ucs == 0x2329 || ucs == 0x232a ||
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
#ifndef _WIN32 // sizeof(wchar_t) == 2
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
(ucs >= 0x30000 && ucs <= 0x3fffd) ||
#endif
0
));
}
int mk_wcswidth(const wchar_t *pwcs, size_t n)
{
int w, width = 0;
for (;*pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
/*
* The following functions are the same as mk_wcwidth() and
* mk_wcswidth(), except that spacing characters in the East Asian
* Ambiguous (A) category as defined in Unicode Technical Report #11
* have a column width of 2. This variant might be useful for users of
* CJK legacy encodings who want to migrate to UCS without changing
* the traditional terminal character-width behaviour. It is not
* otherwise recommended for general use.
*/
int mk_wcwidth_cjk(wchar_t ucs)
{
/* sorted list of non-overlapping intervals of East Asian Ambiguous
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
static const struct interval ambiguous[] = {
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
{ 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
{ 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
{ 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
{ 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
{ 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
{ 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
{ 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
{ 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
{ 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
{ 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
{ 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
{ 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
{ 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
{ 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
{ 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
{ 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
{ 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
{ 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
{ 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
{ 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
{ 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
{ 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
{ 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
{ 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
{ 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
{ 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
{ 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
{ 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
{ 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
{ 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
{ 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
{ 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
{ 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
{ 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
{ 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
{ 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
{ 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
{ 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
{ 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
{ 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
{ 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
{ 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
{ 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
{ 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
{ 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
{ 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
{ 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
{ 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
{ 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
{ 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
};
/* binary search in table of non-spacing characters */
if (bisearch(ucs, ambiguous,
sizeof(ambiguous) / sizeof(struct interval) - 1))
return 2;
return mk_wcwidth(ucs);
}
int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
{
int w, width = 0;
for (;*pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
+6
View File
@@ -0,0 +1,6 @@
{
"home": "https://github.com/ridiculousfish/widecharwidth",
"license": "Public domain",
"version": "Unicode 17",
"author": "ridiculousfish"
}
File diff suppressed because it is too large Load Diff
+72 -20
View File
@@ -10,44 +10,96 @@
#include <ctype.h>
#include <inttypes.h>
bool ffParseModuleOptions(const char* key, const char* value)
{
if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) return false;
if (value && !*value) value = NULL;
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules)
{
FFModuleBaseInfo* baseInfo = *modules;
const char* subKey = ffOptionTestPrefix(key, baseInfo->name);
if (subKey != NULL)
{
if (subKey[0] == '\0' || subKey[0] == '-') // Key is exactly the module name or has a leading '-'
{
fprintf(stderr, "Error: unknown module key %s\n", key);
exit(477);
}
FF_STRBUF_AUTO_DESTROY moduleName = ffStrbufCreateS(baseInfo->name);
ffStrbufLowerCase(&moduleName);
FF_STRBUF_AUTO_DESTROY jsonKey = ffStrbufCreate();
bool flag = false;
for (const char* p = subKey; *p; ++p)
{
if (*p == '-')
{
if (flag)
{
fprintf(stderr, "Error: invalid double `-` in module key %s\n", key);
exit(477);
}
flag = true;
}
else
{
if (!isalpha((unsigned char)*p) && !isdigit((unsigned char)*p))
{
fprintf(stderr, "Error: invalid character `%c` in module key %s\n", *p, key);
exit(477);
}
if (flag)
{
flag = false;
ffStrbufAppendC(&jsonKey, (char) toupper((unsigned char) *p));
}
else
ffStrbufAppendC(&jsonKey, *p);
}
}
fprintf(stderr, "Error: Unsupported module option: %s\n", key);
fputs(" Support of module options has been removed. Please add the flag to the JSON config instead.\n", stderr);
fprintf(stderr, " Example (demonstration only): `{ \"modules\": [ { \"type\": \"%s\", \"%s\": %s%s%s } ] }`\n", moduleName.chars, jsonKey.chars, value ? "\"" : "", value ? value : "true", value ? "\"" : "");
fputs(" See <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration> for more information.\n", stderr);
exit(477);
}
}
return false;
}
void ffPrepareCommandOption(FFdata* data)
{
//If we don't have a custom structure, use the default one
if(data->structure.length == 0)
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME, ':'))
ffPrepareCPUUsage();
if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME))
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME, ':'))
{
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
ffInitDiskIOOptions(&options);
ffPrepareDiskIO(&options);
}
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME, ':'))
{
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
ffInitNetIOOptions(&options);
ffPrepareNetIO(&options);
}
if(instance.config.general.multithreading)
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME, ':'))
{
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
{
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
ffInitPublicIpOptions(&options);
ffPreparePublicIp(&options);
}
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
ffInitPublicIpOptions(&options);
ffPreparePublicIp(&options);
}
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
{
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
ffInitWeatherOptions(&options);
ffPrepareWeather(&options);
}
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME, ':'))
{
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
ffInitWeatherOptions(&options);
ffPrepareWeather(&options);
}
}
+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
+17
View File
@@ -1,4 +1,6 @@
#include "fastfetch.h"
#include "util/FFlist.h"
#include "util/FFstrbuf.h"
#include "common/font.h"
#include <string.h>
@@ -192,6 +194,21 @@ void ffFontInitValues(FFfont* font, const char* name, const char* size)
fontInitPretty(font);
}
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style)
{
ffFontInit(font);
if (name) ffStrbufInitMove(&font->name, name);
if (size) ffStrbufInitMove(&font->size, size);
if (style)
{
FFstrbuf* styleBuf = FF_LIST_ADD(FFstrbuf, font->styles);
ffStrbufInitMove(styleBuf, style);
}
fontInitPretty(font);
}
void ffFontInitWithSpace(FFfont* font, const char* rawName)
{
const char* pspace = strrchr(rawName, ' ');
+1
View File
@@ -15,6 +15,7 @@ void ffFontInit(FFfont* font);
void ffFontInitQt(FFfont* font, const char* data);
void ffFontInitPango(FFfont* font, const char* data);
void ffFontInitValues(FFfont* font, const char* name, const char* size);
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style);
void ffFontInitWithSpace(FFfont* font, const char* rawName);
void ffFontDestroy(FFfont* font);
+2 -2
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");
}
+15 -12
View File
@@ -30,6 +30,7 @@ static void initState(FFstate* state)
ffPlatformInit(&state->platform);
state->configDoc = NULL;
state->resultDoc = NULL;
state->dynamicInterval = 0;
{
// don't enable bright color if the terminal is in light mode
@@ -48,7 +49,7 @@ static void defaultConfig(void)
void ffInitInstance(void)
{
#ifdef WIN32
#ifdef _WIN32
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendat>
setlocale(LC_ALL, ".UTF8");
#else
@@ -74,6 +75,9 @@ static void resetConsole(void)
#if defined(_WIN32)
fflush(stdout);
#endif
if(instance.state.dynamicInterval > 0)
fputs("\033[?1049l", stdout); // Disable alternate buffer
}
#ifdef _WIN32
@@ -88,10 +92,6 @@ static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
resetConsole();
exit(0);
}
static void chldSignalHandler(FF_MAYBE_UNUSED int signal)
{
// empty; used to interrupt the poll and read syscalls
}
#endif
void ffStart(void)
@@ -117,7 +117,10 @@ void ffStart(void)
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
sigaction(SIGQUIT, &action, NULL);
sigaction(SIGCHLD, &(struct sigaction) { .sa_handler = chldSignalHandler }, NULL);
sigset_t newmask;
sigemptyset(&newmask);
sigaddset(&newmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &newmask, NULL);
#endif
//reset everything to default before we start printing
@@ -130,14 +133,17 @@ void ffStart(void)
if(ffDisableLinewrap)
fputs("\033[?7l", stdout);
if(instance.state.dynamicInterval > 0)
{
fputs("\033[?1049h\033[H", stdout); // Enable alternate buffer
fflush(stdout);
}
ffLogoPrint();
}
void ffFinish(void)
{
if(instance.config.logo.printRemaining)
ffLogoPrintRemaining();
resetConsole();
}
@@ -208,9 +214,6 @@ void ffListFeatures(void)
#if FF_HAVE_ZLIB
"zlib\n"
#endif
#if FF_HAVE_XFCONF
"xfconf\n"
#endif
#if FF_HAVE_SQLITE3
"sqlite3\n"
#endif
+23 -6
View File
@@ -83,6 +83,13 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
FF_C_NONNULL(2, 3)
bool ffAppendFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer);
FF_C_NONNULL(2)
static inline bool ffReadFDBuffer(FFNativeFD fd, FFstrbuf* buffer)
{
ffStrbufClear(buffer);
return ffAppendFDBuffer(fd, buffer);
}
FF_C_NONNULL(1, 2)
static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
{
@@ -171,19 +178,27 @@ static inline void ffUnsuppressIO(bool* suppressed)
void ffListFilesRecursively(const char* path, bool pretty);
static inline bool ffIsValidNativeFD(FFNativeFD fd)
{
#ifndef _WIN32
return fd >= 0;
#else
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
return fd != INVALID_HANDLE_VALUE && fd != NULL;
#endif
}
FF_C_NONNULL(1)
static inline bool wrapClose(FFNativeFD* pfd)
{
assert(pfd);
#ifndef WIN32
if (*pfd < 0)
return false;
if (!ffIsValidNativeFD(*pfd))
return false;
#ifndef _WIN32
close(*pfd);
#else
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
if (*pfd == NULL || *pfd == INVALID_HANDLE_VALUE)
return false;
CloseHandle(*pfd);
#endif
@@ -241,8 +256,10 @@ static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char*
}
FFNativeFD ffGetNullFD(void);
bool ffRemoveFile(const char* fileName);
#ifdef _WIN32
// Only O_RDONLY is supported
HANDLE openat(HANDLE dfd, const char* fileName, bool directory);
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory);
#endif
+20 -11
View File
@@ -15,11 +15,8 @@
#if FF_HAVE_WORDEXP
#include <wordexp.h>
#elif FF_HAVE_GLOB
#warning "<wordexp.h> is not available, use <glob.h> instead"
#include <glob.h>
#else
#warning "Neither <wordexp.h> nor <glob.h> is available"
#include <glob.h>
#endif
static void createSubfolders(const char* fileName)
@@ -136,14 +133,14 @@ bool ffAppendFileBufferRelative(int dfd, const char* fileName, FFstrbuf* buffer)
return ffAppendFDBuffer(fd, buffer);
}
bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* out)
bool ffPathExpandEnv(const char* in, FFstrbuf* out)
{
bool result = false;
#if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056
#if FF_HAVE_WORDEXP
wordexp_t exp;
if (wordexp(in, &exp, 0) != 0)
if (wordexp(in, &exp, 0) != 0) // WARN: 0 = no safety flags; command substitution allowed
return false;
if (exp.we_wordc >= 1)
@@ -154,16 +151,23 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
wordfree(&exp);
#elif FF_HAVE_GLOB
#else
glob_t gb;
if (glob(in, GLOB_NOSORT | GLOB_TILDE, NULL, &gb) != 0)
if (glob(in, GLOB_NOSORT
#ifdef GLOB_TILDE
| GLOB_TILDE
#endif
#ifdef GLOB_BRACE
| GLOB_BRACE
#endif
, NULL, &gb) != 0)
return false;
if (gb.gl_matchc >= 1)
if (gb.gl_pathc >= 1)
{
result = true;
ffStrbufSetS(out, gb.gl_pathv[gb.gl_matchc > 1 ? ffTimeGetNow() % gb.gl_matchc : 0]);
ffStrbufSetS(out, gb.gl_pathv[gb.gl_pathc > 1 ? ffTimeGetNow() % (unsigned) gb.gl_pathc : 0]);
}
globfree(&gb);
@@ -367,3 +371,8 @@ FFNativeFD ffGetNullFD(void)
hNullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
return hNullFile;
}
bool ffRemoveFile(const char* fileName)
{
return unlink(fileName) == 0;
}
+40 -18
View File
@@ -3,8 +3,8 @@
#include "util/stringUtils.h"
#include <windows.h>
#include "util/windows/nt.h"
#include <ntstatus.h>
#include <winternl.h>
static void createSubfolders(const char* fileName)
{
@@ -102,31 +102,48 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
return ffAppendFDBuffer(handle, buffer);
}
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory)
{
NTSTATUS ret;
UNICODE_STRING fileNameW;
ret = RtlAnsiStringToUnicodeString(&fileNameW, &(ANSI_STRING) {
.Length = (USHORT) strlen(fileName),
.Buffer = (PCHAR) fileName
}, TRUE);
if (!NT_SUCCESS(ret)) return INVALID_HANDLE_VALUE;
assert(fileNameLen <= 0x7FFF);
FF_AUTO_CLOSE_FD HANDLE hFile;
HANDLE hFile;
IO_STATUS_BLOCK iosb = {};
ret = NtOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
.Length = sizeof(OBJECT_ATTRIBUTES),
.RootDirectory = dfd,
.ObjectName = &fileNameW,
}, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE));
RtlFreeUnicodeString(&fileNameW);
if(!NT_SUCCESS(ret) || iosb.Information != FILE_OPENED)
if(!NT_SUCCESS(NtOpenFile(&hFile,
(directory ? FILE_LIST_DIRECTORY | FILE_TRAVERSE : FILE_READ_DATA | FILE_READ_EA) | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
.Length = sizeof(OBJECT_ATTRIBUTES),
.RootDirectory = dfd,
.ObjectName = &(UNICODE_STRING) {
.Buffer = (PWSTR) fileName,
.Length = fileNameLen * (USHORT) sizeof(wchar_t),
.MaximumLength = (fileNameLen + 1) * (USHORT) sizeof(wchar_t),
},
.Attributes = OBJ_CASE_INSENSITIVE,
},
&iosb,
FILE_SHARE_READ | (directory ? FILE_SHARE_WRITE | FILE_SHARE_DELETE : 0),
FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE)
)))
return INVALID_HANDLE_VALUE;
return hFile;
}
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
{
wchar_t fileNameW[MAX_PATH];
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName, -1, fileNameW, ARRAY_SIZE(fileNameW));
if (len == 0) return INVALID_HANDLE_VALUE;
// Implies `fileNameW[len] = L'\0';` and `len` includes the null terminator
for (int i = 0; i < len - 1; ++i)
{
if (fileNameW[i] == L'/')
fileNameW[i] = L'\\';
}
return openatW(dfd, fileNameW, (uint16_t)(len - 1), directory);
}
bool ffAppendFileBufferRelative(HANDLE dfd, const char* fileName, FFstrbuf* buffer)
{
HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false);
@@ -371,3 +388,8 @@ FFNativeFD ffGetNullFD(void)
});
return hNullFile;
}
bool ffRemoveFile(const char* fileName)
{
return DeleteFileA(fileName) != FALSE;
}
+10
View File
@@ -158,6 +158,16 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
ffPrepareCPUUsage();
break;
}
case 'c': case 'C': {
if (ffStrEqualsIgnCase(type, FF_COMMAND_MODULE_NAME))
{
__attribute__((__cleanup__(ffDestroyCommandOptions))) FFCommandOptions options;
ffInitCommandOptions(&options);
if (module) ffCommandModuleInfo.parseJsonObject(&options, module);
ffPrepareCommand(&options);
}
break;
}
case 'd': case 'D': {
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME))
{
+2 -2
View File
@@ -89,7 +89,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
uint32_t minMetric = UINT32_MAX;
int routeCount = 0;
FF_MAYBE_UNUSED int routeCount = 0;
while (true)
{
@@ -299,7 +299,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
uint32_t minMetric = UINT32_MAX;
int routeCount = 0;
FF_MAYBE_UNUSED int routeCount = 0;
while (true)
{
+7 -1
View File
@@ -44,7 +44,13 @@ typedef enum __attribute__((__packed__)) FFModuleKeyType
FF_MODULE_KEY_TYPE_NONE = 0,
FF_MODULE_KEY_TYPE_STRING = 1 << 0,
FF_MODULE_KEY_TYPE_ICON = 1 << 1,
FF_MODULE_KEY_TYPE_BOTH = FF_MODULE_KEY_TYPE_STRING | FF_MODULE_KEY_TYPE_ICON,
FF_MODULE_KEY_TYPE_SPACE_SHIFT = 4,
FF_MODULE_KEY_TYPE_BOTH_0 = FF_MODULE_KEY_TYPE_STRING | FF_MODULE_KEY_TYPE_ICON,
FF_MODULE_KEY_TYPE_BOTH_1 = FF_MODULE_KEY_TYPE_BOTH_0 | (1 << FF_MODULE_KEY_TYPE_SPACE_SHIFT),
FF_MODULE_KEY_TYPE_BOTH = FF_MODULE_KEY_TYPE_BOTH_1, // alias
FF_MODULE_KEY_TYPE_BOTH_2 = FF_MODULE_KEY_TYPE_BOTH_0 | (2 << FF_MODULE_KEY_TYPE_SPACE_SHIFT),
FF_MODULE_KEY_TYPE_BOTH_3 = FF_MODULE_KEY_TYPE_BOTH_0 | (3 << FF_MODULE_KEY_TYPE_SPACE_SHIFT),
FF_MODULE_KEY_TYPE_BOTH_4 = FF_MODULE_KEY_TYPE_BOTH_0 | (4 << FF_MODULE_KEY_TYPE_SPACE_SHIFT),
FF_MODULE_KEY_TYPE_FORCE_UNSIGNED = UINT8_MAX,
} FFModuleKeyType;
+7 -6
View File
@@ -28,17 +28,12 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
ffPrintColor(&instance.config.display.colorKeys);
}
bool hasIcon = false;
if (instance.config.display.keyType & FF_MODULE_KEY_TYPE_ICON && moduleArgs && moduleArgs->keyIcon.length > 0)
{
ffStrbufWriteTo(&moduleArgs->keyIcon, stdout);
hasIcon = true;
}
if (instance.config.display.keyType & FF_MODULE_KEY_TYPE_STRING)
{
if(hasIcon)
putchar(' ');
ffPrintCharTimes(' ', instance.config.display.keyType >> FF_MODULE_KEY_TYPE_SPACE_SHIFT);
//NULL check is required for modules with custom keys, e.g. disk with the folder path
if((printType & FF_PRINT_TYPE_NO_CUSTOM_KEY) || !moduleArgs || moduleArgs->key.length == 0)
@@ -136,6 +131,12 @@ void ffPrintCharTimes(char c, uint32_t times)
if(times == 0)
return;
if(times == 1)
{
putchar(c);
return;
}
char str[32];
memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled
for(uint32_t i = sizeof(str); i <= times; i += (uint32_t)sizeof(str))
+25 -4
View File
@@ -2,13 +2,30 @@
#include "util/FFstrbuf.h"
#include <sys/types.h>
#ifndef _WIN32
#include <sys/types.h> // pid_t
#endif
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr);
typedef struct FFProcessHandle {
#if _WIN32
void* pid; // HANDLE
void* pipeRead; // HANDLE
#else
pid_t pid;
int pipeRead;
#endif
} FFProcessHandle;
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle);
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer); // Destroys handle internally
static inline const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
{
const char* error = ffProcessAppendOutput(buffer, argv, false);
FFProcessHandle handle;
const char* error = ffProcessSpawn(argv, false, &handle);
if (error) return error;
error = ffProcessReadOutput(&handle, buffer);
if (!error)
ffStrbufTrimRightSpace(buffer);
return error;
@@ -16,7 +33,11 @@ static inline const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const ar
static inline const char* ffProcessAppendStdErr(FFstrbuf* buffer, char* const argv[])
{
const char* error = ffProcessAppendOutput(buffer, argv, true);
FFProcessHandle handle;
const char* error = ffProcessSpawn(argv, true, &handle);
if (error) return error;
error = ffProcessReadOutput(&handle, buffer);
if (!error)
ffStrbufTrimRightSpace(buffer);
return error;
+28 -35
View File
@@ -58,11 +58,9 @@ static inline int ffPipe2(int* fds, int flags)
// Not thread-safe
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle)
{
int pipes[2];
const int timeout = instance.config.general.processingTimeout;
if(ffPipe2(pipes, O_CLOEXEC) == -1)
return "pipe() failed";
@@ -146,7 +144,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if(childPid == 0)
{
//Child
// Child process
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
putenv("LANG=C.UTF-8");
@@ -157,11 +155,24 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
#endif
close(pipes[1]);
outHandle->pid = childPid;
outHandle->pipeRead = pipes[0];
return NULL;
}
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
{
assert(handle->pipeRead != -1);
assert(handle->pid != -1);
const int32_t timeout = instance.config.general.processingTimeout;
FF_AUTO_CLOSE_FD int childPipeFd = handle->pipeRead;
pid_t childPid = handle->pid;
handle->pipeRead = -1;
handle->pid = -1;
char str[FF_PIPE_BUFSIZ];
while(1)
for (;;)
{
if (timeout >= 0)
{
@@ -173,30 +184,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
}
else if (pollret < 0)
{
if (errno == EINTR)
{
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
if (waitpid(childPid, NULL, WNOHANG) == childPid)
{
// Read remaining data from the pipe
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
childPid = -1;
}
}
else
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) error";
}
}
else if (pollfd.revents & POLLERR)
else if (pollret < 0 || (pollfd.revents & POLLERR))
{
kill(childPid, SIGTERM);
waitpid(childPid, NULL, 0);
return "poll(&pollfd, 1, timeout) error";
return pollret < 0
? "poll(&pollfd, 1, timeout) error: pollret < 0"
: "poll(&pollfd, 1, timeout) error: pollfd.revents & POLLERR";
}
}
@@ -211,20 +205,15 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
if (!WIFEXITED(stat_loc))
return "child process exited abnormally";
if (WEXITSTATUS(stat_loc) == 127)
return "command was not found";
return "command not found";
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
return NULL;
}
return NULL;
}
else if (nRead < 0)
{
if (errno == EAGAIN)
return NULL;
else
break;
}
};
break;
}
return "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
}
@@ -284,6 +273,10 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
}
else
{
ffStrbufSetS(exePath, filePath);
}
}
#elif defined(__APPLE__)
+64 -41
View File
@@ -2,7 +2,7 @@
#include "common/processing.h"
#include "common/io/io.h"
#include <Windows.h>
#include <windows.h>
#include <ntstatus.h>
#include <winternl.h>
@@ -45,12 +45,13 @@ static void argvToCmdline(char* const argv[], FFstrbuf* result)
}
}
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle)
{
int timeout = instance.config.general.processingTimeout;
const int32_t timeout = instance.config.general.processingTimeout;
wchar_t pipeName[32];
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u", GetCurrentProcessId());
static unsigned pidCounter = 0;
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u-%u", GetCurrentProcessId(), ++pidCounter);
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
pipeName,
@@ -82,52 +83,67 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
return "CreateFileW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed";
PROCESS_INFORMATION piProcInfo = {};
BOOL success;
STARTUPINFOA siStartInfo = {
.cb = sizeof(siStartInfo),
.dwFlags = STARTF_USESTDHANDLES,
};
if (useStdErr)
{
STARTUPINFOA siStartInfo = {
.cb = sizeof(siStartInfo),
.dwFlags = STARTF_USESTDHANDLES,
};
if (useStdErr)
{
siStartInfo.hStdOutput = ffGetNullFD();
siStartInfo.hStdError = hChildPipeWrite;
}
else
{
siStartInfo.hStdOutput = hChildPipeWrite;
siStartInfo.hStdError = ffGetNullFD();
}
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
argvToCmdline(argv, &cmdline);
success = CreateProcessA(
NULL, // application name
cmdline.chars, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo // receives PROCESS_INFORMATION
);
siStartInfo.hStdOutput = ffGetNullFD();
siStartInfo.hStdError = hChildPipeWrite;
}
else
{
siStartInfo.hStdOutput = hChildPipeWrite;
siStartInfo.hStdError = ffGetNullFD();
}
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
argvToCmdline(argv, &cmdline);
BOOL success = CreateProcessA(
NULL, // application name
cmdline.chars, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo // receives PROCESS_INFORMATION
);
CloseHandle(hChildPipeWrite);
if(!success)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
return "command not found";
return "CreateProcessA() failed";
}
FF_AUTO_CLOSE_FD HANDLE hProcess = piProcInfo.hProcess;
FF_MAYBE_UNUSED FF_AUTO_CLOSE_FD HANDLE hThread = piProcInfo.hThread;
CloseHandle(piProcInfo.hThread); // we don't need the thread handle
outHandle->pid = piProcInfo.hProcess;
outHandle->pipeRead = hChildPipeRead;
hChildPipeRead = INVALID_HANDLE_VALUE; // ownership transferred, don't close it
return NULL;
}
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
{
assert(handle->pipeRead != INVALID_HANDLE_VALUE);
assert(handle->pid != INVALID_HANDLE_VALUE);
int32_t timeout = instance.config.general.processingTimeout;
FF_AUTO_CLOSE_FD HANDLE hProcess = handle->pid;
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = handle->pipeRead;
handle->pid = INVALID_HANDLE_VALUE;
handle->pipeRead = INVALID_HANDLE_VALUE;
char str[FF_PIPE_BUFSIZ];
DWORD nRead = 0;
OVERLAPPED overlapped = { };
OVERLAPPED overlapped = {};
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
do
{
@@ -164,7 +180,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
break;
case ERROR_BROKEN_PIPE:
return NULL;
goto exit;
default:
CancelIo(hChildPipeRead);
@@ -175,6 +191,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
ffStrbufAppendNS(buffer, nRead, str);
} while (nRead > 0);
exit:
{
DWORD exitCode = 0;
if (GetExitCodeProcess(hProcess, &exitCode) && exitCode != STILL_ACTIVE && exitCode != 0)
return "Child process exited with an error";
}
return NULL;
}
+126 -52
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]);
+39 -2
View File
@@ -63,6 +63,26 @@
},
"default": "default"
}
},
{
"long": "json",
"short": "j",
"arg": {
"type": "bool",
"default": false,
"optional": true
},
"desc": "Enable or disable JSON output",
"remark": "Shortcut for `--format json`"
},
{
"long": "dynamic-interval",
"desc": "Keep fastfetch open and update the output every <num> milliseconds",
"remark": "0 (default) to disable the behavior; don't work with --json",
"arg": {
"type": "num",
"default": 0
}
}
],
"Config": [
@@ -70,7 +90,7 @@
"short": "c",
"long": "config",
"desc": "Specify the config file or preset to load",
"remark": "The file will be searched according to the order shown by \"fastfetch --list-config-paths\". Use \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for more info",
"remark": "The file will be searched according to the order shown by \"fastfetch --list-config-paths\". Use \"-\" to read config from stdin or \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for more info",
"arg": {
"type": "config"
}
@@ -555,7 +575,12 @@
"none": "Disable keys",
"string": "Show string",
"icon": "Show icon (requires newest nerd font)",
"both": "Show both icon and string"
"both": "Show both icon and string (alias of `both-1`)",
"both-0": "Show both icon and string with no spaces between them",
"both-1": "Show both icon and string with a space between them",
"both-2": "Show both icon and string with 2 spaces between them",
"both-3": "Show both icon and string with 3 spaces between them",
"both-4": "Show both icon and string with 4 spaces between them"
},
"default": "string"
}
@@ -846,6 +871,18 @@
"default": -1
}
},
{
"long": "fraction-trailing-zeros",
"desc": "Set when to keep trailing zeros",
"arg": {
"type": "enum",
"enum": {
"default": "Use the behavior defined internally",
"always": "Always keep trailing zeros",
"never": "Never keep trailing zeros"
}
}
},
{
"long": "temp-unit",
"desc": "Set the temperature unit",
+28 -42
View File
@@ -5,69 +5,55 @@
const char* ffDetectBios(FFBiosResult* bios)
{
io_registry_entry_t registryEntry;
#ifndef __aarch64__
//https://github.com/osquery/osquery/blob/master/osquery/tables/system/darwin/smbios_tables.cpp
//For Intel
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
return "IORegistryEntryCreateCFProperties(registryEntry) failed";
}
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceRom = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom");
if (!deviceRom)
return "IODeviceTree:/rom not found";
ffCfDictGetString(properties, CFSTR("vendor"), &bios->vendor);
ffCfDictGetString(properties, CFSTR("version"), &bios->version);
ffCfDictGetString(properties, CFSTR("release-date"), &bios->date);
ffStrbufSetStatic(&bios->type, "UEFI");
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef deviceRomProps = NULL;
if(IORegistryEntryCreateCFProperties(deviceRom, &deviceRomProps, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
return "IORegistryEntryCreateCFProperties(deviceRom) failed";
CFRelease(properties);
IOObjectRelease(registryEntry);
return NULL;
}
ffCfDictGetString(deviceRomProps, CFSTR("vendor"), &bios->vendor);
ffCfDictGetString(deviceRomProps, CFSTR("version"), &bios->version);
ffCfDictGetString(deviceRomProps, CFSTR("release-date"), &bios->date);
ffStrbufSetStatic(&bios->type, "UEFI");
#else
//For arm64
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
{
ffCfDictGetString(properties, CFSTR("manufacturer"), &bios->vendor);
ffCfDictGetString(properties, CFSTR("time-stamp"), &bios->date);
CFRelease(properties);
}
IOObjectRelease(registryEntry);
}
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t device = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/");
if (!device)
return "IODeviceTree:/ not found";
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen")))
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef deviceProps = NULL;
if(IORegistryEntryCreateCFProperties(device, &deviceProps, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
return "IORegistryEntryCreateCFProperties(device) failed";
ffCfDictGetString(deviceProps, CFSTR("manufacturer"), &bios->vendor);
ffCfDictGetString(deviceProps, CFSTR("time-stamp"), &bios->date);
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t deviceChosen = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen");
if (deviceChosen)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
FF_CFTYPE_AUTO_RELEASE CFStringRef systemFirmWareVersion = IORegistryEntryCreateCFProperty(deviceChosen, CFSTR("system-firmware-version"), kCFAllocatorDefault, kNilOptions);
if (systemFirmWareVersion)
{
ffCfDictGetString(properties, CFSTR("system-firmware-version"), &bios->version);
ffCfStrGetString(systemFirmWareVersion, &bios->version);
uint32_t index = ffStrbufFirstIndexC(&bios->version, '-');
if (index != bios->version.length)
{
ffStrbufAppendNS(&bios->type, index, bios->version.chars);
ffStrbufRemoveSubstr(&bios->version, 0, index + 1);
}
else
{
ffStrbufSetStatic(&bios->type, "iBoot");
}
CFRelease(properties);
}
IOObjectRelease(registryEntry);
return NULL;
}
if (!bios->type.length)
ffStrbufSetStatic(&bios->type, "iBoot");
#endif
return "Failed to query bios info";
return NULL;
}
+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";
+82 -47
View File
@@ -55,7 +55,7 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
// Works for Apple Silicon and USB-C adapter connection ( but not HTMI )
static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
if (!IOAVServiceCreate || !IOAVServiceReadI2C || !IOAVServiceWriteI2C)
return "IOAVService is not available";
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
@@ -123,65 +123,100 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
return NULL;
}
#else
static IOOptionBits getSupportedTransactionType(void)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("IOFramebufferI2CInterface"), &iterator) != KERN_SUCCESS)
return kIOI2CNoTransactionType;
io_registry_entry_t registryEntry;
while ((registryEntry = IOIteratorNext(iterator)) != MACH_PORT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_service_t io_service = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFNumberRef IOI2CTransactionTypes = IORegistryEntryCreateCFProperty(io_service, CFSTR(kIOI2CTransactionTypesKey), kCFAllocatorDefault, kNilOptions);
if (IOI2CTransactionTypes)
{
int64_t types = 0;
ffCfNumGetInt64(IOI2CTransactionTypes, &types);
if (types) {
if ((1 << kIOI2CDDCciReplyTransactionType) & (uint64_t) types)
return kIOI2CDDCciReplyTransactionType;
if ((1 << kIOI2CSimpleTransactionType) & (uint64_t) types)
return kIOI2CSimpleTransactionType;
}
}
break;
}
return kIOI2CNoTransactionType;
}
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available";
IOOptionBits transactionType = getSupportedTransactionType();
if (transactionType == kIOI2CNoTransactionType)
return "No supported IOI2C transaction type found";
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_EXTERNAL)
{
io_service_t framebuffer = 0;
FF_IOOBJECT_AUTO_RELEASE io_service_t framebuffer = IO_OBJECT_NULL;
CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer);
if (framebuffer == 0) continue;
if (framebuffer == IO_OBJECT_NULL) continue;
IOItemCount count;
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue;
io_service_t interface = 0;
if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue;
uint8_t i2cOut[12] = {};
IOI2CConnectRef connect;
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS)
{
IOObjectRelease(interface);
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0)
continue;
for (IOItemCount bus = 0; bus < count; ++bus)
{
FF_IOOBJECT_AUTO_RELEASE io_service_t interface = IO_OBJECT_NULL;
if (IOFBCopyI2CInterfaceForBus(framebuffer, bus, &interface) != KERN_SUCCESS) continue;
uint8_t i2cOut[12] = {};
IOI2CConnectRef connect = NULL;
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS)
continue;
uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 };
i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3];
IOI2CRequest request = {
.commFlags = kNilOptions,
.sendAddress = 0x6e,
.sendTransactionType = kIOI2CSimpleTransactionType,
.sendBuffer = (vm_address_t) i2cIn,
.sendBytes = ARRAY_SIZE(i2cIn),
.minReplyDelay = options->ddcciSleep * 1000ULL,
.replyAddress = 0x6F,
.replySubAddress = 0x51,
.replyTransactionType = transactionType,
.replyBytes = ARRAY_SIZE(i2cOut),
.replyBuffer = (vm_address_t) i2cOut,
};
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
IOI2CInterfaceClose(connect, kNilOptions);
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess || request.replyBytes < 10) continue;
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue;
uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9];
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->max = max;
brightness->min = 0;
brightness->current = current;
ffStrbufInitCopy(&brightness->name, &display->name);
brightness->builtin = false;
break;
}
uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 };
i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3];
IOI2CRequest request = {
.commFlags = kNilOptions,
.sendAddress = 0x6e,
.sendTransactionType = kIOI2CSimpleTransactionType,
.sendBuffer = (vm_address_t) i2cIn,
.sendBytes = ARRAY_SIZE(i2cIn),
.minReplyDelay = options->ddcciSleep,
.replyAddress = 0x6F,
.replySubAddress = 0x51,
.replyTransactionType = kIOI2CDDCciReplyTransactionType,
.replyBytes = ARRAY_SIZE(i2cOut),
.replyBuffer = (vm_address_t) i2cOut,
};
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
IOI2CInterfaceClose(connect, kNilOptions);
IOObjectRelease(interface);
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue;
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue;
uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9];
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->max = max;
brightness->min = 0;
brightness->current = current;
ffStrbufInitCopy(&brightness->name, &display->name);
brightness->builtin = false;
}
}
+1 -1
View File
@@ -41,7 +41,7 @@ static const char* detectWithBacklight(FFlist* result)
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufSubstrBeforeLastC(&backlightDir, '/');
ffStrbufAppendS(&backlightDir, "/device");
ffStrbufInitA(&brightness->name, PATH_MAX + 1);
ffStrbufInitA(&brightness->name, PATH_MAX);
if(realpath(backlightDir.chars, brightness->name.chars))
{
ffStrbufRecalculateLength(&brightness->name);
+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
+60
View File
@@ -0,0 +1,60 @@
#include "common/processing.h"
#include "util/FFstrbuf.h"
#include "detection/command/command.h"
typedef struct FFCommandResultBundle
{
FFProcessHandle handle;
const char* error;
} FFCommandResultBundle;
// FIFO, non-thread-safe list of running commands
static FFlist commandQueue = {
.elementSize = sizeof(FFCommandResultBundle),
};
static const char* spawnProcess(FFCommandOptions* options, FFProcessHandle* handle)
{
if (options->text.length == 0)
return "No command text specified";
return ffProcessSpawn(options->param.length ? (char* const[]){
options->shell.chars,
options->param.chars,
options->text.chars,
NULL
} : (char* const[]){
options->shell.chars,
options->text.chars,
NULL
}, options->useStdErr, handle);
}
bool ffPrepareCommand(FFCommandOptions* options)
{
if (!options->parallel) return false;
FFCommandResultBundle* bundle = ffListAdd(&commandQueue);
bundle->error = spawnProcess(options, &bundle->handle);
return true;
}
const char* ffDetectCommand(FFCommandOptions* options, FFstrbuf* result)
{
FFCommandResultBundle bundle = {};
if (!options->parallel)
bundle.error = spawnProcess(options, &bundle.handle);
else if (!ffListShift(&commandQueue, &bundle))
return "[BUG] command queue is empty";
if (bundle.error)
return bundle.error;
bundle.error = ffProcessReadOutput(&bundle.handle, result);
if (bundle.error)
return bundle.error;
ffStrbufTrimRightSpace(result);
return NULL;
}
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include "fastfetch.h"
#include "modules/command/option.h"
const char* ffDetectCommand(FFCommandOptions* options, FFstrbuf* result);
+35 -63
View File
@@ -132,35 +132,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
#ifdef __linux__
#include "common/io/io.h"
#include <elf.h>
#include <asm/hwcap.h>
#ifndef HWCAP2_SME
#define HWCAP2_SME (1UL << 23)
#endif
#ifndef HWCAP2_SME2
#define HWCAP2_SME2 (1UL << 37)
#endif
#ifndef HWCAP2_CSSC
#define HWCAP2_CSSC (1UL << 34)
#endif
#ifndef HWCAP2_SME2P1
#define HWCAP2_SME2P1 (1UL << 38)
#endif
#ifndef HWCAP2_MOPS
#define HWCAP2_MOPS (1UL << 43)
#endif
#ifndef HWCAP2_F8E4M3
#define HWCAP2_F8E4M3 (1UL << 55)
#endif
#ifndef HWCAP2_F8E5M2
#define HWCAP2_F8E5M2 (1UL << 56)
#endif
#ifndef HWCAP_CMPBR
#define HWCAP_CMPBR (1UL << 33)
#endif
#ifndef HWCAP_FPRCVT
#define HWCAP_FPRCVT (1UL << 34)
#endif
// #include <asm/hwcap.h>
void ffCPUDetectByCpuid(FFCPUResult* cpu)
{
@@ -188,69 +160,69 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
cpu->march = "unknown";
// ARMv8-A
bool has_fp = (hwcap & HWCAP_FP) != 0;
bool has_asimd = (hwcap & HWCAP_ASIMD) != 0;
bool has_fp = (hwcap & (1 << 0) /* HWCAP_FP */) != 0;
bool has_asimd = (hwcap & (1 << 1) /* HWCAP_ASIMD */) != 0;
// ARMv8.1-A
bool has_atomics = (hwcap & HWCAP_ATOMICS) != 0; // optional from v8.0
bool has_crc32 = (hwcap & HWCAP_CRC32) != 0; // optional from v8.0
bool has_asimdrdm = (hwcap & HWCAP_ASIMDRDM) != 0; // optional from v8.0
bool has_atomics = (hwcap & (1 << 8) /* HWCAP_ATOMICS */) != 0; // optional from v8.0
bool has_crc32 = (hwcap & (1 << 7) /* HWCAP_CRC32 */) != 0; // optional from v8.0
bool has_asimdrdm = (hwcap & (1 << 12) /* HWCAP_ASIMDRDM */) != 0; // optional from v8.0
// ARMv8.2-A
bool has_fphp = (hwcap & HWCAP_FPHP) != 0; // optional
bool has_dcpop = (hwcap & HWCAP_DCPOP) != 0; // DC CVAP, optional from v8.1
bool has_fphp = (hwcap & (1 << 9) /* HWCAP_FPHP */) != 0; // optional
bool has_dcpop = (hwcap & (1 << 16) /* HWCAP_DCPOP */) != 0; // DC CVAP, optional from v8.1
// ARMv8.3-A
bool has_paca = (hwcap & HWCAP_PACA) != 0; // optional from v8.2
bool has_lrcpc = (hwcap & HWCAP_LRCPC) != 0; // optional from v8.2
bool has_fcma = (hwcap & HWCAP_FCMA) != 0; // optional from v8.2
bool has_jscvt = (hwcap & HWCAP_JSCVT) != 0; // optional from v8.2
bool has_paca = (hwcap & (1 << 30) /* HWCAP_PACA */) != 0; // optional from v8.2
bool has_lrcpc = (hwcap & (1 << 15) /* HWCAP_LRCPC */) != 0; // optional from v8.2
bool has_fcma = (hwcap & (1 << 14) /* HWCAP_FCMA */) != 0; // optional from v8.2
bool has_jscvt = (hwcap & (1 << 13) /* HWCAP_JSCVT */) != 0; // optional from v8.2
// ARMv8.4-A
bool has_dit = (hwcap & HWCAP_DIT) != 0; // optional from v8.3
bool has_flagm = (hwcap & HWCAP_FLAGM) != 0; // optional from v8.1
bool has_ilrcpc = (hwcap & HWCAP_ILRCPC) != 0; // optional from v8.2
bool has_dit = (hwcap & (1 << 24) /* HWCAP_DIT */) != 0; // optional from v8.3
bool has_flagm = (hwcap & (1 << 27) /* HWCAP_FLAGM */) != 0; // optional from v8.1
bool has_ilrcpc = (hwcap & (1 << 26) /* HWCAP_ILRCPC */) != 0; // optional from v8.2
// ARMv8.5-A
bool has_bti = (hwcap2 & HWCAP2_BTI) != 0; // optional from v8.4
bool has_sb = (hwcap & HWCAP_SB) != 0; // optional from v8.0
bool has_dcpodp = (hwcap2 & HWCAP2_DCPODP) != 0; // optional from v8.1
bool has_flagm2 = (hwcap2 & HWCAP2_FLAGM2) != 0; // optional from v8.4
bool has_frint = (hwcap2 & HWCAP2_FRINT) != 0; // optional from v8.4
bool has_bti = (hwcap2 & (1 << 17) /* HWCAP2_BTI */) != 0; // optional from v8.4
bool has_sb = (hwcap & (1 << 29) /* HWCAP_SB */) != 0; // optional from v8.0
bool has_dcpodp = (hwcap2 & (1 << 0) /* HWCAP2_DCPODP */) != 0; // optional from v8.1
bool has_flagm2 = (hwcap2 & (1 << 7) /* HWCAP2_FLAGM2 */) != 0; // optional from v8.4
bool has_frint = (hwcap2 & (1 << 8) /* HWCAP2_FRINT */) != 0; // optional from v8.4
// ARMv9.0-A
bool has_sve2 = (hwcap2 & HWCAP2_SVE2) != 0;
bool has_sve2 = (hwcap2 & (1 << 1) /* HWCAP2_SVE2 */) != 0;
// ARMv9.1-A
// ARMv8.6-A
bool has_bf16 = (hwcap2 & HWCAP2_BF16) != 0; // optional from v8.2
bool has_i8mm = (hwcap2 & HWCAP2_I8MM) != 0; // optional from v8.1
bool has_bf16 = (hwcap2 & (1 << 14) /* HWCAP2_BF16 */) != 0; // optional from v8.2
bool has_i8mm = (hwcap2 & (1 << 13) /* HWCAP2_I8MM */) != 0; // optional from v8.1
// ARMv8.7-A
bool has_afp = (hwcap2 & HWCAP2_AFP) != 0; // optional from v8.6
bool has_afp = (hwcap2 & (1 << 20) /* HWCAP2_AFP */) != 0; // optional from v8.6
// ARMv9.2-A
bool has_sme = (hwcap2 & HWCAP2_SME) != 0;
bool has_sme = (hwcap2 & (1 << 23) /* HWCAP2_SME */) != 0;
// ARMv9.3-A
bool has_sme2 = (hwcap2 & HWCAP2_SME2) != 0; // optional from v9.2
bool has_sme2 = (hwcap2 & (1UL << 37) /* HWCAP2_SME2 */) != 0; // optional from v9.2
// ARMv8.8-A
bool has_mops = (hwcap2 & HWCAP2_MOPS) != 0; // optional from v8.7
bool has_mops = (hwcap2 & (1UL << 43) /* HWCAP2_MOPS */) != 0; // optional from v8.7
// ARMv8.9-A
bool has_cssc = (hwcap2 & HWCAP2_CSSC) != 0; // optional from v8.7
bool has_cssc = (hwcap2 & (1UL << 34) /* HWCAP2_CSSC */) != 0; // optional from v8.7
// ARMv9.4-A
bool has_sme2p1 = (hwcap2 & HWCAP2_SME2P1) != 0; // optional from v9.2
bool has_sme2p1 = (hwcap2 & (1UL << 38) /* HWCAP2_SME2P1 */) != 0; // optional from v9.2
// ARMv9.5-A
bool has_f8e4m3 = (hwcap2 & HWCAP2_F8E4M3) != 0; // optional from v9.2
bool has_f8e5m2 = (hwcap2 & HWCAP2_F8E5M2) != 0; // optional from v9.2
bool has_f8e4m3 = (hwcap2 & (1UL << 55) /* HWCAP2_F8E4M3 */) != 0; // optional from v9.2
bool has_f8e5m2 = (hwcap2 & (1UL << 56) /* HWCAP2_F8E5M2 */) != 0; // optional from v9.2
// ARMv9.6-A
bool has_cmpbr = (hwcap & HWCAP_CMPBR) != 0; // optional from v9.5
bool has_fprcvt = (hwcap & HWCAP_FPRCVT) != 0; // optional from v9.5
bool has_cmpbr = (hwcap & (1UL << 33) /* HWCAP_CMPBR */) != 0; // optional from v9.5
bool has_fprcvt = (hwcap & (1UL << 34) /* HWCAP_FPRCVT */) != 0; // optional from v9.5
if (has_sve2 || has_sme) {
// ARMv9
@@ -457,7 +429,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
// ARMv8.4-A
// My CPU (Apple M1 Pro in VM) does support LSE2, but Windows doesn't detect it for some reason
// bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
bool has_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); // DotProd, optional from v8.1 (*)
// ARMv9.0-A
@@ -503,7 +475,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
cpu->march = "ARMv8.7-A";
} else if (has_i8mm && has_bf16) {
cpu->march = "ARMv8.6-A";
} else if (has_dp) {
} else if (has_dp && has_lse2) {
cpu->march = "ARMv8.4-A";
} else if (has_lrcpc && has_jscvt) {
cpu->march = "ARMv8.3-A";
+1
View File
@@ -21,6 +21,7 @@ typedef struct FFCPUResult
uint16_t coresPhysical;
uint16_t coresLogical;
uint16_t coresOnline;
uint16_t numaNodes;
uint32_t frequencyBase; // GHz
uint32_t frequencyMax; // GHz
+25 -17
View File
@@ -3,26 +3,34 @@
#include "util/apple/smc_temps.h"
#include "util/stringUtils.h"
static double detectCpuTemp(const FFstrbuf* cpuName)
static double detectCpuTemp(const FFCPUOptions* options, const FFstrbuf* cpuName)
{
double result = 0;
const char* error = NULL;
if (ffStrbufStartsWithS(cpuName, "Apple M"))
{
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
{
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
default: error = "Unsupported Apple Silicon CPU";
}
}
else // PPC?
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
if(error)
if (options->tempSensor.length)
{
error = ffDetectSmcSpecificTemp(options->tempSensor.chars, &result);
}
else
{
if (ffStrbufStartsWithS(cpuName, "Apple M"))
{
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
{
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
default: error = "Unsupported Apple Silicon CPU";
}
}
else // PPC?
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
}
if (error)
return FF_CPU_TEMP_UNSET;
return result;
@@ -39,7 +47,7 @@ static const char* detectFrequency(FFCPUResult* cpu)
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
if (!entryDevice)
return "IOServiceGetMatchingServices() failed";
return "IOServiceGetMatchingService() failed";
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
@@ -130,7 +138,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
detectFrequency(cpu);
if (options->showPeCoreCount) detectCoreCount(cpu);
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
cpu->temperature = options->temp ? detectCpuTemp(options, &cpu->name) : FF_CPU_TEMP_UNSET;
return NULL;
}
+5
View File
@@ -112,8 +112,12 @@ static const char* armPartId2name(uint32_t partId)
case 0xd87: return "Cortex-A725";
case 0xd88: return "Cortex-A520AE";
case 0xd89: return "Cortex-A720AE";
case 0xd8a: return "C1-Nano";
case 0xd8b: return "C1-Pro";
case 0xd8c: return "C1-Ultra";
case 0xd8e: return "Neoverse-N3";
case 0xd8f: return "Cortex-A320";
case 0xd90: return "C1-Premium";
default: return NULL;
}
}
@@ -213,6 +217,7 @@ static const char* nvidiaPartId2name(uint32_t partId)
case 0x000: return "Denver";
case 0x003: return "Denver 2";
case 0x004: return "Carmel";
case 0x010: return "Olympus";
default: return NULL;
}
}
+22 -20
View File
@@ -8,22 +8,26 @@
#define FF_HAVE_CPUSET 1
#endif
static const char* detectCpuTemp(double* current)
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
{
int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
if (temp == -999999)
return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed";
// In tenth of degrees Kelvin
*current = (double) temp / 10 - 273.15;
return NULL;
}
static const char* detectThermalTemp(double* current)
{
int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
if (temp == -999999)
return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed";
int temp;
if (options->tempSensor.length > 0)
{
temp = ffSysctlGetInt(options->tempSensor.chars, -999999);
if (temp == -999999)
return "ffSysctlGetInt(options->tempSensor) failed";
}
else
{
temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
if (temp == -999999)
{
// Thermal zone temperature
temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
if (temp == -999999)
return "ffSysctlGetInt(\"dev.cpu.0.temperature\" or \"hw.acpi.thermal.tz0.temperature\") failed";
}
}
// In tenth of degrees Kelvin
*current = (double) temp / 10 - 273.15;
@@ -94,11 +98,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
{
if (detectCpuTemp(&cpu->temperature) != NULL)
detectThermalTemp(&cpu->temperature);
}
if (options->temp) detectCpuTemp(options, &cpu->temperature);
cpu->numaNodes = (uint16_t) ffSysctlGetInt("vm.ndomains", 0);
return NULL;
}
+204 -36
View File
@@ -4,6 +4,7 @@
#include "common/properties.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include "util/path.h"
#include <sys/sysinfo.h>
#include <stdlib.h>
@@ -13,6 +14,22 @@
#define FF_CPUINFO_PATH "/proc/cpuinfo"
#ifndef O_PATH
#define O_PATH 0
#endif
static double readTempFile(int dfd, const char* filename, FFstrbuf* buffer)
{
if (filename ? !ffReadFileBufferRelative(dfd, filename, buffer) : !ffReadFDBuffer(dfd, buffer))
return FF_CPU_TEMP_UNSET;
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET); // millidegree Celsius
if (value == FF_CPU_TEMP_UNSET)
return FF_CPU_TEMP_UNSET;
return value / 1000.;
}
static double parseTZDir(int dfd, FFstrbuf* buffer)
{
if (!ffReadFileBufferRelative(dfd, "type", buffer))
@@ -26,18 +43,12 @@ static double parseTZDir(int dfd, FFstrbuf* buffer)
true
) return FF_CPU_TEMP_UNSET;
if (!ffReadFileBufferRelative(dfd, "temp", buffer))
return FF_CPU_TEMP_UNSET;
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius
if (value == FF_CPU_TEMP_UNSET)
return FF_CPU_TEMP_UNSET;
return value / 1000.;
return readTempFile(dfd, "temp", buffer);
}
static double parseHwmonDir(int dfd, FFstrbuf* buffer)
{
//https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
if (!ffReadFileBufferRelative(dfd, "name", buffer))
return FF_CPU_TEMP_UNSET;
@@ -53,25 +64,64 @@ static double parseHwmonDir(int dfd, FFstrbuf* buffer)
true
) return FF_CPU_TEMP_UNSET;
//https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
if (!ffReadFileBufferRelative(dfd, "temp1_input", buffer))
return FF_CPU_TEMP_UNSET;
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius
if (value == FF_CPU_TEMP_UNSET)
return FF_CPU_TEMP_UNSET;
return value / 1000.;
return readTempFile(dfd, "temp1_input", buffer);
}
static double detectCPUTemp(void)
static double detectCPUTemp(const FFCPUOptions* options)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (options->tempSensor.length > 0)
{
FF_AUTO_CLOSE_FD int subfd = -1;
const char* fileName = NULL;
if (ffStrbufStartsWithS(&options->tempSensor, "hwmon") && ffCharIsDigit(options->tempSensor.chars[strlen("hwmon")]))
{
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/hwmon/", O_PATH | O_CLOEXEC);
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (subfd >= 0)
fileName = "temp1_input";
else
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
}
else if (ffStrbufStartsWithS(&options->tempSensor, "thermal_zone") && ffCharIsDigit(options->tempSensor.chars[strlen("thermal_zone")]))
{
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/thermal/", O_PATH | O_CLOEXEC);
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (subfd >= 0)
fileName = "temp";
else
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
}
else if (ffStrbufStartsWithS(&options->tempSensor, "cputemp.") && ffCharIsDigit(options->tempSensor.chars[strlen("cputemp.")]))
{
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/platform/", O_PATH | O_CLOEXEC);
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (subfd >= 0)
fileName = "temp1_input";
else
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
}
else if (ffIsAbsolutePath(options->tempSensor.chars))
{
subfd = open(options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (subfd >= 0)
fileName = "temp1_input";
else
subfd = open(options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
}
if (subfd < 0)
return FF_CPU_TEMP_UNSET;
return readTempFile(subfd, fileName, &buffer);
}
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/hwmon/");
if(dirp)
{
int dfd = dirfd(dirp);
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
@@ -138,6 +188,21 @@ static double detectCPUTemp(void)
return FF_CPU_TEMP_UNSET;
}
static void detectNumaNodes(FFCPUResult* cpu)
{
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/sys/devices/system/node/");
if (!dir) return;
struct dirent* entry;
while ((entry = readdir(dir)) != NULL)
{
if (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN)
continue;
if (ffStrStartsWith(entry->d_name, "node") && ffCharIsDigit(entry->d_name[strlen("node")]))
cpu->numaNodes++;
}
}
#ifdef __ANDROID__
#include "common/settings.h"
@@ -145,11 +210,14 @@ static void detectQualcomm(FFCPUResult* cpu)
{
// https://en.wikipedia.org/wiki/List_of_Qualcomm_Snapdragon_systems_on_chips
assert(cpu->name.length >= 2);
uint32_t code = (uint32_t) strtoul(cpu->name.chars + 2, NULL, 10);
const char* name = NULL;
switch (code)
{
case 8845: name = "8 Gen 5"; break; // ?
case 8850: name = "8 Elite Gen 5"; break;
case 8735: name = "8s Gen 4"; break;
case 8750: name = "8 Elite"; break;
case 8635: name = "8s Gen 3"; break;
@@ -187,11 +255,13 @@ static void detectMediaTek(FFCPUResult* cpu)
{
// https://en.wikipedia.org/wiki/List_of_MediaTek_systems_on_chips
assert(cpu->name.length >= 2);
uint32_t code = (uint32_t) strtoul(cpu->name.chars + 2, NULL, 10);
const char* name = NULL;
switch (code) // The SOC code of MTK Dimensity series is full of mess
{
case 6993: name = "9500"; break;
case 6991: name = "9400"; break;
case 6989:
case 8796: name = "9300"; break;
@@ -216,25 +286,78 @@ static void detectMediaTek(FFCPUResult* cpu)
}
}
static void detectExynos(FFCPUResult* cpu)
{
// https://en.wikipedia.org/wiki/Exynos
assert(cpu->name.length > 3);
uint32_t code = (uint32_t) strtoul(cpu->name.chars + 3, NULL, 10);
const char* name = NULL;
switch (code)
{
case 9955: name = "2500"; break;
case 9945: name = "2400"; break;
// No 2300
case 9925: name = "2200"; break;
case 9840: name = "2100"; break;
case 8855: name = "1580"; break;
case 8845: name = "1480"; break;
case 8835: name = "1380"; break;
case 8535: name = "1330"; break;
case 8825: name = "1280"; break;
case 9815: name = "1080"; break;
case 9830: name = "990"; break;
case 9630: name = "980"; break;
case 8805: name = "880"; break;
case 3830: name = "850"; break;
}
if (name)
{
char str[32];
ffStrCopy(str, cpu->name.chars, sizeof(str));
ffStrbufSetF(&cpu->name, "Samsung Exynos %s [%s]", name, str);
return;
}
}
static void detectAndroid(FFCPUResult* cpu)
{
if (cpu->name.length == 0)
{
if (ffSettingsGetAndroidProperty("ro.soc.model", &cpu->name))
ffStrbufClear(&cpu->vendor); // We usually detect the vendor of CPU core as ARM, but instead we want the vendor of SOC
else if(ffSettingsGetAndroidProperty("ro.mediatek.platform", &cpu->name))
ffStrbufSetStatic(&cpu->vendor, "MTK");
}
if (cpu->vendor.length == 0)
{
if (!ffSettingsGetAndroidProperty("ro.soc.manufacturer", &cpu->vendor))
ffSettingsGetAndroidProperty("ro.product.product.manufacturer", &cpu->vendor);
if (!ffSettingsGetAndroidProperty("ro.product.product.manufacturer", &cpu->vendor))
if (!ffSettingsGetAndroidProperty("ro.product.vendor.manufacturer", &cpu->vendor))
if(ffSettingsGetAndroidProperty("ro.mediatek.platform", &cpu->name))
ffStrbufSetStatic(&cpu->vendor, "MediaTek");
}
if (ffStrbufEqualS(&cpu->vendor, "QTI") && ffStrbufStartsWithS(&cpu->name, "SM"))
if (ffStrbufEqualS(&cpu->vendor, "QTI"))
ffStrbufSetStatic(&cpu->vendor, "Qualcomm");
else if (ffStrbufIgnCaseEqualS(&cpu->vendor, "MediaTek")) // sometimes "Mediatek"
ffStrbufSetStatic(&cpu->vendor, "MediaTek");
else if (cpu->vendor.length > 0)
cpu->vendor.chars[0] = (char) toupper(cpu->vendor.chars[0]);
if (ffStrbufEqualS(&cpu->vendor, "Qualcomm") && ffStrbufStartsWithS(&cpu->name, "SM"))
detectQualcomm(cpu);
else if (ffStrbufEqualS(&cpu->vendor, "MTK") && ffStrbufStartsWithS(&cpu->name, "MT"))
else if (ffStrbufEqualS(&cpu->vendor, "MediaTek") && ffStrbufStartsWithS(&cpu->name, "MT"))
detectMediaTek(cpu);
else if (ffStrbufEqualS(&cpu->vendor, "Samsung") && ffStrbufStartsWithS(&cpu->name, "s5e"))
{
cpu->name.chars[0] = 'S';
cpu->name.chars[2] = 'E';
detectExynos(cpu);
}
}
#endif
@@ -353,6 +476,14 @@ static const char* parseCpuInfo(
(cpu->name.length == 0 && ffParsePropLine(line, "processor 0:", &cpu->name)) ||
(cpu->vendor.length == 0 && ffParsePropLine(line, "vendor_id :", &cpu->vendor)) ||
(cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz static :", cpuMHz)) || // This one cannot be detected because of early return
#elif __ia64__
(cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) ||
(cpu->vendor.length == 0 && ffParsePropLine(line, "vendor :", &cpu->vendor)) ||
(cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz :", cpuMHz)) ||
#elif __hppa__
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) ||
#elif __sh__
(cpu->name.length == 0 && ffParsePropLine(line, "cpu type :", &cpu->name)) ||
#else
(cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) ||
(cpu->name.length == 0 && ffParsePropLine(line, "model :", &cpu->name)) ||
@@ -502,6 +633,8 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0)
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
detectNumaNodes(cpu);
return NULL;
}
@@ -610,19 +743,46 @@ FF_MAYBE_UNUSED static void detectSocName(FFCPUResult* cpu)
if (cpu->name.length > 0)
return;
// device-vendor,device-model\0soc-vendor,soc-model\0
char content[256];
// [x-vendor,x-model\0]*N
char content[512];
ssize_t length = ffReadFileData("/proc/device-tree/compatible", ARRAY_SIZE(content), content);
if (length <= 2) return;
if (length < 4) return; // v,m\0
// get the second NUL terminated string if it exists
char* vendor = memchr(content, '\0', (size_t) length) + 1;
if (!vendor || vendor - content >= length) vendor = content;
if (content[length - 1] != '\0') return; // must end with \0
char* model = strchr(vendor, ',');
if (!model) return;
*model = '\0';
++model;
--length;
char* vendor = NULL;
char* model = NULL;
for (char* p; length > 0; length = p ? (ssize_t) (p - content) - 1 : 0)
{
p = memrchr(content, '\0', (size_t) length);
vendor = p /* first entry */ ? p + 1 : content;
size_t partLen = (size_t) (length - (vendor - content));
if (partLen < 3) continue;
char* comma = memchr(vendor, ',', partLen);
if (!comma) continue;
size_t vendorLen = (size_t) (comma - vendor);
if (vendorLen == 0) continue;
model = comma + 1;
size_t modelLen = (size_t) (partLen - (size_t) (model - vendor));
if (modelLen == 0) continue;
if ((modelLen >= strlen("-platform") && ffStrEndsWith(model, "-platform")) ||
(modelLen >= strlen("-soc") && ffStrEndsWith(model, "-soc")))
continue;
*comma = '\0';
break;
}
if (!length) return;
if (false) {}
#if __aarch64__
@@ -678,6 +838,13 @@ FF_MAYBE_UNUSED static void detectSocName(FFCPUResult* cpu)
for (const char* p = model; *p; ++p)
ffStrbufAppendC(&cpu->name, (char) toupper(*p));
}
else if (ffStrEquals(vendor, "thead"))
{
// Lichee Pi?
ffStrbufSetStatic(&cpu->vendor, "T-Head");
for (const char* p = model; *p; ++p)
ffStrbufAppendC(&cpu->name, (char) toupper(*p));
}
else
{
ffStrbufSetS(&cpu->name, model);
@@ -699,9 +866,9 @@ FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const c
char* pend;
unsigned long id = strtoul(p, &pend, 10);
if (__builtin_expect(id > 64, false))
high |= 1 << (id - 64);
high |= 1UL << (id - 64);
else
low |= 1 << id;
low |= 1UL << id;
p = pend;
}
@@ -777,6 +944,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
detectPhysicalCores(cpu);
ffCPUDetectByCpuid(cpu);
detectNumaNodes(cpu);
return NULL;
}
@@ -784,7 +952,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
cpu->temperature = options->temp ? detectCPUTemp(options) : FF_CPU_TEMP_UNSET;
#if __x86_64__ || __i386__
return detectCPUX86(options, cpu);
+17 -7
View File
@@ -16,7 +16,7 @@ static void freePropDict(prop_dictionary_t* pdict)
prop_object_release(*pdict);
}
static const char* detectCpuTemp(double* current)
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
{
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
@@ -25,11 +25,21 @@ static const char* detectCpuTemp(double* current)
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
prop_array_t array = prop_dictionary_get(root, "coretemp0");
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
if (!array) array = prop_dictionary_get(root, "viac7temp0");
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
if (!array) return "No temp data found in root dictionary";
prop_array_t array;
if (options->tempSensor.length > 0)
{
array = prop_dictionary_get(root, options->tempSensor.chars);
if (!array) return "No temp data found in specified sensor";
}
else
{
array = prop_dictionary_get(root, "coretemp0");
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
if (!array) array = prop_dictionary_get(root, "viac7temp0");
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
if (!array) return "No temp data found in root dictionary";
}
if (prop_array_count(array) != 2)
return "Unexpected `xtemp0` data";
@@ -73,7 +83,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp) detectCpuTemp(&cpu->temperature);
if (options->temp) detectCpuTemp(options, &cpu->temperature);
return NULL;
}
+12 -4
View File
@@ -6,7 +6,7 @@
#include <sys/time.h>
#include <sys/sensors.h>
static const char* detectCPUTemp(FFCPUResult* cpu)
static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu)
{
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
@@ -23,8 +23,16 @@ static const char* detectCPUTemp(FFCPUResult* cpu)
return "sysctl(sensordev) failed";
}
if (!ffStrStartsWith(sensordev.xname, "cpu"))
continue;
if (options->tempSensor.length > 0)
{
if (!ffStrbufEqualS(&options->tempSensor, sensordev.xname))
continue;
}
else
{
if (!ffStrStartsWith(sensordev.xname, "cpu"))
continue;
}
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
{
@@ -62,7 +70,7 @@ const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp) detectCPUTemp(cpu);
if (options->temp) detectCPUTemp(options, cpu);
return NULL;
}
+7 -2
View File
@@ -3,10 +3,15 @@
#include "util/stringUtils.h"
#include <kstat.h>
static const char* detectCPUTempByKstat(kstat_ctl_t* kc, FFCPUResult* cpu)
static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t* kc, FFCPUResult* cpu)
{
const char* possibleModules[] = {"temperature", "cpu_temp", "acpi_thermal", NULL};
if (options->tempSensor.length > 0) {
possibleModules[0] = options->tempSensor.chars;
possibleModules[1] = NULL;
}
for (int i = 0; possibleModules[i] != NULL; i++) {
kstat_t* ks = kstat_lookup(kc, possibleModules[i], -1, NULL);
if (ks && kstat_read(kc, ks, NULL) >= 0) {
@@ -141,7 +146,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (options->temp)
{
if (detectCPUTempByKstat(kc, cpu) != NULL)
if (detectCPUTempByKstat(options, kc, cpu) != NULL)
detectCPUTempByIpmiTool(cpu);
}
+23 -5
View File
@@ -17,7 +17,7 @@ static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
}
}
const char* detectThermalTemp(double* result)
const char* detectThermalTemp(const FFCPUOptions* options, double* result)
{
struct FFPerfQuerySpec
{
@@ -35,6 +35,14 @@ const char* detectThermalTemp(double* result)
.Name = L"\\_TZ.CPUZ", // The standard(?) instance name for CPU temperature in the thermal provider
};
if (options->tempSensor.length > 0)
{
int written = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, options->tempSensor.chars, (int) options->tempSensor.length, querySpec.Name, (int)(ARRAY_SIZE(querySpec.Name) - 1));
if (written == 0)
return "Invalid temp sensor string";
querySpec.Name[written] = L'\0';
}
DWORD dataSize = 0;
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
return "PerfEnumerateCounterSetInstances() failed";
@@ -62,6 +70,9 @@ const char* detectThermalTemp(double* result)
if (dataSize == 0)
{
if (options->tempSensor.length > 0)
return "Unable to find CPU sensor";
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pHead + sizeof(*pHead));
wcscpy(querySpec.Name, instanceName); // Use the first instance name if the specific one is not found
}
@@ -102,12 +113,16 @@ const char* detectThermalTemp(double* result)
if (pCounterData->dwDataSize == sizeof(int32_t))
{
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
int32_t value = *(int32_t*)(pCounterData + 1);
if (value == 0)
return "Temperature data is zero";
switch (pCounterIds[iCounter]) {
case 0: // Temperature
*result = *(int32_t*)(pCounterData + 1) - 273;
*result = value - 273;
break;
case 3: // High Precision Temperature
*result = *(int32_t*)(pCounterData + 1) / 10.0 - 273;
*result = value / 10.0 - 273;
break;
}
}
@@ -226,6 +241,8 @@ static const char* detectNCores(FFCPUResult* cpu)
++cpu->coresPhysical;
else if (ptr->Relationship == RelationProcessorPackage)
++cpu->packages;
else if (ptr->Relationship == RelationNumaNode)
++cpu->numaNodes;
}
return NULL;
@@ -238,7 +255,8 @@ static const char* detectByRegistry(FFCPUResult* cpu)
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
if (ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL))
ffStrbufTrimRightSpace(&cpu->vendor);
if (cpu->coresLogical == 0)
{
@@ -294,7 +312,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
detectMaxSpeedBySmbios(cpu);
if(options->temp)
detectThermalTemp(&cpu->temperature);
detectThermalTemp(options, &cpu->temperature);
return NULL;
}
+1 -1
View File
@@ -9,7 +9,7 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result)
if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed";
// macOS provides the global system cache line size
uint32_t lineSize = (uint32_t) ffSysctlGetInt("hw.cachelinesize", 0);
uint32_t lineSize = (uint32_t) ffSysctlGetInt64("hw.cachelinesize", 0);
char sysctlKey[128] = "hw.perflevelN.";
char* pNum = sysctlKey + strlen("hw.perflevel");
+25 -26
View File
@@ -1,30 +1,5 @@
#include "disk.h"
bool ffDiskMatchMountpoint(FFstrbuf* folders, const char* mountpoint)
{
#ifdef _WIN32
const char separator = ';';
#else
const char separator = ':';
#endif
uint32_t mountpointLength = (uint32_t) strlen(mountpoint);
uint32_t startIndex = 0;
while(startIndex < folders->length)
{
uint32_t colonIndex = ffStrbufNextIndexC(folders, startIndex, separator);
uint32_t folderLength = colonIndex - startIndex;
if (folderLength == mountpointLength && memcmp(folders->chars + startIndex, mountpoint, mountpointLength) == 0)
return true;
startIndex = colonIndex + 1;
}
return false;
}
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
{
return ffStrbufComp(&disk1->mountpoint, &disk2->mountpoint);
@@ -35,7 +10,7 @@ const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
const char* error = ffDetectDisksImpl(options, disks);
if (error) return error;
if (disks->length == 0) return "No disks found";
if (disks->length == 0) return NULL;
//We need to sort the disks, so that we can detect, which disk a path resides on
// For example for /boot/efi/bootmgr we need to check /boot/efi before /boot
@@ -56,3 +31,27 @@ const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
return NULL;
}
#ifndef _WIN32
#include <fnmatch.h>
bool ffDiskMatchesFolderPatterns(FFstrbuf* folders, const char* path, char separator)
{
uint32_t startIndex = 0;
while(startIndex < folders->length)
{
uint32_t sepIndex = ffStrbufNextIndexC(folders, startIndex, separator);
char savedSep = folders->chars[sepIndex]; // Can be '\0' if at end
folders->chars[sepIndex] = '\0';
bool matched = fnmatch(&folders->chars[startIndex], path, 0) == 0;
folders->chars[sepIndex] = savedSep;
if (matched) return true;
startIndex = sepIndex + 1;
}
return false;
}
#endif
+10 -1
View File
@@ -3,6 +3,12 @@
#include "fastfetch.h"
#include "modules/disk/option.h"
#ifdef _WIN32
#define FF_DISK_FOLDER_SEPARATOR ';'
#else
#define FF_DISK_FOLDER_SEPARATOR ':'
#endif
typedef struct FFDisk
{
FFstrbuf mountFrom;
@@ -29,4 +35,7 @@ typedef struct FFDisk
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks /* list of FFDisk */);
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks);
bool ffDiskMatchMountpoint(FFstrbuf* folders, const char* mountpoint);
#ifndef _WIN32
bool ffDiskMatchesFolderPatterns(FFstrbuf* folders, const char* path, char separator);
#endif
+7 -1
View File
@@ -145,12 +145,18 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
{
if(__builtin_expect(options->folders.length > 0, 0))
{
if(!ffDiskMatchMountpoint(&options->folders, fs->f_mntonname))
if(!ffStrbufSeparatedContainS(&options->folders, fs->f_mntonname, FF_DISK_FOLDER_SEPARATOR))
continue;
}
else if(!ffStrEquals(fs->f_mntonname, "/") && !ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs") && !ffStrEquals(fs->f_fstypename, "fusefs.sshfs"))
continue;
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, fs->f_mntonname, FF_DISK_FOLDER_SEPARATOR))
continue;
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, fs->f_fstypename, ':'))
continue;
#ifdef __FreeBSD__
// f_bavail and f_ffree are signed on FreeBSD...
if(fs->f_bavail < 0) fs->f_bavail = 0;
+7 -1
View File
@@ -23,10 +23,16 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
if (__builtin_expect(options->folders.length, 0))
{
if (!ffDiskMatchMountpoint(&options->folders, path.Path()))
if (!ffStrbufSeparatedContainS(&options->folders, path.Path(), FF_DISK_FOLDER_SEPARATOR))
continue;
}
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, path.Path(), FF_DISK_FOLDER_SEPARATOR))
continue;
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, fs.fsh_name, ':'))
continue;
FFDisk* disk = (FFDisk*) ffListAdd(disks);
disk->bytesTotal = (uint64_t)fs.total_blocks * (uint64_t) fs.block_size;
+13 -3
View File
@@ -10,6 +10,10 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
#if defined(STATX_BTIME) && !defined(__ANDROID__)
#include <sys/syscall.h>
#endif
#ifdef __USE_LARGEFILE64
#define stat stat64
#define statvfs statvfs64
@@ -263,9 +267,9 @@ static void detectStats(FFDisk* disk)
}
disk->createTime = 0;
#ifdef FF_HAVE_STATX
#ifdef SYS_statx
struct statx stx;
if (statx(0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME))
if (syscall(SYS_statx, 0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec > 685065600 /*birth of Linux*/)
disk->createTime = (uint64_t)((stx.stx_btime.tv_sec * 1000) + (stx.stx_btime.tv_nsec / 1000000));
#endif
@@ -287,12 +291,18 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
{
if (__builtin_expect(options->folders.length > 0, false))
{
if (!ffDiskMatchMountpoint(&options->folders, device->mnt_dir))
if (!ffStrbufSeparatedContainS(&options->folders, device->mnt_dir, FF_DISK_FOLDER_SEPARATOR))
continue;
}
else if(!isPhysicalDevice(device))
continue;
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, device->mnt_dir, FF_DISK_FOLDER_SEPARATOR))
continue;
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, device->mnt_type, ':'))
continue;
//We have a valid device, add it to the list
FFDisk* disk = ffListAdd(disks);
disk->type = FF_DISK_VOLUME_TYPE_NONE;
+7 -1
View File
@@ -113,12 +113,18 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
{
if (__builtin_expect(options->folders.length, 0))
{
if (!ffDiskMatchMountpoint(&options->folders, device.mnt_mountp))
if (!ffStrbufSeparatedContainS(&options->folders, device.mnt_mountp, FF_DISK_FOLDER_SEPARATOR))
continue;
}
else if(!isPhysicalDevice(&device))
continue;
if (options->hideFolders.length && ffDiskMatchesFolderPatterns(&options->hideFolders, device.mnt_mountp, FF_DISK_FOLDER_SEPARATOR))
continue;
if (options->hideFS.length && ffStrbufSeparatedContainS(&options->hideFS, device.mnt_fstype, ':'))
continue;
//We have a valid device, add it to the list
FFDisk* disk = ffListAdd(disks);
disk->type = FF_DISK_VOLUME_TYPE_NONE;
+26 -14
View File
@@ -47,12 +47,35 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
if (__builtin_expect((long) options->folders.length, 0))
{
if (!ffDiskMatchMountpoint(&options->folders, buffer.chars))
if (!ffStrbufSeparatedContain(&options->folders, &buffer, FF_DISK_FOLDER_SEPARATOR))
continue;
}
else if(driveType == DRIVE_NO_ROOT_DIR)
continue;
if (options->hideFolders.length && ffStrbufSeparatedContain(&options->hideFolders, &buffer, FF_DISK_FOLDER_SEPARATOR))
continue;
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
DWORD diskFlags;
BOOL volumeInfoAvailable = GetVolumeInformationW(mountpoint,
diskName, ARRAY_SIZE(diskName), //Volume name
NULL, //Serial number
NULL, //Max component length
&diskFlags, //File system flags
diskFileSystem, ARRAY_SIZE(diskFileSystem)
);
FF_STRBUF_AUTO_DESTROY diskFileSystemBuf = ffStrbufCreate();
if (volumeInfoAvailable)
{
ffStrbufSetWS(&diskFileSystemBuf, diskFileSystem);
if (options->hideFS.length && ffStrbufSeparatedContain(&options->hideFS, &diskFileSystemBuf, ':'))
continue;
}
FFDisk* disk = ffListAdd(disks);
disk->filesUsed = 0;
@@ -97,20 +120,9 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
(PULARGE_INTEGER)&disk->bytesFree
);
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
DWORD diskFlags;
BOOL result = GetVolumeInformationW(mountpoint,
diskName, ARRAY_SIZE(diskName), //Volume name
NULL, //Serial number
NULL, //Max component length
&diskFlags, //File system flags
diskFileSystem, ARRAY_SIZE(diskFileSystem)
);
if(result)
if(volumeInfoAvailable)
{
ffStrbufSetWS(&disk->filesystem, diskFileSystem);
ffStrbufInitMove(&disk->filesystem, &diskFileSystemBuf);
ffStrbufSetWS(&disk->name, diskName);
if(diskFlags & FILE_READ_ONLY_VOLUME)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
@@ -45,6 +45,7 @@ FFDisplayResult* ffdsAppendDisplay(
display->manufactureYear = 0;
display->manufactureWeek = 0;
display->serial = 0;
display->drrStatus = FF_DISPLAY_DRR_STATUS_UNKNOWN;
return display;
}
@@ -44,6 +44,7 @@
#define FF_WM_PROTOCOL_TTY "TTY"
#define FF_WM_PROTOCOL_X11 "X11"
#define FF_WM_PROTOCOL_WAYLAND "Wayland"
#define FF_WM_PROTOCOL_SURFACEFLINGER "SurfaceFlinger"
typedef enum __attribute__((__packed__)) FFDisplayType {
FF_DISPLAY_TYPE_UNKNOWN,
@@ -59,6 +60,13 @@ typedef enum __attribute__((__packed__)) FFDisplayHdrStatus
FF_DISPLAY_HDR_STATUS_ENABLED,
} FFDisplayHdrStatus;
typedef enum __attribute__((__packed__)) FFDisplayVrrStatus
{
FF_DISPLAY_DRR_STATUS_UNKNOWN,
FF_DISPLAY_DRR_STATUS_DISABLED,
FF_DISPLAY_DRR_STATUS_ENABLED,
} FFDisplayVrrStatus;
typedef struct FFDisplayResult
{
uint32_t width; // in px
@@ -82,6 +90,7 @@ typedef struct FFDisplayResult
uint16_t manufactureYear;
uint16_t manufactureWeek;
uint32_t serial;
FFDisplayVrrStatus drrStatus;
} FFDisplayResult;
typedef struct FFDisplayServerResult
@@ -1,6 +1,7 @@
#include "displayserver.h"
#include "common/settings.h"
#include "common/processing.h"
#include "linux/displayserver_linux.h"
#include <math.h>
@@ -82,13 +83,10 @@ static void detectWithDumpsys(FFDisplayServerResult* ds)
ffStrbufRecalculateLength(&name);
FFDisplayResult* display = ffdsAppendDisplay(ds,
(uint32_t)width,
(uint32_t)height,
(uint32_t)width, (uint32_t)height,
refreshRate,
0,
0,
0,
0,
0, 0,
0, 0,
0,
0,
&name,
@@ -121,13 +119,10 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
ffStrbufSubstrAfterFirstC(&buffer, ',');
double scaleFactor = (double) ffStrbufToUInt(&buffer, 0) / 160.;
FFDisplayResult* display = ffdsAppendDisplay(ds,
width,
height,
0,
(uint32_t) (width / scaleFactor + .5),
(uint32_t) (height / scaleFactor + .5),
0,
width, height,
0,
(uint32_t) (width / scaleFactor + .5), (uint32_t) (height / scaleFactor + .5),
0, 0,
0,
0,
NULL,
@@ -145,11 +140,79 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
return false;
}
static bool detectDE(FFDisplayServerResult* ds)
{
if (ffSettingsGetAndroidProperty("ro.vivo.os.build.display.id", &ds->dePrettyName)) // OriginOS 6
{
ffStrbufAppendC(&ds->dePrettyName, ' ');
ffSettingsGetAndroidProperty("ro.vivo.product.version", &ds->dePrettyName); // PD2505D_xxx
return true;
}
if (ffSettingsGetAndroidProperty("ro.build.version.magic", &ds->dePrettyName) ||
ffSettingsGetAndroidProperty("ro.build.version.emui", &ds->dePrettyName))
{
ffStrbufReplaceAllC(&ds->dePrettyName, '_', ' ');
return true;
}
if (ffSettingsGetAndroidProperty("ro.mi.os.version.name", &ds->dePrettyName))
{
// MiUI like
ffStrbufClear(&ds->dePrettyName);
ffSettingsGetAndroidProperty("ro.build.version.incremental", &ds->dePrettyName); // Detail version number
if (ffStrbufStartsWithS(&ds->dePrettyName, "OS"))
{
ds->dePrettyName.chars[0] = 'S';
ds->dePrettyName.chars[1] = ' ';
ffStrbufPrependS(&ds->dePrettyName, "HyperO");
}
else if (ffStrbufStartsWithS(&ds->dePrettyName, "V"))
{
ds->dePrettyName.chars[0] = ' ';
ffStrbufPrependS(&ds->dePrettyName, "MiUI");
}
else
ffStrbufSetStatic(&ds->dePrettyName, "MiUI");
return true;
}
if (ffSettingsGetAndroidProperty("ro.build.version.oplusrom", &ds->dePrettyName))
{
if (ffStrbufStartsWithS(&ds->dePrettyName, "V"))
ffStrbufSubstrAfter(&ds->dePrettyName, 0);
ffStrbufPrependS(&ds->dePrettyName, "ColorOS");
return true;
}
if (ffSettingsGetAndroidProperty("ro.oxygen.version", &ds->dePrettyName))
{
ffStrbufPrependS(&ds->dePrettyName, "OxygenOS");
return true;
}
if (ffSettingsGetAndroidProperty("ro.build.display.id", &ds->dePrettyName) && ffStrbufStartsWithS(&ds->dePrettyName, "RedMagicOS"))
{
ffStrbufInsertNC(&ds->dePrettyName, strlen("RedMagicOS"), 1, ' ');
return true;
}
return false;
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
{
ffStrbufSetStatic(&ds->wmProcessName, "surfaceflinger");
ffStrbufSetStatic(&ds->wmPrettyName, "SurfaceFlinger");
const char* error = ffdsConnectXcbRandr(ds);
if (error)
error = ffdsConnectXrandr(ds);
if (!error)
{
ffdsDetectWMDE(ds);
return;
}
// https://source.android.com/docs/core/graphics/surfaceflinger-windowmanager
ffStrbufSetStatic(&ds->wmProcessName, "system_server");
ffStrbufSetStatic(&ds->wmPrettyName, "WindowManager"); // A system service managed by system_server
ffStrbufSetStatic(&ds->wmProtocolName, FF_WM_PROTOCOL_SURFACEFLINGER);
if (!detectWithGetprop(ds))
detectWithDumpsys(ds);
detectDE(ds);
}
@@ -196,21 +196,5 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
}
}
const FFOSResult* os = ffDetectOS();
char* str_end;
const char* version = os->version.chars;
unsigned long osNum = strtoul(version, &str_end, 10);
if (str_end != version)
{
if (osNum > 15) { // Tahoe
ffStrbufSetStatic(&ds->dePrettyName, "Liquid Glass");
} else if (osNum < 10) {
ffStrbufSetStatic(&ds->dePrettyName, "Platinum");
} else {
ffStrbufSetStatic(&ds->dePrettyName, "Aqua");
}
}
detectDisplays(ds);
}
@@ -1,12 +1,9 @@
#include "displayserver.h"
#include "detection/os/os.h"
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
#include "util/mallocHelper.h"
#include "util/edidHelper.h"
#include <dwmapi.h>
#include <WinUser.h>
#include <winuser.h>
#include <wchar.h>
typedef struct FFMonitorInfo
@@ -232,6 +229,7 @@ static void detectDisplays(FFDisplayServerResult* ds)
}
if (edidLength > 0)
ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek);
display->drrStatus = path->flags & DISPLAYCONFIG_PATH_BOOST_REFRESH_RATE ? FF_DISPLAY_DRR_STATUS_ENABLED : FF_DISPLAY_DRR_STATUS_DISABLED;
}
}
}
@@ -254,27 +252,4 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
}
detectDisplays(ds);
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
const FFOSResult* os = ffDetectOS();
uint32_t ver = (uint32_t) ffStrbufToUInt(&os->version, 0);
if (ver > 1000)
{
// Windows Server
if (ver >= 2016)
ffStrbufSetStatic(&ds->dePrettyName, "Fluent");
else if (ver >= 2012)
ffStrbufSetStatic(&ds->dePrettyName, "Metro");
else
ffStrbufSetStatic(&ds->dePrettyName, "Aero");
}
else
{
if (ver >= 10)
ffStrbufSetStatic(&ds->dePrettyName, "Fluent");
else if (ver >= 8)
ffStrbufSetStatic(&ds->dePrettyName, "Metro");
else
ffStrbufSetStatic(&ds->dePrettyName, "Aero");
}
}
@@ -0,0 +1,16 @@
#include "displayserver_linux.h"
#include "util/stringUtils.h"
FFDisplayType ffdsGetDisplayType(const char* name)
{
if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-"))
return FF_DISPLAY_TYPE_BUILTIN;
else if(ffStrStartsWith(name, "HDMI-") ||
ffStrStartsWith(name, "DP-") ||
ffStrStartsWith(name, "DisplayPort-") ||
ffStrStartsWith(name, "DVI-") ||
ffStrStartsWith(name, "VGA-"))
return FF_DISPLAY_TYPE_EXTERNAL;
return FF_DISPLAY_TYPE_UNKNOWN;
}
@@ -95,17 +95,3 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
ffdsDetectWMDE(ds);
}
}
FFDisplayType ffdsGetDisplayType(const char* name)
{
if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-"))
return FF_DISPLAY_TYPE_BUILTIN;
else if(ffStrStartsWith(name, "HDMI-") ||
ffStrStartsWith(name, "DP-") ||
ffStrStartsWith(name, "DisplayPort-") ||
ffStrStartsWith(name, "DVI-") ||
ffStrStartsWith(name, "VGA-"))
return FF_DISPLAY_TYPE_EXTERNAL;
return FF_DISPLAY_TYPE_UNKNOWN;
}
+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,
@@ -239,6 +239,11 @@ enum kde_output_device_v2_capability {
* @since 17
*/
KDE_OUTPUT_DEVICE_V2_CAPABILITY_SHARPNESS = 0x1000,
/**
* if this outputdevice supports custom modes
* @since 18
*/
KDE_OUTPUT_DEVICE_V2_CAPABILITY_CUSTOM_MODES = 0x2000,
};
/**
* @ingroup iface_kde_output_device_v2
@@ -280,6 +285,10 @@ enum kde_output_device_v2_capability {
* @ingroup iface_kde_output_device_v2
*/
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_SHARPNESS_SINCE_VERSION 17
/**
* @ingroup iface_kde_output_device_v2
*/
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_CUSTOM_MODES_SINCE_VERSION 18
#endif /* KDE_OUTPUT_DEVICE_V2_CAPABILITY_ENUM */
#ifndef KDE_OUTPUT_DEVICE_V2_VRR_POLICY_ENUM
@@ -794,6 +803,23 @@ struct kde_output_device_v2_listener {
void (*sharpness)(void *data,
struct kde_output_device_v2 *kde_output_device_v2,
uint32_t sharpness);
/**
* output priority
*
* Describes the position of the output in the output order list,
* with lower values being earlier in the list. There's no specific
* value the list has to start at, this value is only used in
* sorting outputs.
*
* Note that the output order protocol is not sufficient for this,
* as an output may not be in the output order if it's disabled or
* mirroring another screen.
* @param priority priority
* @since 18
*/
void (*priority)(void *data,
struct kde_output_device_v2 *kde_output_device_v2,
uint32_t priority);
};
/**
@@ -943,6 +969,10 @@ kde_output_device_v2_add_listener(struct kde_output_device_v2 *kde_output_device
* @ingroup iface_kde_output_device_v2
*/
#define KDE_OUTPUT_DEVICE_V2_SHARPNESS_SINCE_VERSION 17
/**
* @ingroup iface_kde_output_device_v2
*/
#define KDE_OUTPUT_DEVICE_V2_PRIORITY_SINCE_VERSION 18
/** @ingroup iface_kde_output_device_v2 */
@@ -972,6 +1002,18 @@ kde_output_device_v2_destroy(struct kde_output_device_v2 *kde_output_device_v2)
wl_proxy_destroy((struct wl_proxy *) kde_output_device_v2);
}
#ifndef KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM
#define KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM
/**
* @ingroup iface_kde_output_device_mode_v2
* mode flags
*/
enum kde_output_device_mode_v2_flags {
KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_CUSTOM = 0x1,
KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_REDUCED_BLANKING = 0x2,
};
#endif /* KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM */
/**
* @ingroup iface_kde_output_device_mode_v2
* @struct kde_output_device_mode_v2_listener
@@ -1017,6 +1059,15 @@ struct kde_output_device_mode_v2_listener {
*/
void (*removed)(void *data,
struct kde_output_device_mode_v2 *kde_output_device_mode_v2);
/**
* mode flags
*
* This event describes the mode's flags.
* @since 19
*/
void (*flags)(void *data,
struct kde_output_device_mode_v2 *kde_output_device_mode_v2,
uint32_t flags);
};
/**
@@ -1046,6 +1097,10 @@ kde_output_device_mode_v2_add_listener(struct kde_output_device_mode_v2 *kde_out
* @ingroup iface_kde_output_device_mode_v2
*/
#define KDE_OUTPUT_DEVICE_MODE_V2_REMOVED_SINCE_VERSION 1
/**
* @ingroup iface_kde_output_device_mode_v2
*/
#define KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_SINCE_VERSION 19
/** @ingroup iface_kde_output_device_mode_v2 */
@@ -67,12 +67,13 @@ static const struct wl_message kde_output_device_v2_events[] = {
{ "automatic_max_bits_per_color_limit", "15u", kde_output_device_v2_types + 0 },
{ "edr_policy", "16u", kde_output_device_v2_types + 0 },
{ "sharpness", "17u", kde_output_device_v2_types + 0 },
{ "priority", "18u", kde_output_device_v2_types + 0 },
};
WL_EXPORT const struct wl_interface kde_output_device_v2_interface = {
"kde_output_device_v2", 17,
"kde_output_device_v2", 19,
0, NULL,
34, kde_output_device_v2_events,
35, kde_output_device_v2_events,
};
static const struct wl_message kde_output_device_mode_v2_events[] = {
@@ -80,12 +81,13 @@ static const struct wl_message kde_output_device_mode_v2_events[] = {
{ "refresh", "i", kde_output_device_v2_types + 0 },
{ "preferred", "", kde_output_device_v2_types + 0 },
{ "removed", "", kde_output_device_v2_types + 0 },
{ "flags", "19u", kde_output_device_v2_types + 0 },
};
WL_EXPORT const struct wl_interface kde_output_device_mode_v2_interface = {
"kde_output_device_mode_v2", 1,
"kde_output_device_mode_v2", 19,
0, NULL,
4, kde_output_device_mode_v2_events,
5, kde_output_device_mode_v2_events,
};
#endif
@@ -178,6 +178,7 @@ static struct kde_output_device_v2_listener outputListener = {
.automatic_max_bits_per_color_limit = (void*) stubListener,
.edr_policy = (void*) stubListener,
.sharpness = (void*) stubListener,
.priority = (void*) stubListener,
};
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
@@ -220,8 +221,8 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
(uint32_t) display.width,
(uint32_t) display.height,
display.refreshRate / 1000.0,
(uint32_t) (display.width / display.scale),
(uint32_t) (display.height / display.scale),
(uint32_t) (display.width / display.scale + .5),
(uint32_t) (display.height / display.scale + .5),
(uint32_t) display.preferredWidth,
(uint32_t) display.preferredHeight,
display.preferredRefreshRate / 1000.0,
+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) (currentMode ? currentMode->width : crtcInfoReply->width),
(uint32_t) (currentMode ? currentMode->height : crtcInfoReply->height),
currentMode ? (double) currentMode->dot_clock / (double) ((uint32_t) currentMode->htotal * currentMode->vtotal) : 0,
(uint32_t) (crtcInfoReply->width / scaleFactor + .5),
(uint32_t) (crtcInfoReply->height / scaleFactor + .5),
preferredMode ? (uint32_t) preferredMode->width : 0,
preferredMode ? (uint32_t) preferredMode->height : 0,
preferredMode ? (double) preferredMode->dot_clock / (double) ((uint32_t) preferredMode->htotal * preferredMode->vtotal) : 0,
rotation,
name,
displayType,
primary,
0,
(uint32_t) outputInfoReply->mm_width,
(uint32_t) outputInfoReply->mm_height,
currentMode ? "xcb-randr-mode" : "xcb-randr-crtc"
);
if (item && edidLength)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
item->bitDepth = bitDepth;
}
return !!item;
}
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor)
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, double scaleFactor)
{
//for some reasons, we have to construct this our self
xcb_randr_output_iterator_t outputIterator = {
@@ -275,18 +266,20 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
while(outputIterator.rem > 0)
{
if(xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary, displayType))
if(xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary, displayType, screenResources, bitDepth, scaleFactor))
foundOutput = true;
data->ffxcb_randr_output_next(&outputIterator);
};
}
return foundOutput ? true : !!ffdsAppendDisplay(
if (foundOutput) return true;
FFDisplayResult* display = ffdsAppendDisplay(
data->result,
(uint32_t) monitor->width,
(uint32_t) monitor->height,
0,
(uint32_t) monitor->width,
(uint32_t) monitor->height,
(uint32_t) (monitor->width / scaleFactor + .5),
(uint32_t) (monitor->height / scaleFactor + .5),
0, 0, 0,
0,
&name,
@@ -297,6 +290,8 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
(uint32_t) monitor->height_in_millimeters,
"xcb-randr-monitor"
);
if (display) display->bitDepth = bitDepth;
return !!display;
}
static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
@@ -306,13 +301,27 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
if(monitorsReply == NULL)
return false;
//Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
xcb_randr_get_screen_resources_current_cookie_t screenResourcesCookie = data->ffxcb_randr_get_screen_resources_current(data->connection, screen->root);
FF_AUTO_FREE struct xcb_randr_get_screen_resources_current_reply_t* screenResources = data->ffxcb_randr_get_screen_resources_current_reply(data->connection, screenResourcesCookie, NULL);
double scaleFactor = 1;
FF_AUTO_FREE const char* resourceManager = xcbGetProperty(&data->propData, data->connection, screen->root, "RESOURCE_MANAGER");
if (resourceManager)
{
FF_STRBUF_AUTO_DESTROY dpi = ffStrbufCreate();
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpi))
scaleFactor = ffStrbufToDouble(&dpi, 96) / 96;
}
uint8_t bitDepth = (uint8_t) (screen->root_depth / 3);
xcb_randr_monitor_info_iterator_t monitorInfoIterator = data->ffxcb_randr_get_monitors_monitors_iterator(monitorsReply);
bool foundMonitor = false;
while(monitorInfoIterator.rem > 0)
{
if(xcbRandrHandleMonitor(data, monitorInfoIterator.data))
if(xcbRandrHandleMonitor(data, monitorInfoIterator.data, screenResources, bitDepth, scaleFactor))
foundMonitor = true;
data->ffxcb_randr_monitor_info_next(&monitorInfoIterator);
}
@@ -322,17 +331,8 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
{
//Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
xcb_randr_get_screen_resources_current_cookie_t screenResourcesCookie = data->ffxcb_randr_get_screen_resources_current(data->connection, screen->root);
data->screenResources = data->ffxcb_randr_get_screen_resources_current_reply(data->connection, screenResourcesCookie, NULL);
//With all the initialisation done, start the detection
bool ret = xcbRandrHandleMonitors(data, screen);
free(data->screenResources);
if(ret)
if(xcbRandrHandleMonitors(data, screen))
return;
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
@@ -348,7 +348,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
NULL,
FF_DISPLAY_TYPE_UNKNOWN,
false,
0,
(uint64_t) screen->root,
(uint32_t) screen->width_in_millimeters,
(uint32_t) screen->height_in_millimeters,
"xcb-randr-screen"
+52 -43
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,
(uint32_t) (currentMode ? currentMode->width : crtcInfo->width),
(uint32_t) (currentMode ? currentMode->height : crtcInfo->height),
currentMode ? (double) currentMode->dotClock / (double) ((uint32_t) currentMode->hTotal * currentMode->vTotal) : 0,
(uint32_t) crtcInfo->width,
(uint32_t) crtcInfo->height,
(uint32_t) (crtcInfo->width / scaleFactor + .5),
(uint32_t) (crtcInfo->height / scaleFactor + .5),
preferredMode ? (uint32_t) preferredMode->width : 0,
preferredMode ? (uint32_t) preferredMode->height : 0,
preferredMode ? (double) preferredMode->dotClock / (double) ((uint32_t) preferredMode->hTotal * preferredMode->vTotal) : 0,
@@ -156,22 +149,26 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
0,
(uint32_t) output->mm_width,
(uint32_t) output->mm_height,
"xlib-randr-crtc"
currentMode ? "xlib-randr-mode" : "xlib-randr-crtc"
);
if (item && edidLength)
if (item)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
if (edidLength)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
}
item->bitDepth = bitDepth;
}
data->ffXRRFreeCrtcInfo(crtcInfo);
return !!item;
}
static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType)
static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor)
{
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output);
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, screenResources, output);
if(outputInfo == NULL)
return false;
@@ -195,7 +192,7 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
}
}
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength);
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength, screenResources, bitDepth, scaleFactor);
if (edidData)
data->ffXFree(edidData);
@@ -204,7 +201,7 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
return res;
}
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor)
{
bool foundOutput = false;
char* xname = data->ffXGetAtomName(data->display, monitorInfo->name);
@@ -213,17 +210,19 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
FFDisplayType displayType = ffdsGetDisplayType(name.chars);
for(int i = 0; i < monitorInfo->noutput; i++)
{
if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary, displayType))
if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary, displayType, screenResources, bitDepth, scaleFactor))
foundOutput = true;
}
return foundOutput ? true : !!ffdsAppendDisplay(
if (foundOutput) return true;
FFDisplayResult* display = ffdsAppendDisplay(
data->result,
(uint32_t) monitorInfo->width,
(uint32_t) monitorInfo->height,
0,
(uint32_t) monitorInfo->width,
(uint32_t) monitorInfo->height,
(uint32_t) (monitorInfo->width / scaleFactor + .5),
(uint32_t) (monitorInfo->height / scaleFactor + .5),
0, 0, 0,
0,
&name,
@@ -234,6 +233,8 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
(uint32_t) monitorInfo->mheight,
"xlib-randr-monitor"
);
if (display) display->bitDepth = bitDepth;
return !!display;
}
static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
@@ -243,29 +244,36 @@ static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
if(monitorInfos == NULL)
return false;
XRRScreenResources* screenResources = data->ffXRRGetScreenResourcesCurrent(data->display, RootWindowOfScreen(screen));
double scaleFactor = 1;
char* resourceManager = (char*) x11GetProperty(data->propData, data->display, screen->root, "RESOURCE_MANAGER");
if (resourceManager)
{
FF_STRBUF_AUTO_DESTROY dpi = ffStrbufCreate();
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpi))
scaleFactor = ffStrbufToDouble(&dpi, 96) / 96;
data->ffXFree(resourceManager);
}
uint8_t bitDepth = (uint8_t) (screen->root_depth / 3);
bool foundAMonitor = false;
for(int i = 0; i < numberOfMonitors; i++)
{
if(xrandrHandleMonitor(data, &monitorInfos[i]))
if(xrandrHandleMonitor(data, &monitorInfos[i], screenResources, bitDepth, scaleFactor))
foundAMonitor = true;
}
data->ffXRRFreeMonitors(monitorInfos);
data->ffXRRFreeScreenResources(screenResources);
return foundAMonitor;
}
static void xrandrHandleScreen(XrandrData* data, Screen* screen)
{
//Init screen resources
data->screenResources = data->ffXRRGetScreenResourcesCurrent(data->display, RootWindowOfScreen(screen));
bool ret = xrandrHandleMonitors(data, screen);
data->ffXRRFreeScreenResources(data->screenResources);
if(ret)
if(xrandrHandleMonitors(data, screen))
return;
//Fallback to screen
@@ -281,7 +289,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
NULL,
FF_DISPLAY_TYPE_UNKNOWN,
false,
0,
RootWindowOfScreen(screen),
(uint32_t) WidthMMOfScreen(screen),
(uint32_t) HeightMMOfScreen(screen),
"xlib-randr-screen"
@@ -312,6 +320,7 @@ const char* ffdsConnectXrandr(FFDisplayServerResult* result)
X11PropertyData propertyData;
bool propertyDataInitialized = x11InitPropertyData(xrandr, &propertyData);
data.propData = &propertyData;
data.display = ffXOpenDisplay(NULL);
if(data.display == NULL)
+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;
+19 -1
View File
@@ -15,11 +15,18 @@ extern const char* FF_GPU_VENDOR_NAME_AMD;
extern const char* FF_GPU_VENDOR_NAME_INTEL;
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
extern const char* FF_GPU_VENDOR_NAME_MTHREADS;
extern const char* FF_GPU_VENDOR_NAME_QUALCOMM;
extern const char* FF_GPU_VENDOR_NAME_MTK;
extern const char* FF_GPU_VENDOR_NAME_VMWARE;
extern const char* FF_GPU_VENDOR_NAME_PARALLEL;
extern const char* FF_GPU_VENDOR_NAME_MICROSOFT;
extern const char* FF_GPU_VENDOR_NAME_REDHAT;
extern const char* FF_GPU_VENDOR_NAME_ORACLE;
extern const char* FF_GPU_VENDOR_NAME_BROADCOM;
extern const char* FF_GPU_VENDOR_NAME_LOONGSON;
extern const char* FF_GPU_VENDOR_NAME_JINGJIA_MICRO;
extern const char* FF_GPU_VENDOR_NAME_HUAWEI;
extern const char* FF_GPU_VENDOR_NAME_ZHAOXIN;
typedef struct FFGPUMemory
{
@@ -58,7 +65,7 @@ typedef struct FFGpuDriverPciBusId
uint32_t func;
} FFGpuDriverPciBusId;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) || defined(__GNU__)
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
@@ -73,3 +80,14 @@ const char* ffDrmDetectNouveau(FFGPUResult* gpu, int fd);
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
#endif // defined(XXX)
static inline uint64_t ffGPUPciAddr2Id(uint64_t domain, uint64_t bus, uint64_t device, uint64_t function)
{
return (domain << 16) | (bus << 8) | (device << 3) | function;
}
static inline uint64_t ffGPUGeneral2Id(uint64_t originalId)
{
// Note: originalId may already have the MSB set
return (1ULL << 63) | originalId;
}
+1 -1
View File
@@ -57,7 +57,7 @@ static const char* detectFrequency(FFGPUResult* gpu)
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID())
return "\"voltage-states9-sram\" in \"pmgr\" is not found";
// voltage-states5-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
// voltage-states9-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
CFIndex propLength = CFDataGetLength(freqProperty);
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0)
return "Invalid \"voltage-states9-sram\" length";
+6 -3
View File
@@ -30,7 +30,7 @@ static void fillGPUTypeGeneric(FFGPUResult* gpu)
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
// 0000:00:02.0 is reserved for Intel integrated graphics
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
}
}
}
@@ -80,7 +80,7 @@ static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
{
case DRM_BUS_PCI:
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
gpu->deviceId = (dev->businfo.pci->domain * 100000ull) + (dev->businfo.pci->bus * 1000ull) + (dev->businfo.pci->dev * 10ull) + dev->businfo.pci->func;
gpu->deviceId = ffGPUPciAddr2Id(dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func);
break;
case DRM_BUS_HOST1X:
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
@@ -179,6 +179,9 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
{
struct pci_conf* pc = &confs[i];
if (pc->pc_sel.pc_func > 0 && pc->pc_subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
continue; // Likely an auxiliary display controller (#2034)
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pc->pc_vendor));
ffStrbufInit(&gpu->name);
@@ -191,7 +194,7 @@ static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = (pc->pc_sel.pc_domain * 100000ull) + (pc->pc_sel.pc_bus * 1000ull) + (pc->pc_sel.pc_dev * 10ull) + pc->pc_sel.pc_func;
gpu->deviceId = ffGPUPciAddr2Id(pc->pc_sel.pc_domain, pc->pc_sel.pc_bus, pc->pc_sel.pc_dev, pc->pc_sel.pc_func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
+2 -2
View File
@@ -153,7 +153,7 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
return NULL;
#else
FF_UNUSED(gpu, renderPath);
FF_UNUSED(options, gpu, renderPath);
return "Fastfetch is compiled without libdrm support";
#endif
}
@@ -313,7 +313,7 @@ const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = paramsGlobal.chip_id;
gpu->deviceId = ffGPUGeneral2Id(paramsGlobal.chip_id);
if (!gpu->name.length)
{
+9 -2
View File
@@ -14,6 +14,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_slot_match_iterator_create)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_device_next)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_system_cleanup)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(pciaccess, pci_iterator_destroy)
{
// Requires root access
@@ -29,6 +30,11 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
if (dev->device_class >> 16 != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
continue;
uint8_t subclass = (dev->device_class >> 8) & 0xFF;
if (dev->func > 0 && subclass == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
continue; // Likely an auxiliary display controller (#2034)
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->vendor_id));
ffStrbufInit(&gpu->name);
@@ -40,15 +46,16 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ((uint64_t) dev->domain << 6) | ((uint64_t) dev->bus << 4) | ((uint64_t) dev->dev << 2) | (uint64_t) dev->func;
gpu->deviceId = ffGPUPciAddr2Id(dev->domain, dev->bus, dev->dev, dev->func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
ffGPUQueryAmdGpuName(dev->device_id, dev->revision, gpu);
if (gpu->name.length == 0)
ffGPUFillVendorAndName((dev->device_class >> 8) & 0xFF, dev->vendor_id, dev->device_id, gpu);
ffGPUFillVendorAndName(subclass, dev->vendor_id, dev->device_id, gpu);
}
ffpci_iterator_destroy(iter);
ffpci_system_cleanup();
return NULL;
+4 -1
View File
@@ -19,6 +19,9 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
if (dev.class_base != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
continue;
if (dev.function > 0 && dev.class_sub == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
continue; // Likely an auxiliary display controller (#2034)
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev.vendor_id));
ffStrbufInit(&gpu->name);
@@ -30,7 +33,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ((uint64_t) dev.bus << 4) | ((uint64_t) dev.device << 2) | (uint64_t) dev.function;
gpu->deviceId = ffGPUPciAddr2Id(0, dev.bus, dev.device, dev.function);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
+59 -6
View File
@@ -4,10 +4,13 @@
#include "detection/gpu/gpu_driver_specific.h"
#include "common/io/io.h"
#include "common/library.h"
#include "modules/gpu/option.h"
#include "util/FFstrbuf.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <inttypes.h>
#include <stdint.h>
#ifdef FF_HAVE_DRM_AMDGPU
#include <amdgpu.h>
@@ -120,7 +123,7 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult
#endif
}
#else
FF_UNUSED(gpu, drmKey, buffer);
FF_UNUSED(options, gpu, drmKey, buffer);
return "Fastfetch is not compiled with drm support";
#endif
}
@@ -198,7 +201,7 @@ static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
// 0000:00:02.0 is reserved for Intel integrated graphics
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
if (!drmKey) return;
@@ -263,7 +266,7 @@ static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey,
#endif
}
static const char* pciDetectNouveauSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
if (options->temp)
{
@@ -306,6 +309,48 @@ static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey
#endif
}
static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
{
gpu->type = FF_GPU_TYPE_INTEGRATED;
const uint32_t pciDirLen = pciDir->length;
ffStrbufAppendS(pciDir, "/zx_info/eclk");
if (ffReadFileBuffer(pciDir->chars, buffer))
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, FF_GPU_FREQUENCY_UNSET);
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (options->driverSpecific)
{
ffStrbufAppendS(pciDir, "/zx_info/engine_3d_usage");
if (ffReadFileBuffer(pciDir->chars, buffer))
gpu->coreUsage = ffStrbufToDouble(buffer, FF_GPU_CORE_USAGE_UNSET);
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/zx_info/fb_size");
if (ffReadFileBuffer(pciDir->chars, buffer))
gpu->shared.total = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET)
{
gpu->shared.total *= 1024 * 1024;
ffStrbufAppendS(pciDir, "/zx_info/free_fb_mem");
if (ffReadFileBuffer(pciDir->chars, buffer))
gpu->shared.used = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET)
{
gpu->shared.used *= 1024 * 1024;
gpu->shared.used = gpu->shared.total - gpu->shared.used;
}
}
}
return NULL;
}
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
{
const uint32_t drmDirPathLength = deviceDir->length;
@@ -342,6 +387,9 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
return "Invalid PCI device path";
if (pciFunc > 0 && subclassId == 0x80 /*PCI_CLASS_DISPLAY_OTHER*/)
return "Likely an auxiliary display controller"; // #2034
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name);
@@ -354,7 +402,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = (pciDomain * 100000ull) + (pciBus * 1000ull) + (pciDevice * 10ull) + pciFunc;
gpu->deviceId = ffGPUPciAddr2Id(pciDomain, pciBus, pciDevice, pciFunc);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
char drmKeyBuffer[8];
@@ -414,10 +462,15 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && ffStrbufEqualS(&gpu->driver, "nouveau"))
{
pciDetectNouveauSpecific(options, gpu, deviceDir, buffer);
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
if (options->driverSpecific && drmKey)
drmDetectNouveauSpecific(gpu, drmKey, buffer);
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_ZHAOXIN && ffStrbufStartsWithS(&gpu->driver, "zx"))
{
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
pciDetectZxSpecific(options, gpu, deviceDir, buffer);
}
else
{
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
@@ -552,7 +605,7 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
if (ffStrbufStartsWithS(&buffer, "pci:"))
detectPci(options, gpus, &buffer, &drmDir, entry->d_name);
else if (ffStrbufStartsWithS(&buffer, "of:"))
else if (ffStrbufStartsWithS(&buffer, "of:")) // Open Firmware
detectOf(gpus, &buffer, &drmDir, entry->d_name);
ffStrbufSubstrBefore(&drmDir, drmDirLength);
+113
View File
@@ -0,0 +1,113 @@
#include "gpu.h"
#include "common/io/io.h"
#include <sys/param.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>
#include <dev/pci/pciio.h>
static inline int pciReadConf(int fd, uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint32_t* result)
{
struct pciio_bdf_cfgreg bdfr = {
.bus = bus,
.device = device,
.function = func,
.cfgreg = {
.reg = reg,
},
};
if (ioctl(fd, PCI_IOC_BDF_CFGREAD, &bdfr) == -1)
return -1;
*result = bdfr.cfgreg.val;
return 0;
}
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
char pciDevPath[] = "/dev/pciXXX";
for (uint32_t idev = 0; idev <= 255; idev++)
{
snprintf(pciDevPath + strlen("/dev/pci"), 4, "%u", idev);
FF_AUTO_CLOSE_FD int pcifd = open(pciDevPath, O_RDONLY | O_CLOEXEC);
if (pcifd < 0)
{
if (errno == ENOENT)
break; // No more /dev/pciN devices
return "open(\"/dev/pciN\", O_RDONLY | O_CLOEXEC) failed";
}
struct pciio_businfo businfo;
if (ioctl(pcifd, PCI_IOC_BUSINFO, &businfo) != 0)
continue;
uint32_t bus = businfo.busno;
for (uint32_t dev = 0; dev < businfo.maxdevs; dev++)
{
uint32_t maxfuncs = 0;
for (uint32_t func = 0; func <= maxfuncs; func++)
{
uint32_t pciid, pciclass;
if (pciReadConf(pcifd, bus, dev, func, PCI_ID_REG, &pciid) != 0)
continue;
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0)
continue;
if (pciReadConf(pcifd, bus, dev, func, PCI_CLASS_REG, &pciclass) != 0)
continue;
if (func == 0)
{
// For some reason, pciReadConf returns success even for non-existing devices.
// So we need to check for `PCI_VENDOR(pciid) == PCI_VENDOR_INVALID` above to filter them out.
uint32_t bhlcr;
if (pciReadConf(pcifd, bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0)
continue;
if (PCI_HDRTYPE_MULTIFN(bhlcr)) maxfuncs = 7;
}
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY)
continue;
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC)
continue; // Likely an auxiliary display controller (#2034)
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(PCI_VENDOR(pciid)));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInitS(&gpu->platformApi, pciDevPath);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
if (gpu->name.length == 0)
ffGPUFillVendorAndName(PCI_SUBCLASS(pciclass), PCI_VENDOR(pciid), PCI_PRODUCT(pciid), gpu);
struct pciio_drvname drvname = {
.device = dev,
.function = func,
};
if (ioctl(pcifd, PCI_IOC_DRVNAME, &drvname) == 0)
ffStrbufInitS(&gpu->driver, drvname.name);
}
}
}
return NULL;
}
+95
View File
@@ -0,0 +1,95 @@
#include "gpu.h"
#include "common/io/io.h"
#include <sys/param.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>
#include <sys/pciio.h>
static inline int pciReadConf(int fd, uint32_t bus, uint32_t device, uint32_t func, uint32_t reg, uint32_t* result)
{
struct pci_io bdfr = {
.pi_sel = {
.pc_bus = bus,
.pc_dev = device,
.pc_func = func,
},
.pi_reg = reg,
.pi_width = 4,
};
if (ioctl(fd, PCIOCREAD, &bdfr) == -1)
return -1;
*result = bdfr.pi_data;
return 0;
}
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
char pciDevPath[] = "/dev/pci0";
FF_AUTO_CLOSE_FD int pcifd = open(pciDevPath, O_RDONLY | O_CLOEXEC);
if (pcifd < 0)
return "open(\"/dev/pci0\", O_RDONLY | O_CLOEXEC) failed";
for (uint32_t bus = 0; bus <= 255; bus++)
{
for (uint32_t dev = 0; dev < 32; dev++)
{
uint32_t maxfuncs = 0;
for (uint32_t func = 0; func <= maxfuncs; func++)
{
uint32_t pciid, pciclass;
if (pciReadConf(pcifd, bus, dev, func, PCI_ID_REG, &pciid) != 0)
continue;
if (PCI_VENDOR(pciid) == PCI_VENDOR_INVALID || PCI_VENDOR(pciid) == 0)
continue;
if (pciReadConf(pcifd, bus, dev, func, PCI_CLASS_REG, &pciclass) != 0)
continue;
if (func == 0)
{
// For some reason, pciReadConf returns success even for non-existing devices.
// So we need to check for `PCI_VENDOR(pciid) == PCI_VENDOR_INVALID` above to filter them out.
uint32_t bhlcr;
if (pciReadConf(pcifd, bus, dev, 0, PCI_BHLC_REG, &bhlcr) != 0)
continue;
if (PCI_HDRTYPE_MULTIFN(bhlcr)) maxfuncs = 7;
}
if (PCI_CLASS(pciclass) != PCI_CLASS_DISPLAY)
continue;
if (func > 0 && PCI_SUBCLASS(pciclass) == PCI_SUBCLASS_DISPLAY_MISC)
continue; // Likely an auxiliary display controller (#2034)
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(PCI_VENDOR(pciid)));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInitS(&gpu->platformApi, "/dev/pci0");
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ffGPUPciAddr2Id(0, bus, dev, func);
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
ffGPUQueryAmdGpuName(PCI_PRODUCT(pciid), PCI_REVISION(pciid), gpu);
if (gpu->name.length == 0)
ffGPUFillVendorAndName(PCI_SUBCLASS(pciclass), PCI_VENDOR(pciid), PCI_PRODUCT(pciid), gpu);
}
}
}
return NULL;
}
+3 -3
View File
@@ -95,7 +95,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
{
pciDev = (pciAddr >> 16) & 0xFFFF;
pciFunc = pciAddr & 0xFFFF;
gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc;
gpu->deviceId = ffGPUPciAddr2Id(0, pciBus, pciDev, pciFunc);
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
FF_DEBUG("PCI location - Bus: %u, Device: %u, Function: %u, DeviceID: %llu", pciBus, pciDev, pciFunc, gpu->deviceId);
}
@@ -182,7 +182,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
if (ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL))
{
FF_DEBUG("Found adapter LUID: %llu", adapterLuid);
if (!gpu->deviceId) gpu->deviceId = adapterLuid;
if (!gpu->deviceId) gpu->deviceId = ffGPUGeneral2Id(adapterLuid);
}
uint32_t featureLevel = 0;
@@ -449,7 +449,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
FF_DEBUG("Using fallback GPU type detection");
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
gpu->type = gpu->deviceId == ffGPUPciAddr2Id(0, 0, 2, 0) ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
FF_DEBUG("Intel GPU type determined: %s", gpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete");
}
else if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
+7
View File
@@ -79,6 +79,13 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
gpu->deviceId = 0;
ffStrbufInitStatic(&gpu->platformApi, "DXCore");
LUID luid;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, sizeof(luid), &luid)))
{
static_assert(sizeof(luid) == sizeof(uint64_t), "LUID size mismatch");
gpu->deviceId = ffGPUGeneral2Id(*(uint64_t*)&luid);
}
ffStrbufInit(&gpu->driver);
uint64_t value = 0;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DriverVersion, sizeof(value), &value)))
+33 -28
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);
+2 -1
View File
@@ -45,7 +45,8 @@ const char* getOthersByIokit(FFHostResult* host)
const char* ffDetectHost(FFHostResult* host)
{
const char* error = ffSysctlGetString("hw.model", &host->family);
const char* error = ffSysctlGetString("hw.product", &host->family);
if (error) error = ffSysctlGetString("hw.model", &host->family);
if (error) return error;
ffStrbufSetStatic(&host->name, ffHostGetMacProductNameWithHwModel(&host->family));
+1 -1
View File
@@ -181,7 +181,7 @@ const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
#ifdef __x86_64__
bool ffHostDetectMac(FFHostResult* host)
{
if (ffStrbufEqualS(&host->family, "Mac") && ffStrbufEqualS(&host->vendor, "Apple Inc."))
if (ffStrbufStartsWithS(&host->family, "Mac") && ffStrbufEqualS(&host->vendor, "Apple Inc."))
{
const char* productName = ffHostGetMacProductNameWithHwModel(&host->name);
if (productName)
+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;

Some files were not shown because too many files have changed in this diff Show More