Compare commits

..

491 Commits

Author SHA1 Message Date
Carter Li be60eaf7c8 Merge pull request #468 from LinusDierheimer/dev
Release 1.11.3
2023-06-09 22:34:25 +08:00
李通洲 2235c3e8e4 Release 1.11.3 2023-06-09 22:32:02 +08:00
李通洲 68ae9248a6 Settings: try fixing #467 2023-06-09 22:14:29 +08:00
李通洲 b9742642fc Release 1.11.2 before merging #432 2023-06-09 11:31:36 +08:00
李通洲 356c905703 DisplayServer (macOS): add a missing variable initialization 2023-06-09 11:07:06 +08:00
李通洲 47a5473a35 Init: fix possible memleaks 2023-06-09 10:10:03 +08:00
李通洲 96bca6888a LocalIP: remove useless code 2023-06-09 09:47:45 +08:00
李通洲 bbf31c1a95 Doc: update changelog 2023-06-08 22:28:32 +08:00
李通洲 42b8c1b429 Wallpaper: add missing docs 2023-06-08 22:27:15 +08:00
李通洲 77fde11039 Disk (Linux): fix fastfetch doesn't show Windows drives (/mnt/c) 2023-06-08 22:24:57 +08:00
李通洲 e13f04e80f Disk: backport changes from config branch 2023-06-08 22:24:57 +08:00
李通洲 ad026f6105 LocalIP: backport mac address support
Also change `--*-ip-*` to `--*ip-*` to be consistant to my config branch
2023-06-08 22:22:05 +08:00
李通洲 9107d0e107 Player: try avoiding too Linux-specific names 2023-06-08 16:08:56 +08:00
李通洲 ee876c54bf Theme: split detection code 2023-06-08 16:08:56 +08:00
李通洲 4af44a40bf OS (macOS): add fast path for code name detection 2023-06-07 14:30:45 +08:00
李通洲 399cfe2fbc CI (Wallpaper): run this module 2023-06-06 21:17:03 +08:00
李通洲 71d0cdbfce Wallpaper (Linux): add support for xfce4 2023-06-06 21:02:21 +08:00
李通洲 aae740472f Wallpaper (Linux): add support for gnome 2023-06-06 21:02:21 +08:00
李通洲 8f9beb2789 Wallpaper (macOS): add support 2023-06-06 21:02:21 +08:00
李通洲 77b93a904f Wallpaper (Windows): add new module 2023-06-06 15:48:24 +08:00
李通洲 7934c16bca Doc: update changelog for Icons module 2023-06-06 15:46:57 +08:00
李通洲 941ddee2fc Icons (Windows): add support
Instead of icon theme, this module on Windows detects enabled system icons
2023-06-06 15:35:41 +08:00
李通洲 16113bf330 Icons: split detection code 2023-06-06 15:35:41 +08:00
李通洲 505182428b Global: silence some clang warnings 2023-06-04 01:30:48 +08:00
李通洲 3c2a84ff78 TerminalFont: detect /dev/pts/* 2023-06-01 11:00:40 +08:00
李通洲 8a3346b650 DisplayServer (Wayland): remove a useless line 2023-05-30 22:38:35 +08:00
李通洲 5b63fb1362 Doc: update changelog 2023-05-30 21:04:11 +08:00
李通洲 393857b067 Brightness (Linux): print more useful display name instead of intel_backlight 2023-05-30 20:57:05 +08:00
李通洲 cb8a9c0796 DisplayServer (Wayland): detect display type 2023-05-30 20:54:08 +08:00
李通洲 036752763f DisplayServer (Wayland): silence compiler warnings 2023-05-30 20:53:35 +08:00
李通洲 3a90af1f44 DisplayServer (Wayland): detect screen rotation 2023-05-30 20:16:18 +08:00
李通洲 772de0ff97 DisplayServer: better wayland feature detection 2023-05-29 13:35:45 +08:00
李通洲 53a61a8e58 Display (Linux): support name detection for wayland protocol 2023-05-29 13:30:50 +08:00
Linus Dierheimer a37328c1aa Font: Show QT before GTK
keeps consistency with other modules
2023-05-28 12:34:23 +02:00
李通洲 782325395c DE: Fix Gnome version detection on Fedora 2023-05-28 01:10:00 +08:00
李通洲 e13d554433 Merge remote-tracking branch 'upstream/master' into dev 2023-05-28 00:20:31 +08:00
李通洲 15c72c04af Release: 1.11.1
Update changelog too
2023-05-28 00:17:57 +08:00
李通洲 b797246607 DisplayServer (Apple): use FF_AUTO_FREE 2023-05-28 00:17:57 +08:00
李通洲 d54bb4fd16 Windows: use ffStrbufInitWS 2023-05-28 00:17:57 +08:00
李通洲 0a946e3976 Disk (Windows): improve performance 2023-05-28 00:17:57 +08:00
李通洲 a339f00d83 Windows: fix potential memory curruption bug in unicode.c
Also add ffStrbufInitWS
2023-05-28 00:17:57 +08:00
李通洲 de15866c9a TerminalShell (Windows): print clink version 2023-05-28 00:17:57 +08:00
李通洲 24ee87720e TerminalShell: code refactoring 2023-05-28 00:17:57 +08:00
李通洲 7310b3ed09 TerminalShel (Windows): detect Tabby version with exe file version 2023-05-28 00:17:57 +08:00
李通洲 bb6cdc7bb0 Settings (Linux): fix memleaks reported by LeakSanitizer 2023-05-28 00:17:57 +08:00
李通洲 4a2d20fb74 TerminalFont: support Tabby 2023-05-28 00:17:57 +08:00
李通洲 b136b86300 TerminalShell: support Tabby terminal version detection 2023-05-28 00:17:57 +08:00
李通洲 d4a7ae8b34 Sound (macOS): detecting volume more aggressively 2023-05-28 00:17:57 +08:00
李通洲 04da7cebdb Logo: add macOS small version 2023-05-28 00:17:57 +08:00
李通洲 ccb227e694 TerminalShell: fix iTerm being detected as iTermServer-* sometimes 2023-05-28 00:17:57 +08:00
李通洲 9c7b868227 TerminalShell: support xonsh 2023-05-28 00:17:57 +08:00
李通洲 f333937b35 Swap (Windows): fix compiler warnings 2023-05-28 00:17:57 +08:00
李通洲 e4f6f15d70 Vulkan: try fixing #456 2023-05-28 00:17:57 +08:00
李通洲 5ae8ef1cb3 Swap: split module code from memory.c 2023-05-28 00:17:57 +08:00
李通洲 d863652e1b CMake(Windows): remove USE_WIN_NTAPI option 2023-05-28 00:17:57 +08:00
李通洲 ac540d73b7 Network: drop module 2023-05-28 00:17:57 +08:00
Edward Piper 37b9da7337 Fix EndeavourOS logo again 2023-05-28 00:17:57 +08:00
李通洲 93c0dbde0d DisplayServer (Windows): code simplification 2023-05-28 00:17:57 +08:00
李通洲 aa236b4da0 OpenCL: split detection code 2023-05-28 00:17:57 +08:00
李通洲 2fd3643632 Doc: document Network module 2023-05-28 00:17:57 +08:00
李通洲 24f9247c54 LocalIP: simplify loop interface detection 2023-05-28 00:17:57 +08:00
李通洲 d312b752a1 Network (FreeBSD): add dirty support 2023-05-28 00:17:57 +08:00
李通洲 1b476757a0 Network: code refactor & bug fixes 2023-05-28 00:17:57 +08:00
李通洲 c78a8f6317 Network (Linux): add support 2023-05-28 00:17:57 +08:00
李通洲 24c3788055 Network (Windows): add support 2023-05-28 00:17:57 +08:00
李通洲 a644762a60 Network (macOS): init 2023-05-28 00:17:57 +08:00
Linus Dierheimer 3185d92fb5 --pipe: don't print white color blocks
Fixes #450
2023-05-28 00:17:57 +08:00
李通洲 2c629bc821 FFstrbuf: remove FF_STRBUF_CREATE macro 2023-05-28 00:17:57 +08:00
李通洲 1a6c38bc26 CpuUsage: code refactor 2023-05-28 00:17:57 +08:00
李通洲 589f9aa8f3 Processes: code refactor 2023-05-28 00:17:57 +08:00
tdtooke 70e5d0b235 Update builtin.c 2023-05-28 00:17:57 +08:00
tdtooke aa81d80578 Update builtin.c 2023-05-28 00:17:57 +08:00
KingKrouch 7bc6676680 Update Windows 11 ASCII
Reason being that the original ASCII art as shown in Windows Terminal has random portions using "*" and "(" as opposed to "/".
2023-05-28 00:17:57 +08:00
Linus Dierheimer ab9b10824f Fix flatpak package count
Fix user package count
Show runtime packages too
Fixes #441
2023-05-28 00:17:57 +08:00
Linus Dierheimer f5931e80e7 Fix a new compile warning 2023-05-28 00:17:57 +08:00
Linus Dierheimer bf4f86b4f6 Remove leftover comment 2023-05-28 00:17:57 +08:00
李通洲 7f59f22cf4 Font: code refactor 2023-05-28 00:17:57 +08:00
李通洲 14f4817381 Doc: update changelog 2023-05-28 00:17:57 +08:00
李通洲 e821468bb0 Gamepad: fix copy-and-paste errors 2023-05-28 00:17:57 +08:00
李通洲 d9315d2332 Doc: update changelog 2023-05-28 00:17:57 +08:00
李通洲 a2b4be388e Logo: add SteamOS (#439) 2023-05-28 00:17:57 +08:00
李通洲 35e06642f9 Gamepad (Windows): change the name of Pro Controller 2023-05-28 00:17:57 +08:00
李通洲 92de3e4f30 Windows: fix compiling with imagemagick enabled 2023-05-28 00:17:57 +08:00
李通洲 5b65e182e9 Release: 1.11.1
Update changelog too
2023-05-27 23:53:41 +08:00
李通洲 a7896c39f0 DisplayServer (Apple): use FF_AUTO_FREE 2023-05-27 23:34:04 +08:00
李通洲 4f19bf9a18 Windows: use ffStrbufInitWS 2023-05-27 23:34:03 +08:00
李通洲 c379c65960 Disk (Windows): improve performance 2023-05-27 23:34:03 +08:00
李通洲 1ae0a83880 Windows: fix potential memory curruption bug in unicode.c
Also add ffStrbufInitWS
2023-05-27 23:34:03 +08:00
李通洲 77f7c813f4 TerminalShell (Windows): print clink version 2023-05-27 21:47:36 +08:00
李通洲 bfec8b5634 TerminalShell: code refactoring 2023-05-27 21:47:18 +08:00
李通洲 15a43a6b11 TerminalShel (Windows): detect Tabby version with exe file version 2023-05-27 21:26:00 +08:00
李通洲 c9e3c34ce1 Settings (Linux): fix memleaks reported by LeakSanitizer 2023-05-27 18:25:54 +08:00
李通洲 b99b3ad982 TerminalFont: support Tabby 2023-05-26 15:47:19 +08:00
李通洲 f4ce5c4143 TerminalShell: support Tabby terminal version detection 2023-05-26 15:44:54 +08:00
李通洲 bb4bf63621 Sound (macOS): detecting volume more aggressively 2023-05-26 15:18:59 +08:00
李通洲 60c1a552bb Logo: add macOS small version 2023-05-26 09:16:29 +08:00
李通洲 0a979ddd1e TerminalShell: fix iTerm being detected as iTermServer-* sometimes 2023-05-24 14:50:39 +08:00
李通洲 e45c4b49fd TerminalShell: support xonsh 2023-05-24 14:50:37 +08:00
李通洲 b89ace7aae Swap (Windows): fix compiler warnings 2023-05-16 20:54:45 +08:00
李通洲 424ca923fc Vulkan: try fixing #456 2023-05-16 20:53:45 +08:00
李通洲 e837e1e1d1 Swap: split module code from memory.c 2023-05-11 22:03:18 +08:00
李通洲 aea0986928 CMake(Windows): remove USE_WIN_NTAPI option 2023-05-11 19:55:31 +08:00
李通洲 dc2a3492f0 Network: drop module 2023-05-03 21:50:05 +08:00
Edward Piper 8cf033002c Fix EndeavourOS logo again 2023-05-03 21:49:50 +08:00
李通洲 4d7cb25aa6 DisplayServer (Windows): code simplification 2023-04-26 00:14:39 +08:00
李通洲 60cf3ec861 OpenCL: split detection code 2023-04-25 19:08:27 +08:00
李通洲 4fd82b16e8 Doc: document Network module 2023-04-18 20:59:26 +08:00
李通洲 26feccc0e4 LocalIP: simplify loop interface detection 2023-04-18 20:38:02 +08:00
李通洲 9a1bc66dfc Network (FreeBSD): add dirty support 2023-04-18 20:37:22 +08:00
李通洲 24a3783d7c Network: code refactor & bug fixes 2023-04-18 20:36:41 +08:00
李通洲 7e072c395f Network (Linux): add support 2023-04-18 18:27:25 +08:00
李通洲 94e1ed1d7e Network (Windows): add support 2023-04-18 18:02:31 +08:00
李通洲 94e6f4040d Network (macOS): init 2023-04-18 17:29:48 +08:00
Linus Dierheimer d570e59818 --pipe: don't print white color blocks
Fixes #450
2023-04-17 17:04:28 +02:00
李通洲 0e9d48fff0 FFstrbuf: remove FF_STRBUF_CREATE macro 2023-04-15 12:27:51 +08:00
李通洲 e690d73434 CpuUsage: code refactor 2023-04-15 12:27:51 +08:00
李通洲 8f2b3c6b69 Processes: code refactor 2023-04-15 12:27:51 +08:00
Linus Dierheimer 3c0b2fc910 Merge pull request #448 from LinusDierheimer/master
Merge pull request #437 from LinusDierheimer/dev
2023-04-13 09:17:37 +02:00
Linus Dierheimer 7d0a1c8987 Merge pull request #446 from tdtooke/dev
Adds another font color index to arch icon
2023-04-12 08:09:54 +02:00
tdtooke 757d947446 Update builtin.c 2023-04-11 13:44:07 -07:00
tdtooke 4ced4f9631 Update builtin.c 2023-04-11 13:35:24 -07:00
Linus Dierheimer c6859d7edd Merge pull request #445 from KingKrouch/winlogo-patch
Update Windows 11 ASCII logo to look more visually consistent.
2023-04-10 18:04:17 +02:00
KingKrouch 94cf9a89cc Update Windows 11 ASCII
Reason being that the original ASCII art as shown in Windows Terminal has random portions using "*" and "(" as opposed to "/".
2023-04-10 15:28:42 +00:00
Linus Dierheimer bd8d78427b Fix flatpak package count
Fix user package count
Show runtime packages too
Fixes #441
2023-04-06 11:11:31 +02:00
Linus Dierheimer e40d4b9b68 Fix a new compile warning 2023-04-05 13:41:10 +02:00
Linus Dierheimer 4a07485a19 Remove leftover comment 2023-04-05 13:21:46 +02:00
李通洲 71614e0b0c Font: code refactor 2023-04-04 12:06:21 +08:00
李通洲 d5b6c14bdf Doc: update changelog 2023-04-04 11:05:27 +08:00
李通洲 9509718b0e Gamepad: fix copy-and-paste errors 2023-04-04 11:02:59 +08:00
李通洲 c0ca022ac2 Doc: update changelog 2023-04-02 20:56:12 +08:00
李通洲 708b4a8981 Logo: add SteamOS (#439) 2023-04-02 20:54:16 +08:00
李通洲 8006b0ca4f Gamepad (Windows): change the name of Pro Controller 2023-04-02 20:41:18 +08:00
李通洲 cc2286f056 Windows: fix compiling with imagemagick enabled 2023-04-02 20:41:16 +08:00
Carter Li 81a4be498b Merge pull request #437 from LinusDierheimer/dev
Release 1.11.0
2023-03-25 14:42:07 +08:00
李通洲 56477f5ea6 GPU: be more careful to concat strings 2023-03-25 14:19:58 +08:00
李通洲 ca05e2e905 GPU: add option --gpu-force-vulkan 2023-03-25 13:24:28 +08:00
李通洲 a524302ea7 GPU (Windows): use a faster implementation 2023-03-25 13:04:44 +08:00
李通洲 945b5f1b15 Parsing: make it able to print 1.00 GB 2023-03-25 12:53:08 +08:00
李通洲 ccb0f853db Deps: revert changes of JSON parse library
Let's not make the change before fastfetch 2.0
2023-03-25 10:00:35 +08:00
李通洲 b8f1b0d6aa Release 1.11.0 2023-03-25 01:08:32 +08:00
李通洲 aa7d5bd704 Chore: add myself to FUNDING.yml 2023-03-25 00:50:40 +08:00
李通洲 9ee4c08790 Gamepad (Windows): detect gamepad name by productId
Also improve performance
2023-03-25 00:50:40 +08:00
李通洲 725d2f2612 Windows: fix <Windows.h> header mess 2023-03-25 00:50:40 +08:00
李通洲 4d5ad691f3 Doc: update changelog for flatpak-user support 2023-03-24 23:41:06 +08:00
李通洲 b2f3bf3461 Packages (Linux): support flatpak-user
Fixes #436
2023-03-24 17:47:03 +08:00
李通洲 44c389d29f Doc: document --display-compact-type 2023-03-23 15:09:47 +08:00
李通洲 ac8e03419e DisplayServer (Windows): correct resolution for vertical modes 2023-03-22 23:43:52 +08:00
李通洲 babb836f91 DisplayServer: detect display type ( builtin or external ) 2023-03-22 21:33:46 +08:00
李通洲 95e0a5ee95 DisplayServer: fix programming errors 2023-03-22 20:41:21 +08:00
李通洲 642a0c78cc Display: add options --display-detect-name and --display-precise-refresh-rate 2023-03-22 16:51:06 +08:00
李通洲 1ac90584cb Display: add option --display-compact-mode 2023-03-22 16:19:39 +08:00
李通洲 ccef5de86e Display (macOS, Windows): support display name detection 2023-03-22 16:04:48 +08:00
李通洲 e526ec9c32 Brightness: tidy 2023-03-22 15:44:59 +08:00
李通洲 b15e68658f FFstrbuf: make ffStrbufInit inlinable; add ffStrbufInitMove 2023-03-22 15:35:22 +08:00
李通洲 dcd0f8d3f6 DisplayServer (Windows): support precise refresh rate 2023-03-22 14:59:24 +08:00
李通洲 b3da6b0e89 CPU (Windows): try improving performance 2023-03-21 15:27:34 +08:00
李通洲 ff8c761de0 Doc: add changelog for new cursor features 2023-03-20 14:09:35 +08:00
李通洲 e6258acb55 Cursor (macOS): add support 2023-03-20 14:09:35 +08:00
李通洲 ecafed8fd5 Cursor (Windows): support cursor size detection 2023-03-20 10:29:06 +08:00
李通洲 73f99b1298 Doc: update changelog 2023-03-20 10:18:20 +08:00
Carter Li 7a6ed854ec Merge pull request #435 from regulargvy13/patch-1
Small update for nobara logo
2023-03-18 22:05:36 +08:00
regulargvy13 e923d78016 Small update for nobara logo
The last line in nobara logo was missing just a few spaces, so I added them, and now it's in proper shape :)
2023-03-18 00:46:46 +01:00
李通洲 615b2f72ae GPU (Linux): don't exit if libpci is failed to init
* Fixes #433
* Ref https://github.com/pciutils/pciutils/issues/136
2023-03-13 17:46:24 +08:00
李通洲 9773349253 Chassis: fix wrong module args used when printing 2023-03-10 13:54:27 +08:00
李通洲 fc57fa5415 Doc: document foot terminal support
Fix #431
2023-03-09 14:05:01 +08:00
李通洲 bdd9d46517 TerminalFont: support foot terminal 2023-03-09 14:02:08 +08:00
李通洲 013499f7a2 Terminal: support foot version detection 2023-03-09 14:01:59 +08:00
李通洲 c4416379bb Packages (Linux): support linuxbrew (Homebrew for Linux) 2023-03-08 15:02:58 +08:00
李通洲 c0c07e7dc9 TerminalFont: optimise JSON related code 2023-03-07 00:54:56 +08:00
李通洲 38ec3718ce CI: fix Windows artifacts 2023-03-06 11:22:57 +08:00
李通洲 e2e3561443 TerminalFont: migrate to json-c to prevent from 3rd lib code embedding 2023-03-04 12:17:16 +08:00
李通洲 199f2fc0cd Wifi (Linux): fix compiling with musl (#429) 2023-03-04 09:46:21 +08:00
李通洲 c944b2f599 DateTime: correct format as yyyy-MM-dd 2023-03-04 00:49:07 +08:00
李通洲 fdd0d47762 TerminalFont: migrate cJSON to yyjson
yyjson provides faster JSON parsing and supports JSON with comments ( which is allowed in WT config file )
https://github.com/ibireme/yyjson
2023-03-04 00:47:39 +08:00
李通洲 e5f851dcbb DisplayServer (Windows): fix scaled resolution detection 2023-03-04 00:41:32 +08:00
李通洲 78cb2781e6 Brightness (macOS): display monitor names 2023-03-01 15:40:18 +08:00
李通洲 ef9b5c57b1 DisplayServer (macOS): change process names 2023-02-27 11:29:10 +08:00
Carter Li 52eacd7140 Merge pull request #428 from LinusDierheimer/dev
Release: 1.10.3
2023-02-25 17:34:53 +08:00
李通洲 b19d8d6700 Release: 1.10.3 2023-02-25 16:06:16 +08:00
李通洲 6b0add44ee Init: print threads for --list-features if supported 2023-02-25 15:29:12 +08:00
李通洲 b66338494f CMake: fix compile error on Windows 2023-02-25 13:31:36 +08:00
李通洲 47cec48a49 GPU (Windows): fix uninited variables 2023-02-25 13:31:36 +08:00
李通洲 09ccbca79c WmTheme (Apple): don't depend on displayserver detection 2023-02-25 13:31:36 +08:00
李通洲 4f28ae62a7 Font: don't depend on displayserver detection on Windows and macOS. 2023-02-25 13:31:36 +08:00
李通洲 e953ea6542 Android: enable mutltithreading public-ip / weather detection 2023-02-24 17:48:20 +08:00
李通洲 de72c98a28 Init: don't create detection thread for displayserver on Windows / macOS
Displayserver (mainly resolutions) detection is cheap on win / mac, but creating an detection thread is unnecessary
2023-02-24 17:48:20 +08:00
李通洲 7f15f91bd3 Temps (Windows): dirty support
Note: https://stackoverflow.com/a/17083409
2023-02-23 21:31:33 +08:00
李通洲 c570c5bf97 IO: use FF_AUTO_CLOSE_FD 2023-02-23 13:58:39 +08:00
李通洲 52c304ecae IO (Linux): add detailed error messages for ffProcessAppendStdOut 2023-02-23 13:32:12 +08:00
Carter Li 4f4860eee8 Merge pull request #426 from LinusDierheimer/dev
Release: 1.10.2
2023-02-22 15:58:01 +08:00
李通洲 695e3cc692 Release: 1.10.2 2023-02-22 15:16:54 +08:00
李通洲 e05d9da231 Battery / Wifi: fix missing NULL for ffProcessAppendStdOut 2023-02-22 15:12:37 +08:00
Nanda H Krishna c16f9a9e20 sound_apple.c: handle kAudioObjectPropertyElementMain for macOS < 12 2023-02-22 14:19:22 +08:00
Carter Li 74b1871f18 CI: fix build (#424) 2023-02-21 22:19:17 +08:00
Carter Li 8fdb877840 Merge pull request #423 from LinusDierheimer/dev
Release 1.10.1
2023-02-21 21:43:50 +08:00
李通洲 3a7d7d79c0 CMake: more debug info 2023-02-21 21:40:55 +08:00
李通洲 28baf2596e CMake: more debug info 2023-02-21 21:38:10 +08:00
李通洲 30d1a55dde Release: 1.10.1 2023-02-21 21:28:26 +08:00
李通洲 3e068d16df Wifi / Battery (Android): more accurate checks 2023-02-21 21:25:02 +08:00
李通洲 c283e39b22 CI: update artifact name (Win32) 2023-02-21 20:44:22 +08:00
Carter Li f6702d83d0 Merge pull request #422 from LinusDierheimer/dev
Release 1.10.0
2023-02-21 18:48:33 +08:00
李通洲 b1a779c178 Release: 1.10.0; update changelog 2023-02-21 15:54:12 +08:00
李通洲 cc1260ee3c FFvaluestore: fix UB reported by clang 2023-02-21 10:21:07 +08:00
李通洲 92b1788825 Platform: refactor; remove extra / 2023-02-21 10:02:04 +08:00
李通洲 efdbeb585b Battery (Android): add temperature 2023-02-21 09:43:22 +08:00
李通洲 304f171d38 Battery / Wifi (Android): add more debug messages 2023-02-21 09:42:41 +08:00
李通洲 9a3909f8ba Memory (Windows): check for error cases 2023-02-16 17:19:43 +08:00
李通洲 6ca4b5391b Library: refactor FF_LIBRARY_LOAD to use __cleanup__ 2023-02-15 14:51:04 +08:00
李通洲 cabd36d078 CpuUsage (apple): simplify implementation 2023-02-14 19:24:29 +08:00
李通洲 64bacd2572 Vulkan: refactor directory structures 2023-02-14 17:52:58 +08:00
李通洲 47be29b89c DateTime: refactor directory structures 2023-02-14 17:49:23 +08:00
李通洲 6407bf6a1f GTK / QT: refactor directory structures 2023-02-14 17:47:39 +08:00
李通洲 e2d145cf31 Memory (Apple): use sysctl instead of sysctlbyname 2023-02-14 17:31:07 +08:00
李通洲 b634c70f80 Temp (Apple): support memory temperature detection for future use 2023-02-14 17:29:21 +08:00
李通洲 e29169711c TerminalShell (Linux): tidy 2023-02-14 16:33:58 +08:00
李通洲 662ddac050 Vulkan: detect vmem (#416) 2023-02-11 16:05:54 +08:00
李通洲 b90d543afc GPU (Windows): support vmem total / usage detection #416
vmem usage detection is guarded behind `--allow-slow-operations`
because it's really slow sometimes
2023-02-11 16:05:54 +08:00
李通洲 f05d134aa7 OpenCL: tidy 2023-02-10 11:20:27 +08:00
李通洲 74a68aa626 CMake: remove unused options 2023-02-10 11:08:05 +08:00
Linus Dierheimer fcc5170a10 Disk(Linux): Better detection of physical drives 2023-02-09 11:20:40 +01:00
李通洲 3a9403a2f1 Packages (Windows): optimise 2023-02-09 09:51:51 +08:00
李通洲 ff170caff6 GPU (Windows): fix duplicated entries. 2023-02-09 09:46:53 +08:00
李通洲 532b493c42 Doc: update changelog 2023-02-09 00:19:19 +08:00
李通洲 51cc87e0db GPU (Windows): keep WMI query as a slow operation for accurate results 2023-02-09 00:17:13 +08:00
李通洲 878d4608b1 Packages (Windows): fix scoop packages count in non-default install path 2023-02-09 00:15:35 +08:00
李通洲 03d1c62787 Packages (Windows): honor $SCOOP when detecting scoop packages
Fix #417
2023-02-08 22:49:30 +08:00
李通洲 5c46271898 GPU (Windows): fix driver version detection 2023-02-08 21:23:45 +08:00
李通洲 9a7c732555 OpenCL: fix Windows support
They changed the dll file name in the latest release
2023-02-08 21:07:36 +08:00
李通洲 8ffe6fda9b Battery: drop powrprof.dll dependency 2023-02-08 15:11:50 +08:00
Linus Dierheimer e563417166 Build test: Build as release with debug info 2023-02-07 12:21:47 +01:00
Linus Dierheimer ec3f9acd76 Cmake debug: change to exe linker only 2023-02-07 12:18:30 +01:00
李通洲 6c22fd6902 Host: update newest product name data (macOS) 2023-02-07 14:35:50 +08:00
李通洲 82b10a527b GPU: support driver version detection 2023-02-07 11:17:46 +08:00
李通洲 92c744d971 Windows: support for global config path in MSYS2 environment 2023-02-06 22:53:47 +08:00
李通洲 7a691a4286 Windows: add 32bit support 2023-02-06 16:03:38 +08:00
李通洲 e98489a74b Locale: tweaks 2023-02-06 14:55:57 +08:00
李通洲 7a5da23b0c Bluetooth: silense compiler warnings 2023-02-06 14:55:57 +08:00
李通洲 edf4837ed6 GPU: refactor vendor detection code 2023-02-06 14:55:57 +08:00
李通洲 749bd8db0e Gamepad (Windows): display attached controllers only 2023-02-05 21:42:59 +08:00
李通洲 d2460d8e85 GPU (Windows): try improving performance 2023-02-05 18:59:20 +08:00
Linus Dierheimer eead4cf70e Revert "Pipeline: debug"
This reverts commit 291f88b1e4.
2023-02-03 18:53:52 +01:00
Linus Dierheimer 291f88b1e4 Pipeline: debug 2023-02-03 18:48:40 +01:00
Linus Dierheimer 93f1a44d0f Revert "Pipeline: debug"
This reverts commit 550e107683.
2023-02-03 18:43:15 +01:00
Linus Dierheimer 550e107683 Pipeline: debug 2023-02-03 18:41:08 +01:00
Linus Dierheimer 7a8b94b6d4 Fix build with older libnm versions 2023-02-03 14:20:15 +01:00
Linus Dierheimer 2005b396fa Add missing comma 2023-02-03 13:38:37 +01:00
Linus Dierheimer 2a80b5ed36 Pipeline(Linux): Build on Ubuntu 20.04 2023-02-03 13:37:15 +01:00
Linus Dierheimer 47a32c725d X11: init scaled resolution with normal resolution 2023-02-03 11:22:34 +01:00
李通洲 fc26acd0ab DisplayServer: fix scaled resolution detection (Linux) 2023-02-03 10:34:17 +08:00
Linus Dierheimer e57f7d378a Wayland: support basic scale factors
#414
2023-02-02 18:16:56 +01:00
Linus Dierheimer 6de74587bd Update terminator font detection 2023-02-02 17:14:53 +01:00
Linus Dierheimer 6e5e7851d4 Merge pull request #415 from CSoellinger/feat/add-terminator-terminal-support
Add terminator terminal support
2023-02-02 17:01:59 +01:00
CSoellinger 84ccda45b0 feat: simplify parse prop file config 2023-02-02 16:16:24 +01:00
李通洲 ec3cd6cc68 LocalIP: support multiline compact mode 2023-02-02 22:25:31 +08:00
李通洲 cae9fee30a LocalIP (Windows): fix ipv6 detection 2023-02-02 21:01:50 +08:00
李通洲 f0111a8037 Windows: silense compiler warnings 2023-02-02 19:17:51 +08:00
CSoellinger 8fad590f8b feat: add terminator terminal support 2023-02-02 11:40:37 +01:00
CSoellinger 2ae5a9d725 Merge pull request #1 from LinusDierheimer/dev
Update dev
2023-02-02 11:25:06 +01:00
李通洲 8153c8b82c LocalIP: support --localip-compact-type option (#408) 2023-02-02 17:50:22 +08:00
Linus Dierheimer 159f4a3a3c Fix build on apple 2023-02-01 18:35:06 +01:00
Linus Dierheimer 3dbfff57e7 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-02-01 15:56:32 +01:00
Linus Dierheimer a063cd4feb Correctly handle zfs pools
#413
2023-02-01 15:56:25 +01:00
李通洲 dc5da3c3b3 Flashfetch: add missing modules 2023-02-01 21:54:45 +08:00
李通洲 79c9c19b1a Doc: document gamepad module support 2023-02-01 21:47:35 +08:00
李通洲 b49b583e64 Gamepad (Linux): add support 2023-02-01 21:46:23 +08:00
李通洲 0b8e8ad4f2 Gamepad (macOS): add support 2023-02-01 21:46:23 +08:00
李通洲 7fc2c4dcf1 Gamepad: init support for Windows 2023-02-01 21:46:23 +08:00
李通洲 a74cbc5781 Sound: fix memleak, update config file 2023-02-01 20:28:55 +08:00
Linus Dierheimer 619ec921ee Update changelog 2023-02-01 11:16:01 +01:00
Linus Dierheimer 1b23c9a030 Update changelog 2023-02-01 11:14:54 +01:00
Linus Dierheimer d4c11b9a1f Merge pull request #411 from CSoellinger/fix/detect-wm-mutter
fix: add another mutter detection for linux mint 21.1 (cinnamon)
2023-02-01 11:11:00 +01:00
CSoellinger 55da030e2a fix: move mutter(muffin) detection to get FF_WM_PRETTY_MUFFIN back 2023-02-01 10:50:31 +01:00
Linus Dierheimer c64f306550 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-02-01 10:43:32 +01:00
Linus Dierheimer 7ee4a648d0 Small fix to muffin theme detection 2023-02-01 10:43:24 +01:00
Linus Dierheimer 78ca4e7c87 Merge pull request #412 from CSoellinger/fix/spell-correction
fix: spell correction
2023-02-01 10:30:59 +01:00
CSoellinger 7a2826358b fix: spell correction 2023-02-01 10:08:08 +01:00
CSoellinger df84721b55 fix: add another mutter detection for linux mint 21.1 (cinnamon) 2023-02-01 10:01:47 +01:00
李通洲 f53a1f785d Doc: update changelog 2023-01-31 23:32:49 +08:00
李通洲 4f3b9776ae WmTheme (Windows): align output format to winfetch
Ref: https://github.com/lptstr/winfetch/commit/0358deea5e3ca03086be4984b905a0a534f8d1a5
2023-01-31 23:26:50 +08:00
李通洲 39f47d65a9 Sound: remove manufacturer detection
as it's only implemented on macOS
2023-01-31 22:39:27 +08:00
李通洲 a92e6b6d91 Sound (macOS): fix active device detection; fix memleaks; don't use deprecated properties 2023-01-31 22:37:48 +08:00
李通洲 00e044c431 Sound: change option --sound-show-all to --sound-type 2023-01-31 21:12:47 +08:00
李通洲 7132762c9c Sound (Linux): small fixes
1. treat PA_PORT_AVAILABLE_UNKNOWN as active so that the default speaker is active now
2. load `libpulse.so` as suggested in `config_user.txt`
2023-01-31 20:55:01 +08:00
李通洲 2476b44300 Global: add support for colored percentage numbers output 2023-01-31 19:42:11 +08:00
李通洲 d36e827ec9 Fastfetch: remove --nocache which has been deprecated for a while 2023-01-31 17:15:45 +08:00
Linus Dierheimer a37115cb00 Fix build on windows 2023-01-30 23:23:14 +01:00
Linus Dierheimer 7dc73c61ab WMDE: avoid the use of magick strings across the project
There are probably more, but those are all i found for now.
2023-01-30 18:46:39 +01:00
李通洲 a14ef06d14 TerminalShell (Windows): fix a rare case that fails to detect terminal 2023-01-29 23:29:53 +08:00
李通洲 212e7aa47e CI: test for memleaks 2023-01-29 13:12:50 +08:00
李通洲 ebe26eddf0 Windows: minify included headers 2023-01-29 10:21:23 +08:00
李通洲 517e3fcff9 WMI: add timeout to prevent CI from hanging
Hard coded 5 seconds
2023-01-29 10:10:31 +08:00
Linus Dierheimer 679162c762 --list-logos: list custom logos too 2023-01-28 17:19:45 +01:00
李通洲 e4973b3262 IO: fix Windows part; silense warnings 2023-01-28 22:46:59 +08:00
Linus Dierheimer a1ea7804f3 IO: Separate platform specific implementations 2023-01-28 12:40:12 +01:00
Linus Dierheimer 2c51d55ba2 IO: don't require posix specific stuff for ffPathExists 2023-01-28 11:52:23 +01:00
Linus Dierheimer 3b0e1a5833 Image: Use correct cache dir 2023-01-28 11:28:05 +01:00
Linus Dierheimer 9bb6d8fd6e Allow loading images from data dirs too
#375
2023-01-28 11:14:16 +01:00
李通洲 4afba798ba Sound: add missing command helpers 2023-01-28 13:46:40 +08:00
李通洲 f4cefe955b Sound: always initialize identifier and destroy it to avoid memleaks 2023-01-28 13:46:40 +08:00
李通洲 1c38ebb551 Parsing: only disable warning when necessary 2023-01-28 13:46:40 +08:00
Linus Dierheimer 14dcafe2ca Bluetooth(Linux): Refactor code a bit 2023-01-27 18:21:42 +01:00
Linus Dierheimer cf78216d78 Sound(Linux): Don't abuse manufactor 2023-01-27 18:03:57 +01:00
Linus Dierheimer 0c256e2908 Just try with all on and all of 2023-01-27 13:01:24 +01:00
Linus Dierheimer 00fc3f1a1d Add a workflow that tests different build config combinations 2023-01-27 12:56:36 +01:00
Linus Dierheimer 672e309d89 Small fixes 2023-01-27 11:21:01 +01:00
李通洲 b0c19256f0 Bluetooth: silense warnings 2023-01-27 13:10:06 +08:00
李通洲 205e664b4d Sound (Windows): show more detailed information 2023-01-27 13:08:07 +08:00
Linus Dierheimer cb466aec08 Linux: Fix build without dbus
#405
2023-01-26 22:08:55 +01:00
Linus Dierheimer 33f3744a63 Sound(Linux): Treat default port as always active
This fixes no shown sound devices when no audio is currently played
2023-01-26 17:25:14 +01:00
Linus Dierheimer 7adb1606f1 GH Actions: build with libpulse 2023-01-26 15:50:35 +01:00
Linus Dierheimer 184ada6ae8 Sound(linux): Implement using libpulse
Also differentiate between active and main device(s)
2023-01-26 15:48:28 +01:00
李通洲 856c9d58b8 TerminalFont: tweaks 2023-01-26 01:15:33 +08:00
李通洲 f3fba8a389 CI: build with alsa enabled 2023-01-26 01:14:22 +08:00
李通洲 10468a559a Doc: document Sound module support 2023-01-26 01:14:22 +08:00
李通洲 c4c9f02433 Sound (Linux): add dirty support 2023-01-26 01:14:22 +08:00
李通洲 f2dd288a0d Sound: don't leak memory 2023-01-26 00:36:45 +08:00
李通洲 aa36a83182 Windows: silense some warnings 2023-01-25 17:25:05 +08:00
李通洲 dd9047c4e9 Sound (Windows): add support 2023-01-25 17:17:31 +08:00
李通洲 11634b9a67 Windows: add com helper 2023-01-25 17:17:19 +08:00
李通洲 d832324306 Sound (macOS): new module 2023-01-25 14:28:13 +08:00
Linus Dierheimer a7af5c4f66 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-25 00:03:01 +01:00
Linus Dierheimer 0f2022bd40 Bluetooth: Don't leak memory 2023-01-25 00:02:54 +01:00
李通洲 e598598ca8 Bluetooth (macOS): add support
Limitation: no battery level
2023-01-24 22:13:53 +08:00
李通洲 85599fcf53 Bluetooth (Windows): add support
Limitation: no HLE devices, no battery level
2023-01-24 21:01:21 +08:00
Linus Dierheimer 6961488d38 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-24 12:02:47 +01:00
Linus Dierheimer 209d0c98d9 Bluetooth: Support multiple devices 2023-01-24 12:02:20 +01:00
Linus Dierheimer d718cc997c Merge pull request #404 from LinusDierheimer/master
Master
2023-01-24 10:51:03 +01:00
Linus Dierheimer 4967d0a222 Bluetooth: Build on unsupported platforms 2023-01-24 10:46:00 +01:00
Linus Dierheimer 17ebd5cea8 Merge 2023-01-24 10:40:29 +01:00
Linus Dierheimer 25e81b39f9 Bluetooth module 2023-01-24 10:39:33 +01:00
Linus Dierheimer 4b253aa4cf Merge pull request #403 from LinusDierheimer/dev
Release 1.9.1
2023-01-24 10:05:49 +01:00
李通洲 d7b84bed9f Doc: update changelog 2023-01-24 16:16:08 +08:00
李通洲 298d091e2e Wifi: fix the default output formatting 2023-01-24 11:30:25 +08:00
Carter Li ebe30394f2 Display (macOS): fix zero refresh rate on some monitors 2023-01-24 11:21:08 +08:00
李通洲 4c7d479e93 Release: 1.9.1 2023-01-24 10:14:59 +08:00
李通洲 d6d204ae5f Fastfetch: fix builds on unknown platform (#402) 2023-01-24 10:11:35 +08:00
Jonathan Wright ed23eb0fde Fix builds on s390x (#402)
Fixes #401
2023-01-24 10:09:26 +08:00
Linus Dierheimer fbbfc7f73c Merge pull request #399 from LinusDierheimer/dev
Release 1.9.0
2023-01-22 01:09:35 +01:00
李通洲 e0b2db17c2 Changelog: update version 2023-01-22 00:39:45 +08:00
李通洲 f360e10050 Release: 1.9.0 2023-01-22 00:32:41 +08:00
Linus Dierheimer c15f55762d Disk(Linux): Use mountpoint as last fallback for disk name 2023-01-21 14:57:30 +01:00
Linus Dierheimer 7edc715cba Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-21 14:43:02 +01:00
Linus Dierheimer 27f76599bc Fix subvolume detection
#396
2023-01-21 14:42:19 +01:00
李通洲 e8bde5a394 Wifi: fix compiling on macOS 2023-01-21 16:23:28 +08:00
李通洲 3b820f1145 Doc: document wifi / battery support on Android 2023-01-21 16:04:16 +08:00
李通洲 c1444c0822 Android: support Wifi & Battery by using termux-api 2023-01-21 15:23:40 +08:00
李通洲 b424c525cc Disk (Android): fix compiling errors 2023-01-21 14:09:07 +08:00
李通洲 f640102b0e CPU (Linux): fix compiler warnings 2023-01-21 14:03:57 +08:00
李通洲 d9e79a5376 Fastfetch: print more info with -v 2023-01-21 10:33:09 +08:00
Linus Dierheimer 734ee38641 Disk (Linux): partition name impl & general refactor 2023-01-20 20:25:22 +01:00
李通洲 e651633c54 Temp: detect both device/class anddevice/device/class 2023-01-21 06:54:51 +08:00
李通洲 6d4bd06ffe Fastfetch: add missing \n when printing messages 2023-01-21 06:27:39 +08:00
李通洲 2af07fee4f Changelog: doc cpu temp fix 2023-01-21 06:26:24 +08:00
李通洲 6f4bdafb0c Temp: fix severial issues. Fixes #398
1. Temp detection has been gated behind of `--*-temp`. Don't make it a slow operation
2. According to [the kernel doc](https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface), `temp1_input` is millidegree Celsius, which should be divided by 1000
3. There is no `/sys/class/hwmon/hwmon3/device/class` on my laptop, but `/sys/class/hwmon/hwmon3/device/device/class`. Need to confirm with @LinusDierheimer
4. Small code optimizations
2023-01-21 06:18:19 +08:00
Linus Dierheimer a71f2142bb Disk(Linux): Better subvolume detection
#396
2023-01-20 13:28:25 +01:00
李通洲 1e9ec5424a Global: add NO_CONFIG env variable
to disable parsing config files, for debugging purpose.
2023-01-20 16:05:03 +08:00
李通洲 068cbafe3d Packages: detect pacman package count inside MSYS2 env (Windows) 2023-01-18 23:10:28 +08:00
李通洲 4ce618c33c DisplayServer: fix win32 compatibility 2023-01-18 22:44:24 +08:00
李通洲 10b997608b Font: optimise output for Windows 2023-01-18 18:01:09 +08:00
Linus Dierheimer 5edab414d8 Cursor: prefer gtk over Xresources
#382
2023-01-17 17:49:41 +01:00
李通洲 6e904047f9 Display: document scaled resolution support 2023-01-17 23:07:20 +08:00
李通洲 fdb0cfb4df Display: detect scaled resolution (Windows) 2023-01-17 21:36:43 +08:00
李通洲 58999995f1 Display: split phycial resolution and scaled resolution 2023-01-17 19:09:18 +08:00
李通洲 f4a58036fa Resolution: rename to display 2023-01-17 18:21:53 +08:00
李通洲 65e2331979 CI: print brightness 2023-01-18 01:00:30 +08:00
李通洲 622a5c267b Wifi: fall back to ioctls if fail to loading libnm libs 2023-01-18 01:00:00 +08:00
李通洲 c746cde61e Wifi: code refactor; fix a silly copy & paste error 2023-01-17 15:52:51 +08:00
李通洲 68977be256 CI: build with libnm support; print supported features 2023-01-17 15:38:03 +08:00
李通洲 f28805fb94 Wifi: detect more information using libnm (Linux) 2023-01-17 05:36:43 +08:00
李通洲 df793c20fd Wifi: use ioctls instead of iw (Linux) 2023-01-17 10:43:55 +08:00
Linus Dierheimer a4e4e9c495 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-16 11:53:13 +01:00
Linus Dierheimer b1ccd2e2c0 Don't show subvolumes by default 2023-01-16 11:52:54 +01:00
李通洲 9a2687768f FFPlatform: remove extra / 2023-01-16 18:23:54 +08:00
Linus Dierheimer ab7b0571f3 Fix config files loading other config files 2023-01-15 20:03:28 +01:00
李通洲 14286e8c0f Fix typo 2023-01-16 01:20:10 +08:00
李通洲 6b41b85d4d Windows: fix sigfault 2023-01-16 01:18:13 +08:00
李通洲 cc7724dec4 FFPlatform: don't use target platform as running platform 2023-01-15 17:00:36 +08:00
李通洲 c832c7d794 Host: don't print None as product version 2023-01-15 16:55:33 +08:00
李通洲 52f36d29dc Doc: update CHANGELOG 2023-01-16 00:41:56 +08:00
李通洲 9b6dafe715 Packages: fix rpm count detection
Can't believe that this bug has existed for more than 3 months and no one found it
2023-01-16 00:41:35 +08:00
李通洲 d4ecbc6638 FFPlatform: fix memleaks 2023-01-16 00:35:48 +08:00
李通洲 1c93d68e7b Wifi: add basic Linux support using iw 2023-01-16 00:33:31 +08:00
Linus Dierheimer c1d92206f5 Third round of fixes for FFPlatform 2023-01-15 16:45:16 +01:00
Linus Dierheimer 7bef5008c2 Second round of fixes for FFPlatform 2023-01-15 16:26:08 +01:00
Linus Dierheimer 3ef3cca76b First round of fixes for FFPlatform 2023-01-15 16:06:50 +01:00
Linus Dierheimer a1d8e3e598 Introduce FFPlatform 2023-01-15 15:57:26 +01:00
Linus Dierheimer dd77ebe11e Fix GitHub code scanning alert 2023-01-14 19:59:54 +01:00
李通洲 27efc94b09 FFlist: silence compiler warnings when compiling with -m32 2023-01-15 01:02:10 +08:00
Linus Dierheimer b6abc6e326 Update logo doc 2023-01-14 17:54:21 +01:00
Linus Dierheimer f13a502123 Update logo doc 2023-01-14 17:50:14 +01:00
Linus Dierheimer f77f617bc2 Update Support Status 2023-01-14 17:20:36 +01:00
Carter Li 6ae9e0b332 Merge pull request #389 from CarterLi/command
RFC: an attempt to add a new module which can run custom shell scripts
2023-01-15 00:08:04 +08:00
Linus Dierheimer 8a054706b5 Fix build on linux 2023-01-14 17:00:56 +01:00
Linus Dierheimer 6e1d656a60 Fix budgie detection
#382
2023-01-14 16:58:09 +01:00
Linus Dierheimer 53430b9827 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-14 16:38:52 +01:00
Linus Dierheimer 026424ab8c Don't crash when uname fails
#385
2023-01-14 16:38:34 +01:00
李通洲 9c0fc63ee9 Windows: with cdff99, the special build for Win7 is no longer needed. Drop it. 2023-01-14 17:46:11 +08:00
李通洲 cdff99339e Windows: fix the last issue that breaks Win10- 2023-01-14 17:31:04 +08:00
李通洲 b739d94f23 Command: an attempt to add a new module which can run custom shell scripts 2023-01-14 01:27:54 +08:00
李通洲 e076097a7c FFlist: fix compiler warnings 2023-01-14 00:19:55 +08:00
李通洲 3cee8f5475 FFlist: add new functions to make it be able to work as a queue 2023-01-13 19:08:14 +08:00
李通洲 83ea189d81 GPU: simplify code 2023-01-13 15:46:29 +08:00
李通洲 dcf04aa4fe GPU: detect type based on vendor 2023-01-13 15:44:52 +08:00
李通洲 67ab7c0779 GPU: support vendor detection 2023-01-13 15:20:30 +08:00
李通洲 2b5511997c Global: support hiding other texts when printing percentage values 2023-01-12 22:46:21 +08:00
李通洲 53c6a0ec9f GPU: apply GPU type selection logic to Windows 2023-01-12 22:19:14 +08:00
Linus Dierheimer 1a710e4094 Better GPU type detection nr2
#379
2023-01-12 12:56:17 +01:00
Linus Dierheimer 5a90d8b545 Better GPU type detection
#379
2023-01-12 12:54:04 +01:00
Linus Dierheimer f794053f99 Merge branch 'dev' of github.com:LinusDierheimer/fastfetch into dev 2023-01-12 11:42:23 +01:00
Linus Dierheimer 670cf6fe90 GPU selection options
#379
2023-01-12 11:41:07 +01:00
李通洲 46ed8aa87c TerminalFont: don't try to detecting kitty and tty fonts on Windows 2023-01-12 00:19:30 +08:00
李通洲 387b8298bd Windows: fix bug that line buffering doesn't work properly 2023-01-12 00:19:30 +08:00
李通洲 c4aa55d522 TerminalFont: support WezTerm on Windows 2023-01-12 00:09:42 +08:00
李通洲 c3861954dc TerminalFont: support Alacritty on Windows 2023-01-11 23:46:37 +08:00
李通洲 ebfbf108a2 TerminalShell: support Alacritty terminal version detection 2023-01-11 23:46:15 +08:00
李通洲 66ed9adcda TerminalShell: support ConEmu version detection 2023-01-11 22:14:47 +08:00
李通洲 eb02206c05 TerminalShell: support Windows Terminal version detection 2023-01-11 22:10:42 +08:00
李通洲 cd0b74b0de TerminalShell: support deepin-terminal version detection 2023-01-11 18:12:36 +08:00
李通洲 6ca3b76a42 Update README 2023-01-11 18:07:58 +08:00
李通洲 84a03e80de README: clarify that fastfetch isn't written in pure C
Ref: https://github.com/ScoopInstaller/Main/pull/4334#discussion_r1066502517
2023-01-11 17:37:49 +08:00
李通洲 a74f813df1 CHANGLOG: remove a duplicated entry
oops
2023-01-11 17:37:49 +08:00
李通洲 99fc4e76ec TerminalShell: fix build on Windows 2023-01-11 17:27:34 +08:00
李通洲 7145f5252d TerminalShell: add --shell-version and --terminal-version options to disable shell / terminal version detection
in case that users don't like it
2023-01-11 17:17:17 +08:00
李通洲 9dab23b5fc TerminalShell: code refactor 2023-01-11 16:45:34 +08:00
李通洲 09ff8d35bc TerminalShell: support xfce4-terminal version detection 2023-01-11 16:07:34 +08:00
李通洲 ee903d2d07 TerminalShell: support konsole version detection 2023-01-11 15:56:24 +08:00
李通洲 b2f978aa7c TerminalShell: support kitty version detection 2023-01-11 15:14:29 +08:00
李通洲 76d957a144 TerminalShell: support gnome-terminal version detection 2023-01-11 15:12:32 +08:00
李通洲 a0acfeed56 TermiinalShell: code refactor 2023-01-11 15:03:16 +08:00
李通洲 b1f63ab822 Global: rename FF_UNUSED_PARAM to FF_MAYBE_UNUSED since it can be used on functions too. 2023-01-11 14:47:10 +08:00
李通洲 54ea9c2386 TerminalFont: support WezTerm font detection 2023-01-11 13:58:59 +08:00
李通洲 ccdb5c54d0 Linux: enable FF_*_AUTO_DESTROY
They have been on Windows and macOS for sometime and worked well.
2023-01-11 13:55:06 +08:00
李通洲 b8393051e4 Battery: add comments for future use (FreeBSD) 2023-01-11 13:52:14 +08:00
李通洲 94a8e0339e Windows: remove outdated comments 2023-01-11 13:51:47 +08:00
李通洲 a67ba713f5 Windows: fix CLANG64 build 2023-01-11 09:37:00 +08:00
李通洲 8ffbae80b8 Windows: clarify we support Windows 7 and newer only 2023-01-11 01:23:42 +08:00
李通洲 db17f95ce8 TerminalShell: detect Termux version 2023-01-10 21:11:44 +08:00
李通洲 c6365755c7 Title: fix computer name being trancated sometime 2023-01-10 20:56:54 +08:00
李通洲 ef2a5110fe TerminalShell: detect terminal version when available 2023-01-10 19:26:33 +08:00
李通洲 7f97725d7f Disk: add --disk-show-unknown option
Ref: https://github.com/LinusDierheimer/fastfetch/issues/383#issuecomment-1376893128
2023-01-10 17:31:47 +08:00
李通洲 af03c74fba Battery: fix build on macOS 2023-01-10 16:56:56 +08:00
李通洲 bc8a7a03c3 Battery: fix bug on FreeBSD
oops
2023-01-10 12:42:15 +08:00
李通洲 d4c361ae12 Battery: support FreeBSD
Completely untested
2023-01-10 12:36:38 +08:00
李通洲 8f932ac3d6 DisplayServer: fix build (Linux) 2023-01-09 22:33:10 +08:00
李通洲 4cc5f35b04 DisplayServer: revert changes of brightness partially 2023-01-09 22:26:56 +08:00
李通洲 476b0495e0 Brightness: add support for Windows 2023-01-09 22:26:56 +08:00
李通洲 85098a6627 Brightness: add support for Linux 2023-01-09 22:26:56 +08:00
李通洲 d9a022ffff Brightness: add new module (macOS)
It turns out that merging brightness module into resolution module is a bad idea.
2023-01-09 22:26:56 +08:00
Linus Dierheimer 8db1534ef3 Merge pull request #381 from aaronfranke/cpu-riscv
Add support for displaying the ISA string on RISC-V CPUs
2023-01-09 15:22:17 +01:00
Linus Dierheimer 0aa7d646a7 Initial logo documentation 2023-01-09 15:20:30 +01:00
Carter Li 599c06e981 Merge pull request #384 from VergeDX/dev
fix[getNixPackagesImpl]: count line with `wc -l` instead, also fixes leak.
2023-01-09 19:13:05 +08:00
Vanilla 078cb6e5b7 fix[getNixPackagesImpl]: count line with wc -l instead, also fixes leak. 2023-01-09 18:58:52 +08:00
Aaron Franke 5cc17bc306 Add support for displaying the ISA string on RISC-V CPUs 2023-01-09 02:21:26 -06:00
李通洲 ef18c8e3f7 Users: remove "wtsapi32_extend" as mingw_w64 now officially supports these APIs
Ref: https://github.com/mirror/mingw-w64/commit/931ca20b233e766950e7758cff71c270937b0b64
2023-01-09 14:03:46 +08:00
李通洲 012c7552eb macOS: try fixing #380 2023-01-09 13:42:58 +08:00
李通洲 0fd63084dc Global: fix other possible bugs where enumerating directories without ignoring . and .. 2023-01-09 10:45:51 +08:00
李通洲 0b12e73eef DisplayServer: make brightness detection actually work (Linux) 2023-01-09 10:44:09 +08:00
李通洲 4daf3016f8 Global: fix memleaks 2023-01-09 10:02:48 +08:00
李通洲 9f8e256bb4 DisplayServer: support brightness detection (Linux) 2023-01-08 20:47:06 +08:00
Linus Dierheimer 1bbcd9ad0d Look for logo files in <datadir>/fastfetch/logos/ too
#375
2023-01-08 12:30:36 +01:00
Linus Dierheimer b1c0a2dc1e Better init of config & data dirs 2023-01-08 11:32:43 +01:00
Linus Dierheimer 2a092de8d8 Detect data dirs at runtime
* Respecting the current platform
* Using them where appropiate
2023-01-08 01:41:09 +01:00
Linus Dierheimer bb57714ac9 Use configDirs to look for fastfetch configs 2023-01-07 22:51:47 +01:00
Linus Dierheimer 137039f868 Initialize brightness on wayland too 2023-01-07 22:37:01 +01:00
李通洲 e7af38aa11 DisplayServer: make display brightness actually work (Windows) 2023-01-08 01:27:54 +08:00
李通洲 d0bab2ca22 Image: fix compiler warnings (Windows) 2023-01-08 01:27:54 +08:00
李通洲 2621c48f92 DisplayServer: support brightness detection (Windows) 2023-01-08 01:27:54 +08:00
李通洲 959540f17c DisplayServer: support brightness detection (macOS) 2023-01-08 01:27:54 +08:00
李通洲 3e2c344417 Android: honor $XDG_CONFIG_HOME when loading user config file 2023-01-08 01:27:34 +08:00
李通洲 a307977ec1 Image: don't try to read image file with --logo none 2023-01-08 01:26:10 +08:00
李通洲 f3db4e49b6 Windows: store config file in RoamingAppData instead of LocalAppData 2023-01-03 17:01:24 +08:00
李通洲 30f9bcbd22 TerminalFont: fix mintty terminal font detection 2023-01-03 17:01:24 +08:00
李通洲 a98c71aab4 Config: search for user config file in the order of configDirs
This is necessary to keep forward compatibility for Windows / macOS users. Since `$LOCALAPPPATH` and `~/Library/Preferences` are now the first element of `configDirs`, config files in `~/.config` won't be used in previous manner.
2023-01-02 17:27:06 +08:00
李通洲 0d722ebe0b Config: add --list-config-paths option 2023-01-02 16:51:11 +08:00
李通洲 3caa92c567 macOS: looking for config files in ~/Library/Preferences 2023-01-02 16:34:57 +08:00
李通洲 ae6d921f23 Config: don't generate a config file silently
Instead, provide a new flag `--gen-config` and print the path to the config file, so that users can know where to find the file.
2023-01-02 16:34:57 +08:00
李通洲 d692fe91fb Windows: don't try to load config file in /etc 2023-01-02 16:34:57 +08:00
李通洲 822496808d Windows: look for config files in $LOCALAPPDATA 2023-01-02 16:34:57 +08:00
Linus Dierheimer 8533dc234b Update Changelog 2023-01-01 18:33:24 +01:00
Linus Dierheimer 2193fb531f Merge pull request #378 from IamNoRobot/pi-logo
fixed formatting error
2023-01-01 18:23:28 +01:00
Linus Dierheimer c069d14af5 Merge pull request #373 from IamNoRobot/pi-logo
RaspberryPi Logo, RaspberryPi small logo
2023-01-01 18:18:32 +01:00
IamNoRobot 02abc07bc1 fixed formatting error 2023-01-01 18:18:01 +01:00
IamNoRobot 34c33dd42f RaspberryPi Logo, RaspberryPi small logo 2023-01-01 18:05:09 +01:00
Linus Dierheimer dcc22f3bd7 Merge pull request #376 from jessebot/patch-1
Fix error text typo from item to iterm
2023-01-01 15:47:59 +01:00
JesseBot 4247d15672 Fix error text typo from item to iterm 2023-01-01 15:39:03 +01:00
李通洲 39d8ebc3c9 Logo: support --logo-padding-top 2023-01-01 17:37:11 +08:00
李通洲 8e3b6280af Image: support iterm protocol with --logo-type
fixes #374
2023-01-01 17:09:30 +08:00
李通洲 4a781d8471 Logo: support raw image type
For raw image type, fastfetch nether parses the file content, nor tries to detect the image size from the file. It's useful to print pre-converted sixel image.
2023-01-01 17:06:18 +08:00
李通洲 9f93ca8019 README: document image logo support 2023-01-01 12:29:08 +08:00
IamNotARobot 4890cb641c RaspberryPi Logo, RaspberryPi small logo 2022-12-31 17:52:47 +01:00
Linus Dierheimer 90bb004940 Merge pull request #371 from LinusDierheimer/master
Merge pull request #370 from LinusDierheimer/dev
2022-12-31 13:15:21 +01:00
268 changed files with 9056 additions and 3850 deletions
+1 -1
View File
@@ -1 +1 @@
github: LinusDierheimer
github: [LinusDierheimer, CarterLi]
+66 -53
View File
@@ -5,9 +5,44 @@ on:
- pull_request
jobs:
linux-buildtest:
name: Linux build test
permissions:
contents: read
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-20.04]
compiler: [gcc, clang]
enableFeatures: [ON, OFF]
runs-on: ${{ matrix.os }}
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libcjson-dev
- name: configure project
env:
CC: ${{ matrix.compiler }}
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} .
- name: build project
run: cmake --build .
- name: run tests
run: ctest
- name: run fastfetch
run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: ./flashfetch
linux:
name: Linux
runs-on: ubuntu-latest
runs-on: ubuntu-20.04 # 22.04 ships a newer version of glibc than debian stable, allow those people to use the debian package
permissions:
security-events: write
contents: read
@@ -18,7 +53,7 @@ jobs:
uses: actions/checkout@v3
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libcjson-dev
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libcjson-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -34,6 +69,9 @@ jobs:
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
@@ -80,6 +118,9 @@ jobs:
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
@@ -113,6 +154,7 @@ jobs:
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package
./fastfetch --list-features
time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
time ./flashfetch
ctest
@@ -123,8 +165,8 @@ jobs:
name: fastfetch-freebsd
path: ./fastfetch-*.*
windows:
name: Windows
win64:
name: Win64
runs-on: windows-latest
permissions:
security-events: write
@@ -141,27 +183,11 @@ jobs:
with:
msystem: CLANG64
update: true
install: git zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
install: git zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-cjson
- name: print msys version
run: uname -a
# https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785
- name: create OpenCL.pc
run: |
cat > /clang64/lib/pkgconfig/OpenCL.pc << EOF
prefix=/clang64
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: OpenCL
Description: Open Computing Language generic Installable Client Driver Loader
Version: 2022.09.30-1
Libs: -L${libdir} -lOpenCL.dll
Cflags: -I${includedir}
EOF
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
@@ -177,7 +203,10 @@ jobs:
uses: github/codeql-action/analyze@v2
- name: copy necessary dlls
run: cp /clang64/bin/{libcjson,libOpenCL,vulkan-1}.dll .
run: cp /clang64/bin/{libcjson,OpenCL,vulkan-1}.dll .
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
@@ -189,16 +218,16 @@ jobs:
run: ctest
- name: create zip archive
run: zip fastfetch-$(./fastfetch --version-raw)-Windows.zip *.dll fastfetch.exe flashfetch.exe
run: zip fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-windows
path: ./fastfetch-*-Windows.zip
name: fastfetch-win64
path: ./fastfetch-*-Win64.zip
win7:
name: Win7
win32:
name: Win32
runs-on: windows-latest
permissions:
security-events: write
@@ -213,36 +242,20 @@ jobs:
- name: setup-msys2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
msystem: CLANG32
update: true
install: git zip mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-cjson mingw-w64-x86_64-vulkan-loader mingw-w64-x86_64-opencl-icd
install: git zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd mingw-w64-clang-i686-cjson
- name: print msys version
run: uname -a
# https://github.com/msys2/MINGW-packages/issues/13524#event-7555720785
- name: create OpenCL.pc
run: |
cat > /mingw64/lib/pkgconfig/OpenCL.pc << EOF
prefix=/mingw64
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: OpenCL
Description: Open Computing Language generic Installable Client Driver Loader
Version: 2022.09.30-1
Libs: -L${libdir} -lOpenCL.dll
Cflags: -I${includedir}
EOF
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: c, cpp
- name: configure project
run: env PKG_CONFIG_PATH=/mingw64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_BUFFER=Off .
run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build .
@@ -251,7 +264,7 @@ jobs:
uses: github/codeql-action/analyze@v2
- name: copy necessary dlls
run: cp /mingw64/bin/{libcjson,libOpenCL,vulkan-1}.dll .
run: cp /clang32/bin/{libcjson,OpenCL,vulkan-1}.dll .
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
@@ -263,13 +276,13 @@ jobs:
run: ctest
- name: create zip archive
run: zip fastfetch-$(./fastfetch --version-raw)-Win7.zip *.dll fastfetch.exe flashfetch.exe
run: zip fastfetch-$(./fastfetch --version-raw)-Win32.zip *.dll fastfetch.exe flashfetch.exe
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-win7
path: ./fastfetch-*-Win7.zip
name: fastfetch-win32
path: ./fastfetch-*-Win32.zip
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch'
@@ -279,8 +292,8 @@ jobs:
- linux
- macos
- freebsd
- windows
- win7
- win64
- win32
permissions:
contents: write
steps:
@@ -300,4 +313,4 @@ jobs:
tag: ${{ needs.linux.outputs.ffversion }}
commit: ${{ github.sha }}
artifactErrorsFailBuild: true
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/*,fastfetch-win7/*
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-win64/*,fastfetch-win32/*
+182 -1
View File
@@ -1,3 +1,184 @@
# 1.11.3
Bugfixes:
* Fix a segfault bug, regression of `1.11.1` (Linux, wmtheme, #467)
# 1.11.2
This release should be the last version of fastfetch 1.x (if no serious bugs found, hopefully)
Features:
* Support display name, type, rotation detection on Wayland (Linux, Display)
* Print more useful display name instead of intel_backlight (Linux, Brightness)
* Icons module supports Windows (Windows, Icons)
* Add Wallpaper module which shows the current wallpaper image path
* Add mac address detection `--localip-show-mac` (LocalIP, #451)
Bugfixes:
* Fix Gnome version detection on Fedora (DE)
* Fix Windows drives detection in WSL (Disk)
Changes:
* In order to make Icons module consistant between different platforms, `--icons-format` no longer supports individual GTK / QT icon params.
* `--theme-format` no longer supports individual GTK / plasma theme params.
* `--local-ip-*` and `--public-ip-*` have been changed to `--localip-*` and `--publicip-*`
* `--localip-compact-type` is no longer supported. Fastfetch now display IPs as `--localip-compat-type multiline` by default, with `--local-compact true` can be set as an alias of `--localip-compact-type oneline`
* `--localip-v6first` is no longer supported.
# 1.11.1
Features:
* Support xonsh detection (TerminalShell)
* Support Tabby version / terminal font detection (TerminalFont)
Bugfixes:
* Fix name of Pro Controller (Gamepad, Windows)
* Fix compile error with imagemagick enabled (Windows)
* Fix copy-and-paste errors (Gamepad)
* Flatpak: Fix user package count
* Flatpak: Count runtime packages too (#441)
* Fix flatpak package count (#441)
* Don't print white color blocks with `--pipe` (#450)
* Fix iTerm being detected as iTermServer-* sometimes
* Fix sound device volume being incorrectly detected as muted sometimes (Sound)
* Fix memleaks reported by LeakSanitizer (Linux)
* Fix potential memory curruption bug in unicode.c (Windows)
Logo:
* Update Windows 11 ASCII logo to look more visually consistent (#445)
* Add another font color index to arch icon (#446)
* Add SteamOS
* Add macOS small / small2
# 1.11.0
Features:
* Support linuxbrew (Packages, Linux)
* Support foot terminal (#431, Linux)
* Support cursor size detection on Windows (Cursor, Windows)
* Support cursor detection on macOS (Cursor, macOS)
* Support display name, display type and decimal refresh rate detection (Display, macOS / Windows)
* Support `--display-compact-type` to display multiple resolutions in one line (Display)
* Support flatpak-user (Packages, Linux, #436)
* Support `--gpu-force-vulkan` to force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations` (GPU)
Bugfixes:
* Fix date time format
* Fix compiling with musl (Wifi, Linux, #429)
* Don't exit if libpci is failed to init (GPU, Linux, #433)
* Names of most well-known gamepads are correctly printed instead of `Wireless Controller` on Windows
Logo:
* Small update for nobara logo (#435, @regulargvy13)
# 1.10.3
Bugfixes:
* Fix uninitialized variables (GPU, Windows)
* Fix compiling errors (Windows)
Improvements:
* Improve preformance (WmTheme amd Font, Windows and macOS)
* Enable nonblocking public-ip / weather detection (Android)
# 1.10.2
Bugfixes:
* Handle `kAudioObjectPropertyElementMain` for macOS **SDK** < 12 (#425, @nandahkrishna)
* Add missing `NULL` for `ffProcessAppendStdOut` (#421)
# 1.10.1
New release for debugging #421
# 1.10.0
Notable Changes:
* With the support of Win32 platform, original Windows 64bit artifact file is renamed to Win64 to avoid possible confusion
Features:
* Bluetooth module
* Sound module
* Gamepad module
* Support colored percentage numbers output (#409)
* Support `--localip-compact-type` option (#408)
* Terminator terminal font detection (@Zerogiven, #415)
* Windows 32bit compatibility
* Support global configuration in MSYS2 environment (Windows)
* Support GPU driver version detection on Windows 11
* Support scaled resolution detection for wayland (Linux)
Bugfixes:
* Fix build with older libnm versions
* Fix a rare case that fails to detect terminal
* Fix Muffin detection (@Zerogiven, #411)
* Fix IPv6 detection (Windows)
* Fix scoop package count detection when scoop is installed in non-default path (Windows, #417)
* Fix UB reported by clang
* Honor $SCOOP when detecting scoop packages (#417)
Other:
* Simplified wmtheme output format (Windows)
* Improved GPU detection performance on Windows 11
* Lastest Mac model identifier support (macOS)
# 1.9.1
Bugfixes:
* Fix builds on s390x (@jonathanspw, #402)
* Fix zero refresh rate on some monitors (macOS)
* Fix default formatting of Wifi module
# 1.9.0
Notable Changes:
* fastfetch no longer creates a sample config file silently. Use `--gen-config` to generate one.
* fastfetch now search for user config file in the order of `fastfetch --list-config-paths`
* Unknown disks are hidden by default.
* `Resolution` module is renamed to `Display`. (#393)
Features:
* `--logo-padding-top` option (@CarterLi, #372)
* Raw image file as logo support (@CarterLi)
* Look for config files in `$APPDATA` ([RoamingAppData](https://superuser.com/questions/21458/why-are-there-directories-called-local-locallow-and-roaming-under-users-user#answer-21462)) (Windows)
* Look for config files in `~/Library/Preferences` (macOS)
* Add `--list-config-paths` option which list search paths of config files
* Add `--list-data-paths` option which list search paths for presets and logos
* Add `Brightness` module support
* Add `Battery` module support for FreeBSD
* Add `--disk-show-unknown` option for Disk module
* Add `--disk-show-subvolumes` option for Disk module
* Add `--gpu-hide-integrated` option (#379)
* Add `--gpu-hide-discrete` option (#379)
* Detect terminal version when available
* Support `WezTerm` terminal font detection (requires [`wezterm` executable](https://wezfurlong.org/wezterm/cli/general.html) being available)
* Add `--shell-version` and `--terminal-version` options to disable shell / terminal version detection
* Enhance `--percent-type` to allow hiding other texts (#387)
* Add Wifi module support for Linux
* Detect scaled resolutions (Windows, macOS)
* Optimise font module printing (Windows)
* Detect pacman package count inside MSYS2 environment (Windows)
* Add Wifi / Battery module support for Android
* Disk name support for Linux
Logos:
* Raspbian (@IamNoRobot, #373)
Bugfixes:
* `--logo-type` now does accept `iterm` too (@CarterLi, #374)
* Fix mintty terminal font detection (Windows)
* Fix bug that line buffering doesn't work properly (Windows)
* Fix rpm package count detection (Linux)
* Fix cpu temp detection (Linux)
Other:
* Fixed a Typo in iterm error message (@jessebot, #376)
* Don't try to load config file in `/etc` (Windows)
# 1.8.2
Bugfixes:
@@ -112,7 +293,7 @@ Bugfixes:
* Don't segfault in GPU code on Intel Macs (@CarterLi, #236)
* Don't use hardcoded size units in presets (@dr460nf1r3, #255)
* Don't crash with some format strings (#252)
* --logo-none keeps key color now (#264)
* --logo none keeps key color now (#264)
# 1.7.2
+118 -40
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 1.8.2
VERSION 1.11.3
LANGUAGES C
DESCRIPTION "Fast system information tool"
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
@@ -57,7 +57,7 @@ cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD OR APPLE" OFF)
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE" OFF)
@@ -67,12 +67,12 @@ cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF)
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF)
cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND AND NOT ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR WIN32" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
cmake_dependent_option(ENABLE_BUFFER "Enable stdout buffer" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
cmake_dependent_option(USE_WIN_NTAPI "Allow using internal NTAPI" ON "WIN32" OFF)
cmake_dependent_option(USE_WIN_GPU_DXGI "Use DXGI to detect GPUs instead of WMI. Faster, but may ignore GPUs that only support DX9" ON "WIN32" OFF)
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
@@ -102,6 +102,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
if(WIN32)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -fno-exceptions -fno-rtti")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1")
endif()
# Used for dlopen finding dylibs installed by homebrew
@@ -115,7 +116,11 @@ if(NOT WIN32)
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
endif()
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
include(CheckIPOSupported)
@@ -159,6 +164,8 @@ if(NOT TARGET_DIR_ETC)
set(TARGET_DIR_ETC "${TARGET_DIR_ROOT}/etc")
endif()
message(STATUS "Target dirs: ROOT=\"${TARGET_DIR_ROOT}\" USR=\"${TARGET_DIR_USR}\" HOME=\"${TARGET_DIR_HOME}\" ETC=\"${TARGET_DIR_ETC}\"")
#https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT.html
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${TARGET_DIR_USR}" CACHE PATH "..." FORCE)
@@ -224,15 +231,15 @@ set(LIBFASTFETCH_SRC
src/common/font.c
src/common/format.c
src/common/init.c
src/common/io.c
src/common/library.c
src/common/parsing.c
src/common/printing.c
src/common/properties.c
src/common/settings.c
src/detection/bluetooth/bluetooth.c
src/detection/cpu/cpu.c
src/detection/cpuUsage/cpuUsage.c
src/detection/datetime.c
src/detection/datetime/datetime.c
src/detection/disk/disk.c
src/detection/displayserver/displayserver.c
src/detection/font/font.c
@@ -240,12 +247,12 @@ set(LIBFASTFETCH_SRC
src/detection/host/host.c
src/detection/locale/locale.c
src/detection/media/media.c
src/detection/opencl/opencl.c
src/detection/os/os.c
src/detection/packages/packages.c
src/detection/terminalfont/terminalfont.c
src/detection/terminalshell/terminalshell.c
src/detection/title.c
src/detection/vulkan.c
src/detection/vulkan/vulkan.c
src/logo/builtin.c
src/logo/image/im6.c
src/logo/image/im7.c
@@ -253,7 +260,9 @@ set(LIBFASTFETCH_SRC
src/logo/logo.c
src/modules/battery.c
src/modules/bios.c
src/modules/bluetooth.c
src/modules/board.c
src/modules/brightness.c
src/modules/break.c
src/modules/chassis.c
src/modules/colors.c
@@ -261,6 +270,7 @@ set(LIBFASTFETCH_SRC
src/modules/cpuUsage.c
src/modules/cursor.c
src/modules/custom.c
src/modules/command.c
src/modules/date.c
src/modules/datetime.c
src/modules/de.c
@@ -269,6 +279,7 @@ set(LIBFASTFETCH_SRC
src/modules/gpu.c
src/modules/host.c
src/modules/icons.c
src/modules/gamepad.c
src/modules/kernel.c
src/modules/locale.c
src/modules/localip.c
@@ -281,9 +292,11 @@ set(LIBFASTFETCH_SRC
src/modules/poweradapter.c
src/modules/processes.c
src/modules/publicip.c
src/modules/resolution.c
src/modules/display.c
src/modules/separator.c
src/modules/shell.c
src/modules/sound.c
src/modules/swap.c
src/modules/media.c
src/modules/terminal.c
src/modules/terminalfont.c
@@ -293,6 +306,7 @@ set(LIBFASTFETCH_SRC
src/modules/uptime.c
src/modules/users.c
src/modules/vulkan.c
src/modules/wallpaper.c
src/modules/weather.c
src/modules/wifi.c
src/modules/wm.c
@@ -300,19 +314,25 @@ set(LIBFASTFETCH_SRC
src/util/FFlist.c
src/util/FFstrbuf.c
src/util/FFvaluestore.c
src/util/platform/FFPlatform.c
src/util/stringUtils.c
)
if(LINUX)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_linux.c
src/detection/bios/bios_linux.c
src/detection/board/board_linux.c
src/detection/brightness/brightness_linux.c
src/detection/chassis/chassis_linux.c
src/detection/cpu/cpu_linux.c
src/detection/cpuUsage/cpuUsage_linux.c
src/detection/cursor/cursor_linux.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/disk/disk_linux.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
@@ -321,9 +341,11 @@ if(LINUX)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gtk.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_linux.c
src/detection/icons/icons_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_linux.c
src/detection/media/media_linux.c
src/detection/memory/memory_linux.c
src/detection/opengl/opengl_linux.c
@@ -331,23 +353,30 @@ if(LINUX)
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_linux.c
src/detection/qt.c
src/detection/gtk_qt/qt.c
src/detection/sound/sound_linux.c
src/detection/swap/swap_linux.c
src/detection/temps/temps_linux.c
src/detection/terminalfont/terminalfont_linux.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/theme/theme_linux.c
src/detection/uptime/uptime_linux.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/util/platform/FFPlatform_unix.c
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_unix.c
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_nosupport.c
src/detection/battery/battery_android.c
src/detection/bios/bios_nosupport.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/board/board_nosupport.c
src/detection/brightness/brightness_nosupport.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_linux.c
src/detection/cursor/cursor_nosupport.c
@@ -357,7 +386,9 @@ elseif(ANDROID)
src/detection/font/font_nosupport.c
src/detection/gpu/gpu_nosupport.c
src/detection/host/host_android.c
src/detection/icons/icons_nosupport.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_nosupport.c
src/detection/media/media_nosupport.c
src/detection/memory/memory_linux.c
src/detection/opengl/opengl_linux.c
@@ -365,23 +396,31 @@ elseif(ANDROID)
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_linux.c
src/detection/sound/sound_nosupport.c
src/detection/swap/swap_linux.c
src/detection/temps/temps_linux.c
src/detection/terminalfont/terminalfont_android.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/theme/theme_nosupport.c
src/detection/uptime/uptime_linux.c
src/detection/users/users_linux.c
src/detection/wifi/wifi_nosupport.c
src/detection/wallpaper/wallpaper_nosupport.c
src/detection/wifi/wifi_android.c
src/detection/wmtheme/wmtheme_nosupport.c
src/util/platform/FFPlatform_unix.c
)
elseif(BSD)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_nosupport.c
src/detection/battery/battery_bsd.c
src/detection/bios/bios_bsd.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/board/board_nosupport.c
src/detection/brightness/brightness_nosupport.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_bsd.c
src/detection/cpuUsage/cpuUsage_bsd.c
@@ -394,9 +433,11 @@ elseif(BSD)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gtk.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_bsd.c
src/detection/icons/icons_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_nosupport.c
src/detection/media/media_linux.c
src/detection/memory/memory_bsd.c
src/detection/opengl/opengl_linux.c
@@ -404,35 +445,44 @@ elseif(BSD)
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_bsd.c
src/detection/qt.c
src/detection/gtk_qt/qt.c
src/detection/sound/sound_linux.c
src/detection/swap/swap_bsd.c
src/detection/temps/temps_linux.c
src/detection/terminalfont/terminalfont_linux.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/theme/theme_linux.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_nosupport.c
src/detection/wmtheme/wmtheme_linux.c
src/util/platform/FFPlatform_unix.c
)
elseif(APPLE)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_unix.c
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_apple.c
src/detection/bios/bios_apple.c
src/detection/bluetooth/bluetooth_apple.m
src/detection/board/board_nosupport.c
src/detection/brightness/brightness_apple.c
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_apple.c
src/detection/cpuUsage/cpuUsage_apple.c
src/detection/cursor/cursor_nosupport.c
src/detection/cursor/cursor_apple.m
src/detection/disk/disk_apple.m
src/detection/disk/disk_bsd.c
src/detection/displayserver/displayserver_apple.c
src/detection/font/font_apple.m
src/detection/gpu/gpu_apple.c
src/detection/host/host_apple.c
src/detection/icons/icons_nosupport.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_apple.c
src/detection/media/media_apple.m
src/detection/memory/memory_apple.c
src/detection/opengl/opengl_apple.c
@@ -440,24 +490,31 @@ elseif(APPLE)
src/detection/packages/packages_apple.c
src/detection/poweradapter/poweradapter_apple.c
src/detection/processes/processes_bsd.c
src/detection/sound/sound_apple.c
src/detection/swap/swap_apple.c
src/detection/temps/temps_apple.c
src/detection/terminalfont/terminalfont_apple.m
src/detection/terminalshell/terminalshell_linux.c
src/detection/theme/theme_nosupport.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_apple.c
src/detection/wifi/wifi_apple.m
src/detection/wmtheme/wmtheme_apple.m
src/util/apple/cf_helpers.c
src/util/apple/osascript.m
src/util/platform/FFPlatform_unix.c
)
elseif(WIN32)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_windows.c
src/common/networking_windows.c
src/common/processing_windows.c
src/detection/battery/battery_windows.c
src/detection/bios/bios_windows.c
src/detection/bluetooth/bluetooth_windows.c
src/detection/board/board_windows.c
src/detection/brightness/brightness_windows.cpp
src/detection/chassis/chassis_nosupport.c
src/detection/cpu/cpu_windows.c
src/detection/cpuUsage/cpuUsage_windows.c
@@ -465,29 +522,35 @@ elseif(WIN32)
src/detection/disk/disk_windows.c
src/detection/displayserver/displayserver_windows.c
src/detection/font/font_windows.c
src/detection/gpu/gpu_windows.cpp
src/detection/gpu/gpu_windows.c
src/detection/host/host_windows.c
src/detection/icons/icons_windows.c
src/detection/localip/localip_windows.c
src/detection/gamepad/gamepad_windows.c
src/detection/media/media_nosupport.c
src/detection/memory/memory_windows.c
src/detection/opengl/opengl_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.cpp
src/detection/swap/swap_windows.cpp
src/detection/processes/processes_windows.c
src/detection/sound/sound_windows.cpp
src/detection/swap/swap_windows.c
src/detection/terminalfont/terminalfont_windows.c
src/detection/terminalshell/terminalshell_windows.cpp
src/detection/terminalshell/terminalshell_windows.c
src/detection/temps/temps_windows.cpp
src/detection/theme/theme_nosupport.c
src/detection/uptime/uptime_windows.c
src/detection/users/users_windows.c
src/detection/wallpaper/wallpaper_windows.c
src/detection/wifi/wifi_windows.c
src/detection/wmtheme/wmtheme_windows.c
src/util/windows/getline.c
src/util/windows/pwd.c
src/util/windows/com.cpp
src/util/windows/registry.c
src/util/windows/unicode.c
src/util/windows/utsname.c
src/util/windows/wmi.cpp
src/util/platform/FFPlatform_windows.c
)
endif()
@@ -496,6 +559,9 @@ add_library(libfastfetch OBJECT
)
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
if(WIN32)
target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1)
endif()
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX_H)
if(HAVE_UTMPX_H)
@@ -622,14 +688,22 @@ ff_lib_enable(OPENCL
"OpenCL"
"OpenCL"
)
ff_lib_enable(LIBCJSON
"libcjson"
"CJson"
ff_lib_enable(LIBNM
"libnm"
"libnm"
)
ff_lib_enable(FREETYPE
"freetype2"
"FreeType2"
)
ff_lib_enable(PULSE
"libpulse"
"Pulse"
)
ff_lib_enable(LIBCJSON
"libcjson"
"CJson"
)
if(ENABLE_THREADS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
@@ -638,45 +712,44 @@ if(ENABLE_THREADS)
endif()
endif()
if(ENABLE_BUFFER)
target_compile_definitions(libfastfetch PRIVATE FF_ENABLE_BUFFER)
endif()
if(APPLE)
target_link_libraries(libfastfetch
PRIVATE "-framework Cocoa"
PRIVATE "-framework CoreFoundation"
PRIVATE "-framework CoreAudio"
PRIVATE "-framework CoreVideo"
PRIVATE "-framework CoreWLAN"
PRIVATE "-framework IOBluetooth"
PRIVATE "-framework IOKit"
PRIVATE "-framework OpenGL"
PRIVATE "-framework OpenCL"
PRIVATE "-framework Cocoa"
PRIVATE "-framework CoreWLAN"
PRIVATE "-framework SystemConfiguration"
PRIVATE "-weak_framework CoreDisplay"
PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks"
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
)
elseif(WIN32)
target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601)
target_link_libraries(libfastfetch
PRIVATE "bthprops"
PRIVATE "dwmapi"
PRIVATE "gdi32"
PRIVATE "iphlpapi"
PRIVATE "ole32"
PRIVATE "oleaut32"
PRIVATE "opengl32"
PRIVATE "wbemuuid"
PRIVATE "ws2_32"
PRIVATE "ntdll"
PRIVATE "version"
PRIVATE "setupapi"
PRIVATE "dxgi"
PRIVATE "hid"
PRIVATE "wtsapi32"
PRIVATE "powrprof"
)
if(USE_WIN_NTAPI)
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_NTAPI)
endif()
if(USE_WIN_GPU_DXGI)
target_compile_definitions(libfastfetch PRIVATE FF_USE_WIN_GPU_DXGI)
endif()
endif()
target_include_directories(libfastfetch
@@ -712,6 +785,11 @@ target_link_libraries(flashfetch
PRIVATE libfastfetch
)
if(ENABLE_BUFFER) # FF_ENABLE_BUFFER is used in fastfetch.c
target_compile_definitions(fastfetch PRIVATE FF_ENABLE_BUFFER)
target_compile_definitions(flashfetch PRIVATE FF_ENABLE_BUFFER)
endif()
if(WIN32)
set(TARGET_NAME fastfetch)
target_sources(fastfetch
+25 -23
View File
@@ -1,6 +1,6 @@
# Fastfetch
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
<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" />
@@ -10,17 +10,21 @@ Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for
<img src="screenshots/example3.png" width="48%" align="top" />
<img src="screenshots/example5.png" height="15%" align="top" />
There are [screenshots on different platforms](https://github.com/LinusDierheimer/fastfetch/wiki)
## Customization
With customization and speed being two competing goals, this project actually builds two executables.
* The main one being `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent in `~/.config/fastfetch/config.conf`. To view the available options run `fastfetch --help`.
* The main one being `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent in `$XDG_CONFIG_HOME/fastfetch/config.conf`. To view the available options run `fastfetch --help`.
* The second executable being built is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c).
At the moment the performance difference is measurable, but too small to be human recognizable. But the leap will get bigger with more and more options coming, and on slow machines this might actually make a difference.
There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config <filename>`. They may also serve as a good example for format arguments.
Logos can be heavily customized to. See the [logo documentation](doc/logo.md) for more information.
## Dependencies
Fastfetch dynamically loads needed libraries if they are available. On Linux, its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html) (if built with multithreading support). They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions.
@@ -34,14 +38,14 @@ The following libraries are used if present at runtime:
* [`libxcb-randr`](https://xcb.freedesktop.org/),
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
[`libxcb`](https://xcb.freedesktop.org/),
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better resolution detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better display detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
* [`libwayland-client`](https://wayland.freedesktop.org/): Better display performance and output in wayland sessions. Supports different refresh rates per monitor.
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Needed for detecting current media player and song.
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Bluetooth, Player & Media detection.
* [`libEGL`](https://www.khronos.org/registry/EGL/),
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
@@ -50,13 +54,17 @@ The following libraries are used if present at runtime:
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection.
* [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection.
### macOS
* [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system.
* [`DisplayServices`](https://developer.apple.com/forums/thread/666383#663154022): Need for screen brightness detection. It's a private framework provided by newer macOS system.
* [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb)
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb)
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb)
* [`libsqlite3`](https://www.sqlite.org/index.html): Used for fast wallpaper detection ( fallback to AppleScript )
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
@@ -67,10 +75,7 @@ For the image logo, iTerm with iterm image protocol should work. Apple Terminal
* [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. [`vulkan-loader`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-loader) [`vulkan-headers`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-headers)
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module. [`opencl-icd`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-opencl-icd)
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, special build `fastfetch-win7` is provided to support these old systems, which
1. Build with the ancient [MSVCRT](https://en.wikipedia.org/wiki/Microsoft_Windows_library_files#MSVCRT.DLL,_MSVCP*.DLL_and_CRTDLL.DLL) C runtime library, instead of the modern [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library
2. Disable stdout application buffer, which seems to problematic for ConEmu.
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later.
For the image logo, only chafa is supported due to [the design flaw of ConPTY](https://github.com/microsoft/terminal/issues/1173). In addition, chafa support is not built by default due to the massive dependencies of imagemagick. You must built it yourself.
@@ -78,43 +83,39 @@ For the image logo, only chafa is supported due to [the design flaw of ConPTY](h
* [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype)
* [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers)
* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api)
## Support status
All categories not listed here should work without needing a specific implementation.
##### Available Modules
```
Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, Wifi, DateTime, Date, Time, Locale, Colors, Break, Custom
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wallpaper, Wifi, WM, WMTheme
```
##### Logos
##### Builtin logos
```
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Devuan, Deepin, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Parabola, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, Ubuntu, Vanilla, Void, Windows 11, Windows 8, Windows, Zorin
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, CRUX, Crystal, Debian, Deepin, Devuan, Endeavour, Enso, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, Nobara, OpenSUSE, OpenSUSE LEAP, OpenSUSE Tumbleweed, Parabola, Pop!_OS, Raspbian, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Solus, SteamOS, Ubuntu, Vanilla, Void, Windows, Windows 11, Windows 8, Zorin
```
* Most of the logos have a small variant. Access it by appending _small to the logo name.
* Some logos have an old variant. Access it by appending _old to the logo name.
* To disable the logo, use `--logo none`.
* Get a list of all available logos with `fastfetch --print-logos`.
* Printing images as logo is supported using Sixel / Kitty / iTerm graphics protocol or chafas image to text conversion.
##### Package managers
```
Pacman, dpkg, rpm, emerge, eopkg, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop, Chocolatey
apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, pkg, rpm, scoop, Snap, xbps
```
##### WM themes
```
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), DWM (Windows)
DWM (Windows), KWin, Marco, Muffin, Mutter, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), XFWM
```
##### DE versions
```
KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4
```
##### Terminal fonts
```
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, Kitty, LXTerminal, Deepin Terminal, iTerm2, Apple Terminal, Warp, TTY, Windows Terminal, Termux, mintty, ConEmu
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal
```
## Building
@@ -134,12 +135,13 @@ If the build process fails to find the headers for a library listed in [dependen
Currently GCC or clang is required (MSVC is not supported). MSYS2 with CLANG64 subsystem (or CLANGARM64 if needed) is suggested (and tested) to build fastfetch. If you need Windows 7 / 8.x support, using MINGW64 is suggested.
1. Install [MSYS2](https://www.msys2.org/#installation)
1. Open `MSYS2 CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime)
1. Open `MSYS2 / CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime)
1. Install dependencies
```bash
pacman -Syu mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-cjson mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
```
1. Follow building instructions of Linux
Follow the building instructions of Linux next.
## Packaging
+35 -14
View File
@@ -13,7 +13,7 @@ __fastfetch_complete_help()
"processes-format"
"packages-format"
"shell-format"
"resolution-format"
"display-format"
"de-format"
"wm-format"
"wm-theme-format"
@@ -32,8 +32,8 @@ __fastfetch_complete_help()
"battery-format"
"poweradapter-format"
"locale-format"
"local-ip-format"
"public-ip-format"
"localip-format"
"publicip-format"
"player-format"
"media-format"
"datetime-format"
@@ -42,6 +42,7 @@ __fastfetch_complete_help()
"vulkan-format"
"opengl-format"
"opencl-format"
"bluetooth-format"
)
COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD"))
}
@@ -160,6 +161,8 @@ __fastfetch_completion()
"--print-config-system"
"--print-config-user"
"--print-structure"
"--gen-config"
"--gen-config-force"
)
local FF_OPTIONS_HELP=(
@@ -179,16 +182,28 @@ __fastfetch_completion()
"--cpu-temp"
"--gpu-temp"
"--battery-temp"
"--display-detect-name"
"--display-precise-refresh-rate"
"--localip-show-ipv4"
"--localip-show-ipv6"
"--localip-show-loop"
"--localip-name-prefix"
"--localip-compact-type"
"--escape-bedrock"
"--pipe"
"--title-fqdn"
"--escape-bedrock"
"--shell-version"
"--terminal-version"
"--disk-folders"
"--disk-show-removable"
"--disk-show-hidden"
"--disk-show-subvolumes"
"--gpu-hide-integrated"
"--gpu-hide-discrete"
"--gpu-force-vulkan"
"--disk-show-unknown"
"--bluetooth-show-disconnected"
)
local FF_OPTIONS_STRING=(
@@ -196,6 +211,7 @@ __fastfetch_completion()
"--logo-padding"
"--logo-padding-left"
"--logo-padding-right"
"--logo-padding-top"
"--logo-color-1"
"--logo-color-2"
"--logo-color-3"
@@ -211,6 +227,7 @@ __fastfetch_completion()
"--color"
"--color-keys"
"--color-title"
"--display-compact-type"
"--separator"
"-s"
"--structure"
@@ -218,8 +235,8 @@ __fastfetch_completion()
"--set-keyless"
"--player-name"
"--percent-type"
"--public-ip-url"
"--public-ip-timeout"
"--publicip-url"
"--publicip-timeout"
"--weather-output-format"
"--weather-timeout"
"--os-key"
@@ -243,9 +260,9 @@ __fastfetch_completion()
"--shell-key"
"--shell-format"
"--shell-error"
"--resolution-key"
"--resolution-format"
"--resolution-error"
"--display-key"
"--display-format"
"--display-error"
"--de-key"
"--de-format"
"--de-error"
@@ -300,12 +317,12 @@ __fastfetch_completion()
"--locale-key"
"--locale-format"
"--locale-error"
"--local-ip-key"
"--local-ip-format"
"--local-ip-error"
"--public-ip-key"
"--public-ip-format"
"--public-ip-error"
"--localip-key"
"--localip-format"
"--localip-error"
"--publicip-key"
"--publicip-format"
"--publicip-error"
"--wifi-key"
"--wifi-format"
"--wifi-error"
@@ -339,6 +356,9 @@ __fastfetch_completion()
"--users-key"
"--users-format"
"--users-error"
"--bluetooth-key"
"--bluetooth-format"
"--bluetooth-error"
)
local FF_OPTIONS_PATH=(
@@ -364,6 +384,7 @@ __fastfetch_completion()
"--lib-glx"
"--lib-osmesa"
"--lib-opencl"
"--lib-pulse"
"--battery-dir"
)
+116
View File
@@ -0,0 +1,116 @@
# Logo options
## General
| Option | Default | Description |
|--------|---------|-------------|
| `--logo`, `-l` | `""` | The logo source, interpreted depending on type |
| `--logo-type` | `auto` | The logo type. See the following categories for possible values |
| `--<type>` | `""` | Short for `--logo-type <type> --logo <value>` |
| `--logo-padding` | `""` | Sets the padding left and right of the logo |
| `--logo-padding-left` | `0` | Sets the padding left of the logo |
| `--logo-padding-right` | `4` | Sets the padding right of the logo |
| `--logo-padding-top` | `0` | Sets the padding top of the logo |
All filesytem paths can be:
* Absolute
* Relative to the current working directory
* Relative to any of the directories listed by `fastfetch --list-data-paths` + `/logos`
For example, the file `~/.local/share/fastfetch/logos/shrek` can simply be referenced as `shrek`.
## Text
| Option | Default | Description |
|--------|---------|-------------|
| `--logo-color-[1-9]` | `""` | Overrides a color for logos that support it |
| `--logo-print-remaining` | `true` | Print the remaining logo, if it is higher than the keys |
* Color placeholders are in the form `$[1-9]`. To print a `$`, use `$$`.
* If a color placeholder value is not set, the placeholder is simply discarded.
## Image
| Option | Default | Description |
|--------|---------|-------------|
| `--logo-width` | `""` | Sets the width of the logo for logos that support it |
| `--logo-height` | `""` | Sets the height of the logo for logos that support it |
* If one of the height / width options is set, but the other not, the aspect ratio is preserved.
* If neither height nor width is set, the original size is used.
# Logo types
## auto
Trys to detect the logo type depending on the value of `--logo`, in the following order:
* If the value is empty / not set, an autodected builtin logo is displayed.
* If the value is the name of a builtin logo, it is displayed.
* If the value is the path to an image file, and the terminal emulator is known to support an image protocol, the image is displayed.
* If the value is the path to a text file, the content is displayed.
* The autodetected builtin logo is displayed.
## builtin
The value of `--logo` is interpreted as the name of a builtin logo.
* If the value is empty / not set, it is autodetected.
* Use `--list-logos` to get a list of all available logos.
* Use `--print-logos` to see all available logos.
* All builtin logos set default values for `--logo-color-[1-9]`.
* Use `none` to disable the logo, but keep key colors from the detected logo.
## file
The value of `--logo` is interpreted as the path to a file. The content of the file is displayed.
* If the file can't be read, the autodetected builtin logo is displayed.
## file-raw
The value of `--logo` is interpreted as the path to a file. The content of the file is displayed.
* No color placeholder replacement is done.
* If the file can't be read, the autodetected builtin logo is displayed.
## data
The value of `--logo` is interpreted as the logo and directly displayed.
* If the value is empty / not set, the autodetected builtin logo is displayed.
## data-raw
The value of `--logo` is interpreted as the logo and directly displayed.
* No color placeholder replacement is done.
* If the value is empty / not set, the autodetected builtin logo is displayed.
## sixel
The value of `--logo` is interpreted as the path to an image file. It is displayed using the sixel graphics protocol.
* `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature.
## kitty
The value of `--logo` is interpreted as the path to an image file. It is displayed using the kitty graphics protocol.
* If the file is a png file, and both `--logo-width` and `--logo-height` are specified, the image is directly send to the terminal emulator.
* Otherwise `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature.
## iterm
The value of `--logo` is interpreted as the path to an image file. It is displayed using the iTerm graphics protocol.
* Both `--logo-width` and `--logo-height` must be specified.
## chafa
The value of `--logo` is interpreted as the path to an image file. It is converted to an ascii logo using `libchafa`.
* `fastfetch` must be compiled with the `chafa` feature.
* `fastfetch` must be compiled with the `imagemagick6` or `imagemagick7` feature.
* Use `--chafa-fg-only` to set weather to render foreground only.
* Use `--chafa-symbols` to set the symbols.
* Use `--chafa-canvas-mode` to set the canvas mode.
* Use `--chafa-color-space` to set the color space.
* Use `--chafa-dither-mode` to set the dither mode.
* See the [chafa documentation](https://hpjansson.org/chafa/man/) for more information.
## raw
The value of `--logo` is interpreted as the path to a binary file. It is printed as-is.
* Both `--logo-width` and `--logo-height` must be specified.
* Use this to display a pre converted image file.
* If the file can't be read, the autodetected builtin logo is displayed.
+1 -1
View File
@@ -1 +1 @@
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Break:Colors
+1 -1
View File
@@ -1,4 +1,4 @@
--structure Host:Resolution:CPU:GPU:Memory:Disk:Battery
--structure Host:Display:CPU:GPU:Memory:Disk:Battery
--memory-format "{?2}{2}{?}"
--disk-format "{?2}{2}{?}"
--battery-format "{?1}{1} {?}{?2}{2} {?}{?3}({3}){?}"
+3 -3
View File
@@ -1,10 +1,10 @@
--structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors"
--structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors"
--host-format "{/2}{-}{/}{2}{?3} {3}{?}"
--os-format "{3} {12}"
--resolution-format "{}x{}"
--display-format "{}x{}"
--de-format "{2} {3}"
--theme-format "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}"
--terminal-font-format "{/2}{-}{/}{2}{?3} {3}{?}"
--memory-format "{/1}{-}{/}{/2}{-}{/}{} / {}"
--gpu-key "GPU"
--resolution-key "Resolution"
--display-key "Display"
+2 -2
View File
@@ -1,5 +1,5 @@
--structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Resolution:Terminal:Break:CPU:GPU:Memory:Break:Colors
--structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Display:Terminal:Break:CPU:GPU:Memory:Break:Colors
--host-format "{/2}{-}{/}{2}{?3} {3}{?}"
--battery-format "{/4}{-}{/}{4}%{?5} [{5}]{?}"
--resolution-key "Resolution"
--display-key "Display"
--gpu-key "GPU"
+4 -3
View File
@@ -3,9 +3,9 @@
--kernel-format Sysname: {}; Release: {}; Version: {}
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
--processes-format Count: {}
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak-system: {}; flatpak-user: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}
--shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}
--resolution-format Width: {}; Height: {}; Refresh rate: {}
--display-format Width: {}; Height: {}; Refresh rate: {}; ScaledWith: {}; ScaledHeight: {}
--de-format Process name: {}; Pretty name: {}; Version: {}
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
--wm-theme-format Name: {}
@@ -17,7 +17,7 @@
--terminal-font-format Pretty: {}; Name: {}; Size: {}; Styles: {}
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
--cpu-usage-format Percentage: {}
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}; Type: {}
--memory-format Used: {}; Total: {}; Percentage: {}
--disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; Removable: {}; Hidden: {}; Filesystem: {}; Name: {}
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
@@ -28,3 +28,4 @@
--vulkan-format driver: {}; Api Version: {}; Conformance Version: {}
--opengl-format version: {}; renderer: {}; vendor: {}
--opencl-format version: {}; device: {}; vendor: {}
--bluetooth-format Name: {}; Address: {}; Type: {}; Battery: {}
+50
View File
@@ -47,3 +47,53 @@ void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent,
else
ffStrbufAppendS(buffer, " ]");
}
// if (green < yellow)
// [0, green]: print green
// (green, yellow]: print yellow
// (yellow, 100]: print red
//
// if (green > yellow)
// [green, 100]: print green
// [yellow, green): print yellow
// [0, yellow): PRINT RED
void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses)
{
assert(green <= 100 && yellow <= 100);
bool colored = !!(instance->config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
if (parentheses)
ffStrbufAppendC(buffer, '(');
if (colored && !instance->config.pipe)
{
if(green < yellow)
{
if (percent <= green)
ffStrbufAppendS(buffer, "\033[32m");
else if (percent <= yellow)
ffStrbufAppendS(buffer, "\033[93m");
else
ffStrbufAppendS(buffer, "\033[91m");
}
else
{
if (percent >= green)
ffStrbufAppendS(buffer, "\033[32m");
else if (percent >= yellow)
ffStrbufAppendS(buffer, "\033[93m");
else
ffStrbufAppendS(buffer, "\033[91m");
}
}
ffStrbufAppendF(buffer, "%u%%", (unsigned) percent);
if (colored && !instance->config.pipe)
{
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
if (parentheses)
ffStrbufAppendC(buffer, ')');
}
+5 -2
View File
@@ -7,10 +7,13 @@
enum
{
FF_PERCENTAGE_TYPE_NUM_BIT = 1,
FF_PERCENTAGE_TYPE_BAR_BIT = 2,
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
};
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
void ffAppendPercentNum(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses);
#endif
+206
View File
@@ -0,0 +1,206 @@
#include "dbus.h"
#ifdef FF_HAVE_DBUS
#include "common/thread.h"
#include "util/stringUtils.h"
static bool loadLibSymbols(const FFinstance* instance, FFDBusLibrary* lib)
{
FF_LIBRARY_LOAD(dbus, &instance->config.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_has_next, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false)
dbus = NULL; // don't auto dlclose
return true;
}
static const FFDBusLibrary* loadLib(const FFinstance* instance)
{
static FFDBusLibrary lib;
static bool loaded = false;
static bool loadSuccess = false;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
ffThreadMutexLock(&mutex);
if(!loaded)
{
loaded = true;
loadSuccess = loadLibSymbols(instance, &lib);
}
ffThreadMutexUnlock(&mutex);
return loadSuccess ? &lib : NULL;
}
const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data)
{
data->lib = loadLib(instance);
if(data->lib == NULL)
return "Failed to load DBus library";
data->connection = data->lib->ffdbus_bus_get(busType, NULL);
if(data->connection == NULL)
return "Failed to connect to DBus";
return NULL;
}
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
{
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_STRING)
{
const char* value = NULL;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
if(!ffStrSet(value))
return false;
ffStrbufAppendS(result, value);
return true;
}
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
return false;
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
if(argType == DBUS_TYPE_VARIANT)
return ffDBusGetValue(dbus, &subIter, result);
//At this point we have an array
bool foundAValue = false;
while(true)
{
if(ffDBusGetValue(dbus, &subIter, result))
{
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
FF_DBUS_ITER_CONTINUE(dbus, &subIter);
}
if(foundAValue)
ffStrbufSubstrBefore(result, result->length - 2);
return foundAValue;
}
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result)
{
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_BOOLEAN)
{
dbus_bool_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value != 0;
return true;
}
if(argType != DBUS_TYPE_VARIANT)
return false;
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetBool(dbus, &subIter, result);
}
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result)
{
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_BYTE)
{
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 ffDBusGetByte(dbus, &subIter, result);
}
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method)
{
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
if(message == NULL)
return NULL;
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
dbus->lib->ffdbus_message_unref(message);
return reply;
}
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property)
{
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
if(message == NULL)
return NULL;
DBusMessageIter requestIterator;
dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator);
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
{
dbus->lib->ffdbus_message_unref(message);
return NULL;
}
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
{
dbus->lib->ffdbus_message_unref(message);
return NULL;
}
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
dbus->lib->ffdbus_message_unref(message);
return reply;
}
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result)
{
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
if(reply == NULL)
return;
DBusMessageIter rootIterator;
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
{
dbus->lib->ffdbus_message_unref(reply);
return;
}
ffDBusGetValue(dbus, &rootIterator, result);
dbus->lib->ffdbus_message_unref(reply);
}
#endif //FF_HAVE_DBUS
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#ifndef FF_INCLUDED_common_dbus
#define FF_INCLUDED_common_dbus
#ifdef FF_HAVE_DBUS
#include <dbus/dbus.h>
#include "util/FFstrbuf.h"
#include "common/library.h"
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \
{ \
if(!(dbus)->lib->ffdbus_message_iter_has_next(iterator)) \
break; \
(dbus)->lib->ffdbus_message_iter_next(iterator); \
continue; \
}
typedef struct FFDBusLibrary
{
FF_LIBRARY_SYMBOL(dbus_bus_get)
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
FF_LIBRARY_SYMBOL(dbus_message_iter_init)
FF_LIBRARY_SYMBOL(dbus_message_iter_init_append)
FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic)
FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type)
FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic)
FF_LIBRARY_SYMBOL(dbus_message_iter_recurse)
FF_LIBRARY_SYMBOL(dbus_message_iter_has_next)
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
FF_LIBRARY_SYMBOL(dbus_message_unref)
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block)
FF_LIBRARY_SYMBOL(dbus_connection_flush)
FF_LIBRARY_SYMBOL(dbus_pending_call_block)
FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply)
FF_LIBRARY_SYMBOL(dbus_pending_call_unref)
} FFDBusLibrary;
typedef struct FFDBusData
{
const FFDBusLibrary* lib;
DBusConnection* connection;
} FFDBusData;
const char* ffDBusLoadData(const FFinstance* instance, DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result);
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method);
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
void ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
#endif // FF_HAVE_DBUS
#endif // FF_INCLUDED_common_dbus
+3
View File
@@ -2,6 +2,7 @@
#include "common/format.h"
#include "common/parsing.h"
#include "util/textModifier.h"
#include "util/stringUtils.h"
#include <inttypes.h>
@@ -19,6 +20,8 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
ffStrbufAppendS(buffer, (const char*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRBUF)
ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_FLOAT)
ffStrbufAppendF(buffer, "%f", *(float*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_DOUBLE)
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_BOOL)
+1
View File
@@ -12,6 +12,7 @@ typedef enum FFformatargtype
FF_FORMAT_ARG_TYPE_INT,
FF_FORMAT_ARG_TYPE_STRING,
FF_FORMAT_ARG_TYPE_STRBUF,
FF_FORMAT_ARG_TYPE_FLOAT,
FF_FORMAT_ARG_TYPE_DOUBLE,
FF_FORMAT_ARG_TYPE_LIST,
FF_FORMAT_ARG_TYPE_BOOL
+89 -126
View File
@@ -1,8 +1,6 @@
#include "fastfetch.h"
#include "common/parsing.h"
#include "common/thread.h"
#include "detection/qt.h"
#include "detection/gtk.h"
#include "detection/displayserver/displayserver.h"
#include "util/textModifier.h"
@@ -10,109 +8,20 @@
#include <unistd.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <wincon.h>
#include <windows.h>
#include <locale.h>
#include "util/windows/unicode.h"
#else
#include <signal.h>
#endif
static void initConfigDirs(FFstate* state)
{
ffListInit(&state->configDirs, sizeof(FFstrbuf));
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__))
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
if(ffStrSet(xdgConfigHome))
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigHome);
ffStrbufEnsureEndsWithC(buffer, '/');
}
#endif
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
if(ffListFirstIndexComp(&state->configDirs, element, (bool(*)(const void*, const void*))ffStrbufEqual) < state->configDirs.length - 1) \
{ \
ffStrbufDestroy(ffListGet(&state->configDirs, state->configDirs.length - 1)); \
--state->configDirs.length; \
}
FFstrbuf* userConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(userConfigHome, 64);
ffStrbufAppendS(userConfigHome, state->passwd->pw_dir);
ffStrbufAppendS(userConfigHome, "/.config/");
FF_ENSURE_ONLY_ONCE_IN_LIST(userConfigHome)
FFstrbuf* userHome = ffListAdd(&state->configDirs);
ffStrbufInitA(userHome, 64);
ffStrbufAppendS(userHome, state->passwd->pw_dir);
ffStrbufEnsureEndsWithC(userHome, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(userHome)
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__ANDROID__))
FFstrbuf xdgConfigDirs;
ffStrbufInitA(&xdgConfigDirs, 64);
ffStrbufAppendS(&xdgConfigDirs, getenv("XDG_CONFIG_DIRS"));
uint32_t startIndex = 0;
while (startIndex < xdgConfigDirs.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&xdgConfigDirs, startIndex, ':');
xdgConfigDirs.chars[colonIndex] = '\0';
if(!ffStrSet(xdgConfigDirs.chars + startIndex))
{
startIndex = colonIndex + 1;
continue;
}
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigDirs.chars + startIndex);
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(buffer);
startIndex = colonIndex + 1;
}
ffStrbufDestroy(&xdgConfigDirs);
FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfigHome, 64);
ffStrbufAppendS(systemConfigHome, FASTFETCH_TARGET_DIR_ETC"/xdg/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigHome)
#endif
FFstrbuf* systemConfig = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfig, 64);
ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ETC"/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig)
#undef FF_ENSURE_ONLY_ONCE_IN_LIST
}
static void initState(FFstate* state)
{
#ifdef WIN32
//https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendations&view=msvc-170#utf-8-support
setlocale(LC_ALL, ".UTF8");
#endif
state->logoWidth = 0;
state->logoHeight = 0;
state->keysHeight = 0;
#ifndef WIN32
state->passwd = getpwuid(getuid());
#else
state->passwd = ffGetPasswd();
#endif
uname(&state->utsname);
initConfigDirs(state);
ffPlatformInit(&state->platform);
}
static void initModuleArg(FFModuleArgs* args)
@@ -130,6 +39,7 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInit(&instance->config.logo.colors[i]);
instance->config.logo.width = 0;
instance->config.logo.height = 0; //preserve aspect ratio
instance->config.logo.paddingTop = 0;
instance->config.logo.paddingLeft = 0;
instance->config.logo.paddingRight = 4;
instance->config.logo.printRemaining = true;
@@ -163,13 +73,14 @@ static void defaultConfig(FFinstance* instance)
initModuleArg(&instance->config.host);
initModuleArg(&instance->config.bios);
initModuleArg(&instance->config.board);
initModuleArg(&instance->config.brightness);
initModuleArg(&instance->config.chassis);
initModuleArg(&instance->config.kernel);
initModuleArg(&instance->config.uptime);
initModuleArg(&instance->config.processes);
initModuleArg(&instance->config.packages);
initModuleArg(&instance->config.shell);
initModuleArg(&instance->config.resolution);
initModuleArg(&instance->config.display);
initModuleArg(&instance->config.de);
initModuleArg(&instance->config.wm);
initModuleArg(&instance->config.wmTheme);
@@ -198,9 +109,13 @@ static void defaultConfig(FFinstance* instance)
initModuleArg(&instance->config.date);
initModuleArg(&instance->config.time);
initModuleArg(&instance->config.vulkan);
initModuleArg(&instance->config.wallpaper);
initModuleArg(&instance->config.openGL);
initModuleArg(&instance->config.openCL);
initModuleArg(&instance->config.users);
initModuleArg(&instance->config.bluetooth);
initModuleArg(&instance->config.sound);
initModuleArg(&instance->config.gamepad);
ffStrbufInitA(&instance->config.libPCI, 0);
ffStrbufInitA(&instance->config.libVulkan, 0);
@@ -224,25 +139,39 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInitA(&instance->config.libOpenCL, 0);
ffStrbufInitA(&instance->config.libcJSON, 0);
ffStrbufInitA(&instance->config.libfreetype, 0);
ffStrbufInit(&instance->config.libPulse);
ffStrbufInit(&instance->config.libwlanapi);
ffStrbufInit(&instance->config.libnm);
instance->config.cpuTemp = false;
instance->config.gpuTemp = false;
instance->config.gpuForceVulkan = false;
instance->config.batteryTemp = false;
instance->config.gpuHideIntegrated = false;
instance->config.gpuHideDiscrete = false;
instance->config.shellVersion = true;
instance->config.terminalVersion = true;
instance->config.titleFQDN = false;
ffStrbufInitA(&instance->config.diskFolders, 0);
instance->config.diskShowRemovable = true;
instance->config.diskShowHidden = false;
instance->config.diskShowTypes = FF_DISK_TYPE_REGULAR_BIT | FF_DISK_TYPE_EXTERNAL_BIT;
instance->config.displayCompactType = FF_DISPLAY_COMPACT_TYPE_NONE;
instance->config.displayDetectName = false;
instance->config.displayPreciseRefreshRate = false;
instance->config.bluetoothShowDisconnected = false;
instance->config.soundType = FF_SOUND_TYPE_MAIN;
ffStrbufInitA(&instance->config.batteryDir, 0);
ffStrbufInitA(&instance->config.separatorString, 0);
instance->config.localIpShowIpV4 = true;
instance->config.localIpShowIpV6 = false;
instance->config.localIpShowLoop = false;
instance->config.localIpShowType = FF_LOCALIP_TYPE_IPV4_BIT;
ffStrbufInit(&instance->config.localIpNamePrefix);
instance->config.publicIpTimeout = 0;
@@ -256,48 +185,54 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInitA(&instance->config.playerName, 0);
instance->config.percentType = 1;
ffStrbufInitS(&instance->config.commandShell,
#ifdef _WIN32
"cmd"
#elif defined(__FreeBSD__)
"csh"
#else
"bash"
#endif
);
ffListInit(&instance->config.commandKeys, sizeof(FFstrbuf));
ffListInit(&instance->config.commandTexts, sizeof(FFstrbuf));
}
void ffInitInstance(FFinstance* instance)
{
#ifdef WIN32
//https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendations&view=msvc-170#utf-8-support
setlocale(LC_ALL, ".UTF8");
#endif
initState(&instance->state);
defaultConfig(instance);
}
#ifdef FF_HAVE_THREADS
#if defined(FF_HAVE_THREADS) && !(defined(__APPLE__) || defined(_WIN32) || defined(__ANDROID__))
#include "detection/gtk_qt/gtk_qt.h"
#define FF_START_DETECTION_THREADS
FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*)
#if !(defined(__APPLE__) || defined(_WIN32))
#define FF_DETECT_QT_GTK 1
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectQt, FFinstance*)
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK2, FFinstance*)
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK3, FFinstance*)
FF_THREAD_ENTRY_DECL_WRAPPER(ffDetectGTK4, FFinstance*)
#endif //!(defined(__APPLE__) || defined(_WIN32))
#endif //FF_HAVE_THREADS
void startDetectionThreads(FFinstance* instance)
{
#ifdef FF_HAVE_THREADS
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, instance));
#ifdef FF_DETECT_QT_GTK
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, instance));
#endif
#else
FF_UNUSED(instance);
#endif
}
#endif //FF_HAVE_THREADS
static volatile bool ffDisableLinewrap = true;
static volatile bool ffHideCursor = true;
@@ -308,13 +243,17 @@ static void resetConsole()
if(ffHideCursor)
fputs("\033[?25h", stdout);
#if defined(_WIN32) && defined(FF_ENABLE_BUFFER)
fflush(stdout);
#endif
}
#ifdef _WIN32
BOOL WINAPI consoleHandler(DWORD signal)
{
FF_UNUSED(signal);
resetConsole();
resetConsole();
exit(0);
}
#else
@@ -328,8 +267,10 @@ static void exitSignalHandler(int signal)
void ffStart(FFinstance* instance)
{
if(instance->config.multithreading)
startDetectionThreads(instance);
#ifdef FF_START_DETECTION_THREADS
if(instance->config.multithreading)
startDetectionThreads(instance);
#endif
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
@@ -396,12 +337,13 @@ static void destroyConfig(FFinstance* instance)
destroyModuleArg(&instance->config.host);
destroyModuleArg(&instance->config.bios);
destroyModuleArg(&instance->config.board);
destroyModuleArg(&instance->config.chassis);
destroyModuleArg(&instance->config.kernel);
destroyModuleArg(&instance->config.uptime);
destroyModuleArg(&instance->config.processes);
destroyModuleArg(&instance->config.packages);
destroyModuleArg(&instance->config.shell);
destroyModuleArg(&instance->config.resolution);
destroyModuleArg(&instance->config.display);
destroyModuleArg(&instance->config.de);
destroyModuleArg(&instance->config.wm);
destroyModuleArg(&instance->config.wmTheme);
@@ -422,6 +364,7 @@ static void destroyConfig(FFinstance* instance)
destroyModuleArg(&instance->config.locale);
destroyModuleArg(&instance->config.localIP);
destroyModuleArg(&instance->config.publicIP);
destroyModuleArg(&instance->config.wallpaper);
destroyModuleArg(&instance->config.weather);
destroyModuleArg(&instance->config.wifi);
destroyModuleArg(&instance->config.player);
@@ -433,6 +376,9 @@ static void destroyConfig(FFinstance* instance)
destroyModuleArg(&instance->config.openGL);
destroyModuleArg(&instance->config.openCL);
destroyModuleArg(&instance->config.users);
destroyModuleArg(&instance->config.bluetooth);
destroyModuleArg(&instance->config.sound);
destroyModuleArg(&instance->config.gamepad);
ffStrbufDestroy(&instance->config.libPCI);
ffStrbufDestroy(&instance->config.libVulkan);
@@ -456,7 +402,9 @@ static void destroyConfig(FFinstance* instance)
ffStrbufDestroy(&instance->config.libOpenCL);
ffStrbufDestroy(&instance->config.libcJSON);
ffStrbufDestroy(&instance->config.libfreetype);
ffStrbufDestroy(&instance->config.libPulse);
ffStrbufDestroy(&instance->config.libwlanapi);
ffStrbufDestroy(&instance->config.libnm);
ffStrbufDestroy(&instance->config.diskFolders);
ffStrbufDestroy(&instance->config.batteryDir);
@@ -466,13 +414,19 @@ static void destroyConfig(FFinstance* instance)
ffStrbufDestroy(&instance->config.weatherOutputFormat);
ffStrbufDestroy(&instance->config.osFile);
ffStrbufDestroy(&instance->config.playerName);
ffStrbufDestroy(&instance->config.commandShell);
FF_LIST_FOR_EACH(FFstrbuf, item, instance->config.commandKeys)
ffStrbufDestroy(item);
ffListDestroy(&instance->config.commandKeys);
FF_LIST_FOR_EACH(FFstrbuf, item, instance->config.commandTexts)
ffStrbufDestroy(item);
ffListDestroy(&instance->config.commandTexts);
}
static void destroyState(FFinstance* instance)
{
for(uint32_t i = 0; i < instance->state.configDirs.length; ++i)
ffStrbufDestroy((FFstrbuf*)ffListGet(&instance->state.configDirs, i));
ffListDestroy(&instance->state.configDirs);
ffPlatformDestroy(&instance->state.platform);
}
void ffDestroyInstance(FFinstance* instance)
@@ -485,6 +439,9 @@ void ffDestroyInstance(FFinstance* instance)
void ffListFeatures()
{
fputs(
#ifdef FF_HAVE_THREADS
"threads\n"
#endif
#ifdef FF_HAVE_LIBPCI
"libpci\n"
#endif
@@ -552,7 +509,13 @@ void ffListFeatures()
"libcjson\n"
#endif
#ifdef FF_HAVE_FREETYPE
"freetype"
"freetype\n"
#endif
#ifdef FF_HAVE_PULSE
"libpulse\n"
#endif
#ifdef FF_HAVE_LIBNM
"libnm\n"
#endif
""
, stdout);
-285
View File
@@ -1,285 +0,0 @@
#include "fastfetch.h"
#include "common/io.h"
#include <unistd.h>
#include <fcntl.h>
#ifdef _WIN32
#include <fileapi.h>
#else
#include <termios.h>
#include <poll.h>
#endif
static void createSubfolders(const char* fileName)
{
FFstrbuf path;
ffStrbufInit(&path);
while(*fileName != '\0')
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
{
mkdir(path.chars
#ifndef WIN32
, S_IRWXU | S_IRGRP | S_IROTH
#endif
);
}
++fileName;
}
ffStrbufDestroy(&path);
}
bool ffWriteFDBuffer(int fd, const FFstrbuf* content)
{
return write(fd, content->chars, content->length) != -1;
}
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
{
#ifdef _WIN32
HANDLE handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
createSubfolders(fileName);
handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
}
DWORD written;
bool ret = !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL);
CloseHandle(handle);
#else
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC;
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open(fileName, openFlagsModes, openFlagsRights);
if(fd == -1)
{
createSubfolders(fileName);
fd = open(fileName, openFlagsModes, openFlagsRights);
if(fd == -1)
return false;
}
bool ret = write(fd, data, dataSize) != -1;
close(fd);
#endif
return ret;
}
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
{
return ffWriteFileData(fileName, buffer->length, buffer->chars);
}
#ifdef _WIN32
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer)
{
DWORD readed = 0;
LARGE_INTEGER fileSize;
if(!GetFileSizeEx(handle, &fileSize))
fileSize.QuadPart = 0;
ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31);
uint32_t free = ffStrbufGetFree(buffer);
bool success;
while(
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
(uint32_t) readed == free
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return success;
}
#endif
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
{
ssize_t readed = 0;
struct stat fileInfo;
if(fstat(fd, &fileInfo) != 0)
return false;
ffStrbufEnsureFree(buffer, fileInfo.st_size > 0 ? (uint32_t)fileInfo.st_size : 31);
uint32_t free = ffStrbufGetFree(buffer);
while(
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
(uint32_t) readed == free
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return readed >= 0;
}
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
{
#ifdef _WIN32
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
DWORD readed;
if(!ReadFile(handle, data, (DWORD)dataSize, &readed, NULL))
return -1;
return (ssize_t)readed;
#else
int fd = open(fileName, O_RDONLY);
if(fd == -1)
return -1;
ssize_t readed = read(fd, data, dataSize);
close(fd);
return readed;
#endif
}
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
{
#ifdef _WIN32
HANDLE handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
bool ret = ffAppendHandleBuffer(handle, buffer);
CloseHandle(handle);
#else
int fd = open(fileName, O_RDONLY);
if(fd == -1)
return false;
bool ret = ffAppendFDBuffer(fd, buffer);
close(fd);
#endif
return ret;
}
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
{
ffStrbufClear(buffer);
return ffAppendFileBuffer(fileName, buffer);
}
// Not thread safe!
void ffSuppressIO(bool suppress)
{
static bool init = false;
static int origOut = -1;
static int origErr = -1;
static int nullFile = -1;
if(!init)
{
if(!suppress)
return;
origOut = dup(STDOUT_FILENO);
origErr = dup(STDERR_FILENO);
nullFile = open("/dev/null", O_WRONLY);
init = true;
}
if(nullFile == -1)
return;
fflush(stdout);
fflush(stderr);
dup2(suppress ? nullFile : origOut, STDOUT_FILENO);
dup2(suppress ? nullFile : origErr, STDERR_FILENO);
}
bool ffFileExists(const char* fileName, mode_t mode)
{
struct stat fileStat;
return stat(fileName, &fileStat) == 0 && ((fileStat.st_mode & S_IFMT) == mode);
}
void ffGetTerminalResponse(const char* request, const char* format, ...)
{
#ifndef WIN32
struct termios oldTerm, newTerm;
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
return;
fputs(request, stdout);
fflush(stdout);
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN;
pfd.revents = 0;
//Give the terminal 35ms to respond
if(poll(&pfd, 1, 35) <= 0)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
return;
}
char buffer[512];
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
if(readed <= 0)
return;
buffer[readed] = '\0';
va_list args;
va_start(args, format);
vsscanf(buffer, format, args);
va_end(args);
#else
//Unimplemented
FF_UNUSED(request, format);
#endif
}
-30
View File
@@ -1,30 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_io
#define FF_INCLUDED_common_io
#include "fastfetch.h"
#include <sys/stat.h> //mode_t, fstat, stat
bool ffWriteFDBuffer(int fd, const FFstrbuf* content);
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer);
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer);
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer);
#ifdef _WIN32
bool ffAppendHandleBuffer(HANDLE handle, FFstrbuf* buffer);
#endif
bool ffFileExists(const char* fileName, mode_t mode);
// Not thread safe!
void ffSuppressIO(bool suppress);
FF_C_SCANF(2, 3) void ffGetTerminalResponse(const char* request, const char* format, ...);
#endif
+134
View File
@@ -0,0 +1,134 @@
#pragma once
#ifndef FF_INCLUDED_common_io_io
#define FF_INCLUDED_common_io_io
#include "util/FFstrbuf.h"
#ifdef _WIN32
#include <fileapi.h>
#include <handleapi.h>
#include <io.h>
typedef HANDLE FFNativeFD;
#else
#include <unistd.h>
typedef int FFNativeFD;
#endif
static inline FFNativeFD FFUnixFD2NativeFD(int unixfd)
{
#ifndef _WIN32
return unixfd;
#else
return (FFNativeFD) _get_osfhandle(unixfd);
#endif
}
static inline bool ffWriteFDData(FFNativeFD fd, size_t dataSize, const void* data)
{
#ifndef _WIN32
return write(fd, data, dataSize) != -1;
#else
DWORD written;
return WriteFile(fd, data, (DWORD) dataSize, &written, NULL) && written == dataSize;
#endif
}
static inline bool ffWriteFDBuffer(FFNativeFD fd, const FFstrbuf* content)
{
return ffWriteFDData(fd, content->length, content->chars);
}
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data);
static inline bool ffWriteFileBuffer(const char* fileName, const FFstrbuf* buffer)
{
return ffWriteFileData(fileName, buffer->length, buffer->chars);
}
static inline ssize_t ffReadFDData(FFNativeFD fd, size_t dataSize, void* data)
{
#ifndef _WIN32
return read(fd, data, dataSize);
#else
DWORD readed;
if(!ReadFile(fd, data, (DWORD)dataSize, &readed, NULL))
return -1;
return (ssize_t)readed;
#endif
}
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer);
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
{
ffStrbufClear(buffer);
return ffAppendFileBuffer(fileName, buffer);
}
//Bit flags, combine with |
typedef enum FFPathType
{
FF_PATHTYPE_REGULAR = 1,
FF_PATHTYPE_LINK = 2,
FF_PATHTYPE_DIRECTORY = 4
} FFPathType;
#define FF_PATHTYPE_FILE (FF_PATHTYPE_REGULAR | FF_PATHTYPE_LINK)
#define FF_PATHTYPE_ANY (FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY)
bool ffPathExists(const char* path, FFPathType pathType);
#ifndef _WIN32
FF_C_SCANF(2, 3)
void ffGetTerminalResponse(const char* request, const char* format, ...);
#endif
// Not thread safe!
bool ffSuppressIO(bool suppress);
static inline void ffUnsuppressIO(bool* suppressed)
{
if (!*suppressed) return;
ffSuppressIO(false);
*suppressed = false;
}
#define FF_SUPPRESS_IO() bool __attribute__((__cleanup__(ffUnsuppressIO), __unused__)) io_suppressed__ = ffSuppressIO(true)
void ffListFilesRecursively(const char* path);
static inline bool wrapClose(FFNativeFD* pfd)
{
assert(pfd);
#ifndef WIN32
if (*pfd < 0)
return false;
close(*pfd);
#else
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
if (*pfd == NULL || *pfd == INVALID_HANDLE_VALUE)
return false;
CloseHandle(*pfd);
#endif
return true;
}
#define FF_AUTO_CLOSE_FD __attribute__((__cleanup__(wrapClose)))
static inline bool wrapFclose(FILE** pfile)
{
assert(pfile);
if (!*pfile)
return false;
fclose(*pfile);
return true;
}
#define FF_AUTO_CLOSE_FILE __attribute__((__cleanup__(wrapFclose)))
#endif // FF_INCLUDED_common_io_io
+226
View File
@@ -0,0 +1,226 @@
#include "io.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <termios.h>
#include <poll.h>
#include <dirent.h>
static void createSubfolders(const char* fileName)
{
FFstrbuf path;
ffStrbufInit(&path);
while(*fileName != '\0')
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH);
++fileName;
}
ffStrbufDestroy(&path);
}
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
{
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC;
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int FF_AUTO_CLOSE_FD fd = open(fileName, openFlagsModes, openFlagsRights);
if(fd == -1)
{
createSubfolders(fileName);
fd = open(fileName, openFlagsModes, openFlagsRights);
if(fd == -1)
return false;
}
return write(fd, data, dataSize) > 0;
}
bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
{
ssize_t readed = 0;
struct stat fileInfo;
if(fstat(fd, &fileInfo) != 0)
return false;
ffStrbufEnsureFree(buffer, fileInfo.st_size > 0 ? (uint32_t)fileInfo.st_size : 31);
uint32_t free = ffStrbufGetFree(buffer);
while(
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
(uint32_t) readed == free
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return readed >= 0;
}
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
{
int FF_AUTO_CLOSE_FD fd = open(fileName, O_RDONLY);
if(fd == -1)
return -1;
return ffReadFDData(fd, dataSize, data);
}
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
{
int FF_AUTO_CLOSE_FD fd = open(fileName, O_RDONLY);
if(fd == -1)
return false;
return ffAppendFDBuffer(fd, buffer);
}
bool ffPathExists(const char* path, FFPathType type)
{
struct stat fileStat;
if(stat(path, &fileStat) != 0)
return false;
int mode = fileStat.st_mode & S_IFMT;
if(type & FF_PATHTYPE_REGULAR && mode == S_IFREG)
return true;
if(type & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
return true;
if(type & FF_PATHTYPE_LINK && mode == S_IFLNK)
return true;
return false;
}
void ffGetTerminalResponse(const char* request, const char* format, ...)
{
struct termios oldTerm, newTerm;
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
return;
fputs(request, stdout);
fflush(stdout);
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN;
pfd.revents = 0;
//Give the terminal 35ms to respond
if(poll(&pfd, 1, 35) <= 0)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
return;
}
char buffer[512];
ssize_t readed = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
if(readed <= 0)
return;
buffer[readed] = '\0';
va_list args;
va_start(args, format);
vsscanf(buffer, format, args);
va_end(args);
}
bool ffSuppressIO(bool suppress)
{
static bool init = false;
static int origOut = -1;
static int origErr = -1;
static int nullFile = -1;
if(!init)
{
if(!suppress)
return true;
origOut = dup(STDOUT_FILENO);
origErr = dup(STDERR_FILENO);
nullFile = open("/dev/null", O_WRONLY);
init = true;
}
if(nullFile == -1)
return false;
fflush(stdout);
fflush(stderr);
dup2(suppress ? nullFile : origOut, STDOUT_FILENO);
dup2(suppress ? nullFile : origErr, STDERR_FILENO);
return true;
}
void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName)
{
DIR* dir = opendir(folder->chars);
if(dir == NULL)
return;
uint32_t folderLength = folder->length;
if(folderName != NULL)
printf("%s/\n", folderName);
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if(entry->d_type == DT_DIR)
{
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
ffStrbufAppendS(folder, entry->d_name);
ffStrbufAppendC(folder, '/');
listFilesRecursively(folder, (uint8_t) (indentation + 1), entry->d_name);
ffStrbufSubstrBefore(folder, folderLength);
continue;
}
for(uint8_t i = 0; i < indentation; i++)
fputs(" | ", stdout);
puts(entry->d_name);
}
closedir(dir);
}
void ffListFilesRecursively(const char* path)
{
FFstrbuf folder;
ffStrbufInitS(&folder, path);
ffStrbufEnsureEndsWithC(&folder, '/');
listFilesRecursively(&folder, 0, NULL);
ffStrbufDestroy(&folder);
}
+149
View File
@@ -0,0 +1,149 @@
#include "io.h"
static void createSubfolders(const char* fileName)
{
FF_STRBUF_AUTO_DESTROY path;
ffStrbufInit(&path);
while(*fileName != '\0')
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
CreateDirectoryA(path.chars, NULL);
++fileName;
}
}
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
{
HANDLE FF_AUTO_CLOSE_FD handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
createSubfolders(fileName);
handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
}
DWORD written;
return !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL);
}
bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer)
{
DWORD readed = 0;
LARGE_INTEGER fileSize;
if(!GetFileSizeEx(handle, &fileSize))
fileSize.QuadPart = 0;
ffStrbufEnsureFree(buffer, fileSize.QuadPart > 0 ? (uint32_t)fileSize.QuadPart : 31);
uint32_t free = ffStrbufGetFree(buffer);
bool success;
while(
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
(uint32_t) readed == free
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return success;
}
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
{
HANDLE FF_AUTO_CLOSE_FD handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return -1;
return ffReadFDData(handle, dataSize, data);
}
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
{
HANDLE FF_AUTO_CLOSE_FD handle = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
return false;
return ffAppendFDBuffer(handle, buffer);
}
bool ffPathExists(const char* path, FFPathType type)
{
DWORD attr = GetFileAttributesA(path);
if(attr == INVALID_FILE_ATTRIBUTES)
return false;
if(type & FF_PATHTYPE_REGULAR && !(attr & FILE_ATTRIBUTE_DIRECTORY))
return true;
if(type & FF_PATHTYPE_DIRECTORY && (attr & FILE_ATTRIBUTE_DIRECTORY))
return true;
if(type & FF_PATHTYPE_LINK && (attr & FILE_ATTRIBUTE_REPARSE_POINT))
return true;
return false;
}
bool ffSuppressIO(bool suppress)
{
(void) suppress; //Not implemented.
return false;
}
void listFilesRecursively(FFstrbuf* folder, uint8_t indentation, const char* folderName)
{
uint32_t folderLength = folder->length;
if(folderName != NULL)
printf("%s/\n", folderName);
ffStrbufAppendC(folder, '*');
WIN32_FIND_DATAA entry;
HANDLE hFind = FindFirstFileA(folder->chars, &entry);
if(hFind == INVALID_HANDLE_VALUE)
return;
do
{
if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(strcmp(entry.cFileName, ".") == 0 || strcmp(entry.cFileName, "..") == 0)
continue;
ffStrbufSubstrBefore(folder, folderLength);
ffStrbufAppendS(folder, entry.cFileName);
ffStrbufAppendC(folder, '/');
listFilesRecursively(folder, (uint8_t) (indentation + 1), entry.cFileName);
ffStrbufSubstrBefore(folder, folderLength);
continue;
}
for(uint8_t i = 0; i < indentation; i++)
fputs(" | ", stdout);
puts(entry.cFileName);
} while (FindNextFileA(hFind, &entry));
FindClose(hFind);
}
void ffListFilesRecursively(const char* path)
{
FFstrbuf folder;
ffStrbufInitS(&folder, path);
ffStrbufEnsureEndsWithC(&folder, '/');
listFilesRecursively(&folder, 0, NULL);
ffStrbufDestroy(&folder);
}
+21 -6
View File
@@ -6,7 +6,7 @@
#include "fastfetch.h"
#include "util/FFcheckmacros.h"
#if defined(_WIN32) //We don't force MSYS using LoadLibrary because dlopen also searches $LD_LIBRARY_PATH
#if defined(_WIN32)
#include <libloaderapi.h>
#define FF_DLOPEN_FLAGS 0
FF_C_NODISCARD static inline void* dlopen(const char* path, int mode) { FF_UNUSED(mode); return LoadLibraryA(path); }
@@ -24,21 +24,30 @@
#define FF_LIBRARY_EXTENSION ".so"
#endif
static inline void ffLibraryUnload(void** handle)
{
assert(handle);
if (*handle)
dlclose(*handle);
}
#define FF_LIBRARY_SYMBOL(symbolName) \
__typeof__(&symbolName) ff ## symbolName;
#define FF_LIBRARY_LOAD(libraryObjectName, userLibraryName, returnValue, ...) \
void* libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\
void* __attribute__((__cleanup__(ffLibraryUnload))) libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\
if(libraryObjectName == NULL) \
return returnValue;
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
symbolMapping = dlsym(library, #symbolName); \
if(symbolMapping == NULL) \
{ \
dlclose(library); \
return returnValue; \
}
return returnValue;
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, symbolMapping, symbolName, alternateName, returnValue) \
symbolMapping = dlsym(library, #symbolName); \
if(symbolMapping == NULL && !(symbolMapping = dlsym(library, #alternateName))) \
return returnValue;
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
@@ -49,12 +58,18 @@
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(library, symbolName, alternateName) \
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
#define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, returnValue);
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName.ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(library, varName, symbolName, alternateName) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, varName.ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, varName->ff ## symbolName, symbolName, returnValue);
+10 -11
View File
@@ -1,18 +1,13 @@
#include "fastfetch.h"
#include "common/parsing.h"
#include <ctype.h>
#include <inttypes.h>
bool ffStrSet(const char* str)
{
if(str == NULL)
return false;
while(isspace(*str))
str++;
return *str != '\0';
}
#ifdef _WIN32
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
#endif
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch)
{
@@ -70,7 +65,7 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, uint8_t p
long double size = (long double) bytes;
uint8_t counter = 0;
while(size > base && counter < prefixesLength - 1)
while(size >= base && counter < prefixesLength - 1)
{
size /= base;
counter++;
@@ -175,3 +170,7 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
ffStrbufAppendS(buffer, " [GTK4]");
}
}
#ifdef _WIN32
#pragma GCC diagnostic pop
#endif
+2 -1
View File
@@ -3,6 +3,8 @@
#ifndef FF_INCLUDED_parsing_h
#define FF_INCLUDED_parsing_h
#include "fastfetch.h"
#include <stdint.h>
typedef struct FFVersion
@@ -14,7 +16,6 @@ typedef struct FFVersion
#define FF_VERSION_INIT ((FFVersion) {0})
bool ffStrSet(const char* str);
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch);
void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, const FFstrbuf* gtk4);
+4 -1
View File
@@ -130,9 +130,12 @@ void ffPrintColor(const FFstrbuf* colorValue)
void ffPrintCharTimes(char c, uint32_t times)
{
if(times == 0)
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 += sizeof(str))
for(uint32_t i = sizeof(str); i <= times; i += (uint32_t)sizeof(str))
fwrite(str, 1, sizeof(str), stdout);
uint32_t remaining = times % sizeof(str);
if(remaining > 0)
+15 -4
View File
@@ -1,6 +1,6 @@
#include "fastfetch.h"
#include "common/processing.h"
#include "common/io.h"
#include "common/io/io.h"
#include <stdlib.h>
#include <unistd.h>
@@ -30,9 +30,20 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
//Parent
close(pipes[1]);
waitpid(childPid, NULL, 0);
ffAppendFDBuffer(pipes[0], buffer);
close(pipes[0]);
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
int status = -1;
if(waitpid(childPid, &status, 0) < 0)
return "waitpid(childPid, &status, 0) failed";
if (!WIFEXITED(status))
return "WIFEXITED(status) == false";
if(WEXITSTATUS(status) == 901)
return "WEXITSTATUS(status) == 901 ( execvp failed )";
if(!ffAppendFDBuffer(childPipeFd, buffer))
return "ffAppendFDBuffer(childPipeFd, buffer) failed";
return NULL;
}
-2
View File
@@ -1,10 +1,8 @@
#include "fastfetch.h"
#include "common/processing.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
//We can't use this native version yet because we still use POSIX path ( eg /usr/bin/fish ) at a lot of places.
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
{
SECURITY_ATTRIBUTES saAttr = {
+5 -20
View File
@@ -144,16 +144,11 @@ done:
return true;
}
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
}
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
FFstrbuf absolutePath;
ffStrbufInitA(&absolutePath, 64);
ffStrbufAppendS(&absolutePath, instance->state.passwd->pw_dir);
ffStrbufAppend(&absolutePath, &instance->state.platform.homeDir);
ffStrbufAppendC(&absolutePath, '/');
ffStrbufAppendS(&absolutePath, relativeFile);
@@ -164,22 +159,17 @@ bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeF
return result;
}
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
bool foundAFile = false;
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
FF_LIST_FOR_EACH(FFstrbuf, dirPrefix, *list)
{
//We need to copy the config dir each time, because it used by multiple threads, so we can't directly write to it.
ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
//We need to copy the dir each time, because it used by multiple threads, so we can't directly write to it.
ffStrbufSet(&baseDir, dirPrefix);
ffStrbufAppendS(&baseDir, relativeFile);
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
@@ -203,8 +193,3 @@ bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativ
return foundAFile;
}
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
+36 -4
View File
@@ -14,10 +14,42 @@ typedef struct FFpropquery
bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer);
bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer);
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer);
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
static inline bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileList(const FFlist* list, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileListValues(list, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
return ffParsePropFileListValues(&instance->state.platform.configDirs, relativeFile, numQueries, queries);
}
static inline bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileDataValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
return ffParsePropFileListValues(&instance->state.platform.dataDirs, relativeFile, numQueries, queries);
}
static inline bool ffParsePropFileData(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileDataValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
#endif
+62 -10
View File
@@ -2,7 +2,7 @@
#include "common/settings.h"
#include "common/library.h"
#include "common/thread.h"
#include "common/io.h"
#include "common/io/io.h"
#include <string.h>
@@ -57,23 +57,31 @@ typedef enum FFInitState
typedef struct GVariantGetters
{
FF_LIBRARY_SYMBOL(g_variant_get_string)
FF_LIBRARY_SYMBOL(g_variant_dup_string)
FF_LIBRARY_SYMBOL(g_variant_get_boolean)
FF_LIBRARY_SYMBOL(g_variant_get_int32)
FF_LIBRARY_SYMBOL(g_variant_unref)
} GVariantGetters;
static FFvariant getGVariantValue(GVariant* variant, FFvarianttype type, const GVariantGetters* variantGetters)
{
FFvariant result;
if(variant == NULL)
return FF_VARIANT_NULL;
result = FF_VARIANT_NULL;
else if(type == FF_VARIANT_TYPE_STRING)
return (FFvariant) {.strValue = variantGetters->ffg_variant_get_string(variant, NULL)};
result = (FFvariant) {.strValue = variantGetters->ffg_variant_dup_string(variant, NULL)}; // Dup string, so that variant itself can be freed
else if(type == FF_VARIANT_TYPE_BOOL)
return (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true};
result = (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true};
else if(type == FF_VARIANT_TYPE_INT)
return (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)};
result = (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)};
else
return FF_VARIANT_NULL;
result = FF_VARIANT_NULL;
if(variant)
variantGetters->ffg_variant_unref(variant);
return result;
}
typedef struct GSettingsData
@@ -102,9 +110,10 @@ static const GSettingsData* getGSettingsData(const FFinstance* instance)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_get_default)
#define data data.variantGetters
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_dup_string)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_unref);
#undef data
data.schemaSource = data.ffg_settings_schema_source_get_default();
@@ -169,9 +178,10 @@ static const DConfData* getDConfData(const FFinstance* instance)
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
#define data data.variantGetters
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_string)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_dup_string)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_boolean)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_get_int32)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_variant_unref)
#undef data
data.client = data.ffdconf_client_new();
@@ -288,6 +298,7 @@ typedef struct SQLiteData
FF_LIBRARY_SYMBOL(sqlite3_step)
FF_LIBRARY_SYMBOL(sqlite3_data_count)
FF_LIBRARY_SYMBOL(sqlite3_column_int)
FF_LIBRARY_SYMBOL(sqlite3_column_text)
FF_LIBRARY_SYMBOL(sqlite3_finalize)
FF_LIBRARY_SYMBOL(sqlite3_close)
} SQLiteData;
@@ -301,6 +312,7 @@ static const SQLiteData* getSQLiteData(const FFinstance* instance)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_step)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_data_count)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_int)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_column_text)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_finalize)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_close)
@@ -309,7 +321,7 @@ static const SQLiteData* getSQLiteData(const FFinstance* instance)
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
{
if(!ffFileExists(dbPath, S_IFREG))
if(!ffPathExists(dbPath, FF_PATHTYPE_FILE))
return 0;
const SQLiteData* data = getSQLiteData(instance);
@@ -341,12 +353,52 @@ int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, cons
return result;
}
bool ffSettingsGetSQLite3String(const FFinstance* instance, const char* dbPath, const char* query, FFstrbuf* result)
{
if(!ffPathExists(dbPath, FF_PATHTYPE_FILE))
return false;
const SQLiteData* data = getSQLiteData(instance);
if(data == NULL)
return false;
sqlite3* db;
if(data->ffsqlite3_open_v2(dbPath, &db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK)
return false;
sqlite3_stmt* stmt;
if(data->ffsqlite3_prepare_v2(db, query, (int) strlen(query), &stmt, NULL) != SQLITE_OK)
{
data->ffsqlite3_close(db);
return false;
}
if(data->ffsqlite3_step(stmt) != SQLITE_ROW || data->ffsqlite3_data_count(stmt) < 1)
{
data->ffsqlite3_finalize(stmt);
data->ffsqlite3_close(db);
return false;
}
ffStrbufSetS(result, (const char *) data->ffsqlite3_column_text(stmt, 0));
data->ffsqlite3_finalize(stmt);
data->ffsqlite3_close(db);
return true;
}
#else //FF_HAVE_SQLITE3
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query)
{
FF_UNUSED(instance, dbPath, query)
return 0;
}
bool ffSettingsGetSQLite3String(const FFinstance* instance, const char* dbPath, const char* query, FFstrbuf* result)
{
FF_UNUSED(instance, dbPath, query, result)
return false;
}
#endif //FF_HAVE_SQLITE3
#ifdef __ANDROID__
+1
View File
@@ -31,6 +31,7 @@ FFvariant ffSettingsGet(const FFinstance* instance, const char* dconfKey, const
FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelName, const char* propertyName, FFvarianttype type);
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query);
bool ffSettingsGetSQLite3String(const FFinstance* instance, const char* dbPath, const char* query, FFstrbuf* result);
#ifdef __ANDROID__
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
+1 -1
View File
@@ -20,7 +20,7 @@
}
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; }
static inline void ffThreadDetach(FFThreadType thread) { CloseHandle(thread); }
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, INFINITE); }
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, 0xffffffff /*INFINITE*/); }
#else
#include <pthread.h>
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+108 -14
View File
@@ -6,7 +6,7 @@
# Empty lines or lines starting with # are ignored.
# This file was shipped with $" FASTFETCH_PROJECT_VERSION $".
# Use fastfetch --print-config-user > ~/.config/fastfetch/config.conf to overwrite this file with the current defaults
# Use fastfetch --gen-config-force to overwrite this file with the current defaults
# Below some often usefull options are listed. Uncomment and modify them so they take affect.
# Note that there are a lot more options than the ones listed here, take a look at "fastfetch --help".
@@ -16,7 +16,7 @@
# Load additional config files.
# Some are shipped with fastfetch, list them with "fastfetch --list-presets".
# Must be a path to a config file or the name of a shipped preset.
# The config file is completly loaded before continuing in the current file, so the placement of this option matters, as later options overwrite already set ones.
# The config file is completely loaded before continuing in the current file, so the placement of this option matters, as later options overwrite already set ones.
# Can be used multiple times to load multiple config files / presets.
#--load-config /path/to/config.txt
@@ -114,6 +114,12 @@
# Default is 0.
#--logo-padding-right 0
# Logo padding top option:
# Adds a padding to the top side of the logo.
# Must be a positive integer.
# Default is 0.
#--logo-padding-top 0
# Logo print remaining option:
# Sets if the remaining logo should be printed, it is has more lines than modules to show.
# Must be true or false.
@@ -162,13 +168,13 @@
# Sets the URL of public IP detection server to be used.
# Only HTTP protocol is supported, and the value should not contain "http://" prefix.
# Default is "ipinfo.io/ip".
#--public-ip-url "ipinfo.io/ip"
#--publicip-url "ipinfo.io/ip"
# Public IP timeout option:
# Sets the time to wait for the public ip server to respond.
# Must be a positive integer.
# Default is 0 (disabled).
#--public-ip-timeout 0
#--publicip-timeout 0
# Weather output format option:
# Sets the weather format to be used. It must be URI encoded.
@@ -206,10 +212,82 @@
# Default is auto.
#--gl auto
# GPU hide options
# Sets weather to hide certain gpu types
# Must be either true or false
# Default is false.
#--gpu-hide-integrated
#--gpu-hide-discrete
# GPU detection options
# Forces using vulkan to detect GPUs
# which support video memory usage detection with `--allow-slow-operations`
# Must be either true or false
# Default is false.
#--gpu-force-vulkan
# Shell option
# Sets if shell version should be detected and printed
# Must be either true or false
# Default is true.
#--shell-version true
# Terminal option
# Sets if terminal version should be detected and printed
# Must be either true or false
# Default is true.
#--terminal-version true
# Disk show options
# Sets if certain types of disk should be printed
# Must be either true or false
# Default is false except for --disk-show-removable.
#--disk-show-removable true
#--disk-show-hidden false
#--disk-show-subvolumes false
#--disk-show-unknown false
# Disk option
# A colon (semicolon on Windows) separated list of folder paths for the disk output
# This option override `--disk-show-*` options above
# Must be a string
# Default is "/:/home" ("C:\\;D:\\ ..." on Windows).
#--disk-folders /:/home
# Bluetooth show disconnected option
# Sets if disconnected bluetooth devices should be printed
# Must be either true or false
# Default is false.
#--bluetooth-show-disconnected false
# Display compact output option
# Sets if all displays should be printed in one line
# Must be either original (print pixel resolution) or scaled (print scaled resolution)
# Default is none.
#--display-compact-type none
# Display detect name option
# Sets if display name should be detected and printed (if supported)
# Must be either true of false
# Default is false.
#--display-detect-name none
# Display precise refresh rate option
# Sets if decimal refresh rates should not be rounded into integers when printing
# Must be either true (keep decimals) of false (round into integers)
# Default is false.
#--display-precise-refresh-rate false
# Sound show all option
# Sets if all sound devices should be printed
# Must be either main, active or all. Default is main
# Default is main.
#--sound-type main
# Percentage output type option
# Applies to all modules that prints percentage values. Currently memory, swap, disk, battery and CPU usage are supported.
# Only works with default format ( without --module-format option ).
# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar
# 0: prints none; 1: prints percent number only; 2: prints bar only; 3: prints both percent number and bar; 6: prints bar and hide other texts; 9: prints colored number
#--percent-type 1
# Key options:
@@ -223,7 +301,8 @@
#--processes-key Processes
#--packages-key Packages
#--shell-key Shell
#--resolution-key Resolution {1}
#--display-key Display {1}
#--brightness-key Brightness ({1})
#--de-key DE
#--wm-key WM
#--wm-theme-key WM Theme
@@ -242,8 +321,8 @@
#--battery-key Battery {1}
#--poweradapter-key Power Adapter {1}
#--locale-key Locale
#--local-ip-key Local IP ({1})
#--public-ip-key Public IP
#--localip-key Local IP ({1})
#--publicip-key Public IP
#--wifi-key Wifi
#--weather-key Weather
#--player-key Media Player
@@ -253,6 +332,10 @@
#--opengl-key OpenGL
#--opencl-key OpenCL
#--users-key Users
#--bluetooth-key Bluetooth
#--sound-key Sound
#--gamepad-key Gamepad
#--wallpaper-key Wallpaper
# Format options:
# Sets the format string for module values.
@@ -267,7 +350,8 @@
#--processes-format
#--packages-format
#--shell-format
#--resolution-format
#--display-format
#--brightness-format
#--de-format
#--wm-format
#--wm-theme-format
@@ -286,8 +370,8 @@
#--battery-format
#--poweradapter-format
#--locale-format
#--local-ip-format
#--public-ip-format
#--localip-format
#--publicip-format
#--weather-format
#--player-format
#--media-format
@@ -296,6 +380,10 @@
#--opengl-format
#--opencl-format
#--users-format
#--bluetooth-format
#--sound-format
#--gamepad-format
#--wallpaper-format
# Error options:
# Sets the format string to use if an error occured
@@ -310,7 +398,8 @@
#--processes-error
#--packages-error
#--shell-error
#--resolution-error
#--display-error
#--brightness-error
#--de-error
#--wm-error
#--wm-theme-error
@@ -329,8 +418,8 @@
#--battery-error
#--poweradapter-error
#--locale-error
#--local-ip-error
#--public-ip-error
#--localip-error
#--publicip-error
#--weather-error
#--player-error
#--media-error
@@ -339,6 +428,10 @@
#--opengl-error
#--opencl-error
#--users-error
#--bluetooth-error
#--sound-error
#--gamepad-error
#--wallpaper-error
# Library options:
# Sets an user specific path to a library to load.
@@ -365,3 +458,4 @@
#--lib-opencl /usr/lib/libOpenCL.so
#--lib-cjson /usr/lib/libcjson.so
#--lib-freetype /data/data/com.termux/files/usr/lib
#--lib-pulse /usr/lib/libpulse.so
+46 -21
View File
@@ -4,6 +4,8 @@ Informative options:
-h,--help: Show this message
-h,--help <command>: Show help for a specific command
-v,--version: Show the version of fastfetch
--list-config-paths: List search paths of config files
--list-data-paths: List search paths of presets and logos
--list-logos: List available logos
--list-modules: List available modules
--list-presets: List presets fastfetch knows about; they can be loaded with --load-config (+)
@@ -12,6 +14,8 @@ Informative options:
--print-config-system: Print the default system config
--print-config-user: Print the default user config
--print-structure: Print the default structure
--gen-config: Generate a sample config file in the default path
--gen-config-force: Generate a sample config file in the default path. Overwrite the existing one
General options:
--load-config <file>: Load a config file or preset (+)
@@ -31,6 +35,7 @@ Logo options:
--logo-padding <padding>: Set the padding on the left and the right of the logo
--logo-padding-left <padding>: Set the padding on the left of the logo
--logo-padding-right <padding>: Set the padding on the right of the logo
--logo-padding-top <padding>: Set the padding on the top of the logo
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
--file <file>: Short for --logo-type file --logo <file>
--file-raw <file>: Short for --logo-type file-raw --logo <file>
@@ -93,29 +98,49 @@ Library options: Set the path of a library to load
--lib-osmesa <path>
--lib-opencl <path>
--lib-cjson <path>
--lib-pulse <path>
--lib-freetype <path>
Module specific options:
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
--separator-string <str>: Set the string printed by the separator module
--os-file <path>: Set the path to the file containing OS information
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
--public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
--public-ip-url: The URL of public IP detection server to be used.
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
--weather-output-format: The output weather format to be used. It must be URI encoded.
--player-name: The name of the player to use
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both. Default is 1
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
--separator-string <str>: Set the string printed by the separator module
--os-file <path>: Set the path to the file containing OS information
--shell-version <?value>: Set if shell version should be detected and printed
--terminal-version <?value>: Set if terminal version should be detected and printed
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
--disk-show-regular <?value>: Set if regular volume should be printed. Default is true
--disk-show-removable <?value>: Set if removable volume should be printed. Default is true
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
--bluetooth-show-disconnected: <?value>: Set if disconnected bluetooth devices should be printed. Default is false
--display-compact-type: <?string>: Set if all displays should be printed in one line. Default is none
--display-detect-name: <?value>: Set if display name should be detected and printed (if supported). Default is false
--display-precise-refresh-rate: <?value>:Set if decimal refresh rates should not be rounded into integers when printing
--sound-type: <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
--gpu-hide-integrated <?value>: Hide integrated GPU if supported. Default is false
--gpu-hide-discrete <?value>: Hide discrete GPU if supported. Default is false
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
--localip-show-mac <?value>: Show mac addresses in local ip module. Default is false
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
--localip-compact <?value>: Show all IPs in one line. Default is false
--publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
--publicip-url: The URL of public IP detection server to be used.
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
--weather-output-format: The output weather format to be used. It must be URI encoded.
--player-name: The name of the player to use
--gl <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 1
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, csh for FreeBSD, bash for others
--command-key <str>: Set the module key to display, can be specified mulitple times
--command-text <str>: Set the command text to be executed, can be specified mulitple times
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
If a value starts with a ?, it is optional. "true" will be used if not set.
+1 -1
View File
@@ -33,4 +33,4 @@ You can therefore use --host-format " " to disable host output.
Note that --host-format "" would evaluate as not set, and therefore use the built-in host format
Format string is also the way to go to set a fixed value - just use one without placeholders.
For example when running in headless mode, you could use "--resolution-format "Preferred".
For example when running in headless mode, you could use "--display-format Preferred".
+2 -1
View File
@@ -1,5 +1,6 @@
Battery
Bios
Bluetooth
Board
Break
Chassis
@@ -11,6 +12,7 @@ Date
Datetime
DE
Disk
Display
Font
GPU
Host
@@ -27,7 +29,6 @@ Player
PowerAdapter
Processes
PublicIP
Resolution
Separator
Shell
Swap
+1 -1
View File
@@ -1 +1 @@
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors
+56
View File
@@ -0,0 +1,56 @@
#include "fastfetch.h"
#include "battery.h"
#include "common/processing.h"
#include "common/properties.h"
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
#define FF_TERMUX_API_PARAM "BatteryStatus"
const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results)
{
FF_STRBUF_AUTO_DESTROY buffer;
ffStrbufInit(&buffer);
if(ffProcessAppendStdOut(&buffer, (char* const[]){
FF_TERMUX_API_PATH,
FF_TERMUX_API_PARAM,
NULL
}))
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
if(buffer.chars[0] != '{')
return "`" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` prints invalid result (not a JSON object)";
BatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
if(ffParsePropLines(buffer.chars, "\"percentage\": ", &battery->status))
{
battery->capacity = ffStrbufToDouble(&battery->status);
ffStrbufClear(&battery->status);
}
if(instance->config.batteryTemp)
{
if(ffParsePropLines(buffer.chars, "\"temperature\": ", &battery->status))
{
ffStrbufTrimRight(&battery->status, ',');
ffStrbufTrim(&battery->status, '"');
battery->temperature = ffStrbufToDouble(&battery->status);
ffStrbufClear(&battery->status);
}
}
if(ffParsePropLines(buffer.chars, "\"status\": ", &battery->status))
{
ffStrbufTrimRight(&battery->status, ',');
ffStrbufTrim(&battery->status, '"');
}
return NULL;
}
+59
View File
@@ -0,0 +1,59 @@
#include "fastfetch.h"
#include "battery.h"
#include <dev/acpica/acpiio.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <unistd.h>
const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results)
{
//https://www.freebsd.org/cgi/man.cgi?acpi_battery(4)
//https://gitlab.xfce.org/panel-plugins/xfce4-battery-plugin/-/blob/master/panel-plugin/libacpi.c
int acpifd = open("/dev/acpi", O_RDONLY);
if(acpifd < 0)
return "open(\"/dev/acpi\", O_RDONLY) failed";
int units = ioctl(acpifd, ACPIIO_BATT_GET_UNITS, 0);
if(units < 0)
{
close(acpifd);
return "No acpiio battery units found";
}
for(int i = 0; i < units; ++i)
{
union acpi_battery_ioctl_arg battio;
battio.unit = i;
if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state & ACPI_BATT_STAT_NOT_PRESENT))
continue;
BatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
battery->capacity = battio.battinfo.cap;
if(battio.battinfo.state & ACPI_BATT_STAT_INVALID)
{
ffStrbufAppendS(&battery->status, "Invalid");
}
else
{
if(battio.battinfo.state & ACPI_BATT_STAT_DISCHARG)
ffStrbufAppendS(&battery->status, "Discharging, ");
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
ffStrbufAppendS(&battery->status, "Charging, ");
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
ffStrbufAppendS(&battery->status, "Ctritical");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
close(acpifd);
return NULL;
}
+4 -1
View File
@@ -1,5 +1,5 @@
#include "fastfetch.h"
#include "common/io.h"
#include "common/io/io.h"
#include "battery.h"
#include <dirent.h>
@@ -99,6 +99,9 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
ffStrbufAppendS(&baseDir, entry->d_name);
parseBattery(&baseDir, results);
ffStrbufSubstrBefore(&baseDir, baseDirLength);
+13 -2
View File
@@ -2,11 +2,22 @@
#include "util/windows/unicode.h"
#include "util/mallocHelper.h"
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <setupapi.h>
#include <batclass.h>
#include <devguid.h>
#include <winternl.h>
#include <powrprof.h>
NTSYSCALLAPI
NTSTATUS
NTAPI
NtPowerInformation(
IN POWER_INFORMATION_LEVEL InformationLevel,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength);
static inline void wrapCloseHandle(HANDLE* handle)
{
@@ -133,7 +144,7 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
else
{
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(CallNtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
{
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
+1 -1
View File
@@ -1,5 +1,5 @@
#include "bios.h"
#include "common/io.h"
#include "common/io/io.h"
#include <stdlib.h>
+15
View File
@@ -0,0 +1,15 @@
#include "bluetooth.h"
#include "../internal.h"
void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth);
const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance)
{
FF_DETECTION_INTERNAL_GUARD(FFBluetoothResult,
ffStrbufInit(&result.error);
ffListInit(&result.devices, sizeof(FFBluetoothDevice));
ffDetectBluetoothImpl(instance, &result);
)
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#ifndef FF_INCLUDED_detection_bluetooth_bluetooth
#define FF_INCLUDED_detection_bluetooth_bluetooth
#include "fastfetch.h"
typedef struct FFBluetoothDevice
{
FFstrbuf name;
FFstrbuf address;
FFstrbuf type;
uint8_t battery; // 0-100%
bool connected;
} FFBluetoothDevice;
typedef struct FFBluetoothResult
{
FFstrbuf error;
FFlist devices; // List of FFBluetoothDevice
} FFBluetoothResult;
const FFBluetoothResult* ffDetectBluetooth(const FFinstance* instance);
#endif
+93
View File
@@ -0,0 +1,93 @@
#include "bluetooth.h"
#import <IOBluetooth/IOBluetooth.h>
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
{
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
if(!ioDevices)
{
ffStrbufAppendS(&bluetooth->error, "IOBluetoothDevice.pairedDevices failed");
return;
}
for(IOBluetoothDevice* ioDevice in ioDevices)
{
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!ioDevice.isConnected;
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode)
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved1)
ffStrbufAppendS(&device->type, "LE audio, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorReserved2)
ffStrbufAppendS(&device->type, "Reserved for future use, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorPositioning)
ffStrbufAppendS(&device->type, "Positioning, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorNetworking)
ffStrbufAppendS(&device->type, "Networking, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorRendering)
ffStrbufAppendS(&device->type, "Rendering, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorCapturing)
ffStrbufAppendS(&device->type, "Capturing, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorObjectTransfer)
ffStrbufAppendS(&device->type, "Object Transfer, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorAudio)
ffStrbufAppendS(&device->type, "Audio, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorTelephony)
ffStrbufAppendS(&device->type, "Telephony, ");
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorInformation)
ffStrbufAppendS(&device->type, "Information, ");
if(device->type.length == 0)
{
switch(ioDevice.deviceClassMajor)
{
case kBluetoothDeviceClassMajorMiscellaneous:
ffStrbufAppendS(&device->type, "Miscellaneous");
break;
case kBluetoothDeviceClassMajorComputer:
ffStrbufAppendS(&device->type, "Computer");
break;
case kBluetoothDeviceClassMajorPhone:
ffStrbufAppendS(&device->type, "Phone");
break;
case kBluetoothDeviceClassMajorLANAccessPoint:
ffStrbufAppendS(&device->type, "LAN/Network Access point");
break;
case kBluetoothDeviceClassMajorAudio:
ffStrbufAppendS(&device->type, "Audio/Video");
break;
case kBluetoothDeviceClassMajorPeripheral:
ffStrbufAppendS(&device->type, "Peripheral");
break;
case kBluetoothDeviceClassMajorImaging:
ffStrbufAppendS(&device->type, "Imaging");
break;
case kBluetoothDeviceClassMajorWearable:
ffStrbufAppendS(&device->type, "Wearable");
break;
case kBluetoothDeviceClassMajorToy:
ffStrbufAppendS(&device->type, "Toy");
break;
case kBluetoothDeviceClassMajorHealth:
ffStrbufAppendS(&device->type, "Health");
break;
case kBluetoothDeviceClassMajorUnclassified:
ffStrbufAppendS(&device->type, "Uncategorized");
break;
default:
ffStrbufAppendS(&device->type, "Unknown");
break;
}
}
else
{
ffStrbufTrimRight(&device->type, ' ');
ffStrbufTrimRight(&device->type, ',');
}
}
}
+203
View File
@@ -0,0 +1,203 @@
#include "bluetooth.h"
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
dict entry( //object
object path "/org/bluez/hci0/dev_03_21_8B_91_16_4D"
array [
dict entry( //property
string "org.bluez.Device1"
array [
dict entry( //value
string "Address"
variant string "03:21:8B:91:16:4D"
)
dict entry( //value
string "Name"
variant string "JBL TUNE160BT"
)
dict entry( //value
string "Icon"
variant string "audio-headset"
)
dict entry( //value
string "Connected"
variant boolean true
)
]
)
dict entry( //property
string "org.bluez.Battery1"
array [
dict entry( //value
string "Percentage"
variant byte 100
)
]
)
]
)
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(strcmp(deviceProperty, "Address") == 0)
ffDBusGetValue(dbus, &dictIter, &device->address);
else if(strcmp(deviceProperty, "Name") == 0)
ffDBusGetValue(dbus, &dictIter, &device->name);
else if(strcmp(deviceProperty, "Icon") == 0)
ffDBusGetValue(dbus, &dictIter, &device->type);
else if(strcmp(deviceProperty, "Percentage") == 0)
ffDBusGetByte(dbus, &dictIter, &device->battery);
else if(strcmp(deviceProperty, "Connected") == 0)
ffDBusGetBool(dbus, &dictIter, &device->connected);
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL)
return; //We don't care about other properties
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
while(true)
{
detectBluetoothValue(dbus, &arrayIter, device);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
}
static void detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
return;
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
//We don't want adapter objects
if(strstr(objectPath, "dev_") == NULL)
return;
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = false;
while(true)
{
detectBluetoothProperty(dbus, &arrayIter, device);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
ffStrbufDestroy(&device->type);
--bluetooth->devices.length;
}
}
static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
while(true)
{
detectBluetoothObject(bluetooth, dbus, &arrayIter);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
}
static const char* detectBluetooth(const FFinstance* instance, FFBluetoothResult* bluetooth)
{
FFDBusData dbus;
const char* error = ffDBusLoadData(instance, DBUS_BUS_SYSTEM, &dbus);
if(error)
return error;
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
if(!managedObjects)
return "Failed to call GetManagedObjects";
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
{
dbus.lib->ffdbus_message_unref(managedObjects);
return "Failed to get root iterator of GetManagedObjects";
}
detectBluetoothRoot(bluetooth, &dbus, &rootIter);
dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}
#endif
void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth)
{
#ifdef FF_HAVE_DBUS
ffStrbufAppendS(&bluetooth->error, detectBluetooth(instance, bluetooth));
#else
FF_UNUSED(instance);
ffStrbufAppendS(&bluetooth->error, "Fastfetch was compiled without DBus support");
#endif
}
@@ -0,0 +1,6 @@
#include "bluetooth.h"
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
{
ffStrbufAppendS(&bluetooth->error, "Bluetooth not supported on this platform");
}
+115
View File
@@ -0,0 +1,115 @@
#include "bluetooth.h"
#include "util/windows/unicode.h"
#include <windows.h>
#include <bluetoothapis.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-sign"
void ffDetectBluetoothImpl(FF_MAYBE_UNUSED const FFinstance* instance, FFBluetoothResult* bluetooth)
{
BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = {
.fReturnConnected = TRUE,
.fReturnRemembered = TRUE,
.fReturnAuthenticated = TRUE,
.fReturnUnknown = TRUE,
.dwSize = sizeof(btsp)
};
BLUETOOTH_DEVICE_INFO btdi = {
.dwSize = sizeof(btdi)
};
HBLUETOOTH_DEVICE_FIND hFind = BluetoothFindFirstDevice(&btsp, &btdi);
if(!hFind)
ffStrbufAppendS(&bluetooth->error, "BluetoothFindFirstDevice() failed or no devices found");
do {
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!btdi.fConnected;
ffStrbufSetWS(&device->name, btdi.szName);
for (uint32_t i = 0; i < sizeof(btdi.Address.rgBytes) / sizeof(btdi.Address.rgBytes); ++i)
ffStrbufAppendF(&device->address, "%X:", btdi.Address.rgBytes[i]);
ffStrbufTrimRight(&device->name, ':');
//https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
if(BitTest(&btdi.ulClassofDevice, 13))
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
if(BitTest(&btdi.ulClassofDevice, 14))
ffStrbufAppendS(&device->type, "LE audio, ");
if(BitTest(&btdi.ulClassofDevice, 15))
ffStrbufAppendS(&device->type, "Reserved for future use, ");
if(BitTest(&btdi.ulClassofDevice, 16))
ffStrbufAppendS(&device->type, "Positioning, ");
if(BitTest(&btdi.ulClassofDevice, 17))
ffStrbufAppendS(&device->type, "Networking, ");
if(BitTest(&btdi.ulClassofDevice, 18))
ffStrbufAppendS(&device->type, "Rendering, ");
if(BitTest(&btdi.ulClassofDevice, 19))
ffStrbufAppendS(&device->type, "Capturing, ");
if(BitTest(&btdi.ulClassofDevice, 20))
ffStrbufAppendS(&device->type, "Object Transfer, ");
if(BitTest(&btdi.ulClassofDevice, 21))
ffStrbufAppendS(&device->type, "Audio, ");
if(BitTest(&btdi.ulClassofDevice, 22))
ffStrbufAppendS(&device->type, "Telephony, ");
if(BitTest(&btdi.ulClassofDevice, 23))
ffStrbufAppendS(&device->type, "Information, ");
if(device->type.length == 0)
{
uint32_t majorDeviceClasses = (btdi.ulClassofDevice >> 8) & ~(UINT32_MAX << 5);
switch(majorDeviceClasses)
{
case 0b00000:
ffStrbufAppendS(&device->type, "Miscellaneous");
break;
case 0b00001:
ffStrbufAppendS(&device->type, "Computer");
break;
case 0b00010:
ffStrbufAppendS(&device->type, "Phone");
break;
case 0b00011:
ffStrbufAppendS(&device->type, "LAN/Network Access point");
break;
case 0b00100:
ffStrbufAppendS(&device->type, "Audio/Video");
break;
case 0b00101:
ffStrbufAppendS(&device->type, "Peripheral");
break;
case 0b00110:
ffStrbufAppendS(&device->type, "Imaging");
break;
case 0b00111:
ffStrbufAppendS(&device->type, "Wearable");
break;
case 0b01000:
ffStrbufAppendS(&device->type, "Toy");
break;
case 0b01001:
ffStrbufAppendS(&device->type, "Health");
break;
case 0b11111:
ffStrbufAppendS(&device->type, "Uncategorized");
break;
default:
ffStrbufAppendS(&device->type, "Unknown");
break;
}
}
else
{
ffStrbufTrimRight(&device->type, ' ');
ffStrbufTrimRight(&device->type, ',');
}
} while (BluetoothFindNextDevice(hFind, &btdi));
}
#pragma GCC diagnostic pop
+1 -1
View File
@@ -1,5 +1,5 @@
#include "board.h"
#include "common/io.h"
#include "common/io/io.h"
#include <stdlib.h>
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#ifndef FF_INCLUDED_detection_brightness_brightness
#define FF_INCLUDED_detection_brightness_brightness
#include "fastfetch.h"
#include "util/FFlist.h"
typedef struct FFBrightnessResult
{
FFstrbuf name;
float value;
} FFBrightnessResult;
const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult
#endif
@@ -0,0 +1,51 @@
#include "brightness.h"
#include "util/apple/cf_helpers.h"
#include <CoreGraphics/CoreGraphics.h>
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
const char* ffDetectBrightness(FFlist* result)
{
if(DisplayServicesGetBrightness == NULL)
return "DisplayServices function DisplayServicesGetBrightness is not available";
CGDirectDisplayID screens[128];
uint32_t screenCount;
if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess)
return "CGGetOnlineDisplayList() failed";
for(uint32_t i = 0; i < screenCount; i++)
{
CGDirectDisplayID screen = screens[i];
float brightness;
if(DisplayServicesGetBrightness(screen, &brightness) != kCGErrorSuccess)
continue;
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
display->value = brightness * 100;
ffStrbufInit(&display->name);
if(CoreDisplay_DisplayCreateInfoDictionary)
{
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary(screen);
if(displayInfo)
{
CFDictionaryRef productNames;
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
{
if(!ffCfDictGetString(productNames, CFSTR("en_US"), &display->name))
continue;
}
}
}
if(CGDisplayIsBuiltin(screen))
ffStrbufAppendS(&display->name, "built-in");
else
ffStrbufAppendF(&display->name, "external-%u", (unsigned) screen);
}
return NULL;
}
@@ -0,0 +1,64 @@
#include "brightness.h"
#include "common/io/io.h"
#include <dirent.h>
#include <ctype.h>
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
{
//https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight
const char* backlightDirPath = "/sys/class/backlight/";
DIR* dirp = opendir(backlightDirPath);
if(dirp == NULL)
return "Failed to open `/sys/class/backlight/`";
FF_STRBUF_AUTO_DESTROY backlightDir;
ffStrbufInitA(&backlightDir, 64);
ffStrbufAppendS(&backlightDir, backlightDirPath);
uint32_t backlightDirLength = backlightDir.length;
FF_STRBUF_AUTO_DESTROY buffer;
ffStrbufInit(&buffer);
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
ffStrbufAppendS(&backlightDir, entry->d_name);
ffStrbufAppendS(&backlightDir, "/actual_brightness");
if(ffReadFileBuffer(backlightDir.chars, &buffer))
{
double actualBrightness = ffStrbufToDouble(&buffer);
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
ffStrbufAppendS(&backlightDir, entry->d_name);
ffStrbufAppendS(&backlightDir, "/max_brightness");
if(ffReadFileBuffer(backlightDir.chars, &buffer))
{
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
ffStrbufSubstrBeforeLastC(&backlightDir, '/');
ffStrbufAppendS(&backlightDir, "/device");
ffStrbufInitA(&display->name, PATH_MAX + 1);
if(realpath(backlightDir.chars, display->name.chars))
{
ffStrbufRecalculateLength(&display->name);
ffStrbufSubstrAfterLastC(&display->name, '/');
if(ffStrbufStartsWithS(&display->name, "card") && isdigit(display->name.chars[4]))
ffStrbufSubstrAfterFirstC(&display->name, '-');
}
else
ffStrbufInitS(&display->name, entry->d_name);
double maxBrightness = ffStrbufToDouble(&buffer);
display->value = (float) (actualBrightness * 100 / maxBrightness);
}
}
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
}
closedir(dirp);
return NULL;
}
@@ -0,0 +1,6 @@
#include "brightness.h"
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
{
return "Not supported on this platform";
}
@@ -0,0 +1,27 @@
extern "C"
{
#include "brightness.h"
}
#include "util/windows/wmi.hpp"
extern "C"
const char* ffDetectBrightness(FFlist* result)
{
FFWmiQuery query(L"SELECT CurrentBrightness, InstanceName FROM WmiMonitorBrightness WHERE Active = true", nullptr, FFWmiNamespace::WMI);
if(!query)
return "Query WMI service failed";
while(FFWmiRecord record = query.next())
{
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInit(&display->name);
record.getString(L"InstanceName", &display->name);
ffStrbufSubstrAfterFirstC(&display->name, '\\');
ffStrbufSubstrBeforeFirstC(&display->name, '\\');
uint64_t brightness;
record.getUnsigned(L"CurrentBrightness", &brightness);
display->value = (float) brightness;
}
return NULL;
}
+1 -1
View File
@@ -1,5 +1,5 @@
#include "chassis.h"
#include "common/io.h"
#include "common/io/io.h"
#include <stdlib.h>
+52 -8
View File
@@ -1,5 +1,5 @@
#include "cpu.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/properties.h"
#include "detection/temps/temps_linux.h"
@@ -7,7 +7,7 @@
#include <stdlib.h>
#include <unistd.h>
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz)
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz, FFstrbuf* cpuIsa, FFstrbuf* cpuUarch)
{
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL)
@@ -19,7 +19,7 @@ static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrb
while(getline(&line, &len, cpuinfo) != -1)
{
//Stop after the first CPU
if(cpu->name.length > 0 && (*line == '\0' || *line == '\n'))
if(*line == '\0' || *line == '\n')
break;
(void)(
@@ -27,6 +27,8 @@ static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrb
ffParsePropLine(line, "vendor_id :", &cpu->vendor) ||
ffParsePropLine(line, "cpu cores :", physicalCoresBuffer) ||
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
ffParsePropLine(line, "isa :", cpuIsa) ||
ffParsePropLine(line, "uarch :", cpuUarch) ||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) //For Android devices
);
}
@@ -65,9 +67,9 @@ static double getFrequency(const char* info, const char* scaling)
return getGHz(scaling);
}
static double detectCPUTemp(const FFinstance* instance)
static double detectCPUTemp(void)
{
const FFTempsResult* temps = ffDetectTemps(instance);
const FFTempsResult* temps = ffDetectTemps();
for(uint32_t i = 0; i < temps->values.length; i++)
{
@@ -83,10 +85,29 @@ static double detectCPUTemp(const FFinstance* instance)
return FF_CPU_TEMP_UNSET;
}
static void parseIsa(FFstrbuf* cpuIsa)
{
if(ffStrbufStartsWithS(cpuIsa, "rv"))
{
// RISC-V ISA string example: "rv64imafdch_zicsr_zifencei".
// The _z parts are not important for CPU showcasing, so we remove them.
if(ffStrbufContainC(cpuIsa, '_'))
ffStrbufSubstrBeforeFirstC(cpuIsa, '_');
// Then we replace "imafd" with "g" since "g" is a shorthand.
if(ffStrbufContainS(cpuIsa, "imafd"))
{
// Remove 4 of the 5 characters and replace the remaining one with "g".
ffStrbufRemoveSubstr(cpuIsa, 4, 8);
cpuIsa->chars[4] = 'g';
}
// The final ISA output of the above example is "rv64gch".
}
}
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
if(instance->config.cpuTemp)
cpu->temperature = detectCPUTemp(instance);
cpu->temperature = detectCPUTemp();
else
cpu->temperature = FF_CPU_TEMP_UNSET;
@@ -96,7 +117,13 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
FFstrbuf cpuMHz;
ffStrbufInit(&cpuMHz);
parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz);
FFstrbuf cpuIsa;
ffStrbufInit(&cpuIsa);
FFstrbuf cpuUarch;
ffStrbufInit(&cpuUarch);
parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch);
cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1);
@@ -104,7 +131,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
cpu->coresOnline = (uint16_t) get_nprocs();
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
if(ffFileExists(BP, S_IFDIR))
if(ffPathExists(BP, FF_PATHTYPE_DIRECTORY))
{
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
@@ -114,6 +141,23 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
cpu->frequencyMin = cpu->frequencyMax = ffStrbufToDouble(&cpuMHz) / 1000;
}
if(cpuUarch.length > 0)
{
if(cpu->name.length > 0)
ffStrbufAppendC(&cpu->name, ' ');
ffStrbufAppend(&cpu->name, &cpuUarch);
}
if(cpuIsa.length > 0)
{
parseIsa(&cpuIsa);
if(cpu->name.length > 0)
ffStrbufAppendC(&cpu->name, ' ');
ffStrbufAppend(&cpu->name, &cpuIsa);
}
ffStrbufDestroy(&physicalCoresBuffer);
ffStrbufDestroy(&cpuMHz);
ffStrbufDestroy(&cpuIsa);
ffStrbufDestroy(&cpuUarch);
}
+14 -7
View File
@@ -1,4 +1,5 @@
#include "cpu.h"
#include "detection/temps/temps_windows.h"
#include "util/windows/registry.h"
#include "util/mallocHelper.h"
@@ -14,25 +15,28 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
DWORD length = 0;
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &length);
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
pLogicalInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
if(pLogicalInfo && GetLogicalProcessorInformationEx(RelationProcessorCore, pLogicalInfo, &length))
if(pProcessorInfo && GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
{
for(
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pLogicalInfo;
(uint8_t*)ptr < ((uint8_t*)pLogicalInfo) + length;
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
)
{
if(ptr->Relationship == RelationProcessorCore)
++cpu->coresPhysical;
else if(ptr->Relationship == RelationGroup)
{
cpu->coresOnline += ptr->Group.GroupInfo->ActiveProcessorCount;
cpu->coresLogical += ptr->Group.GroupInfo->MaximumProcessorCount;
}
}
}
}
cpu->coresOnline = (uint16_t)GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
cpu->coresLogical = (uint16_t)GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
FF_HKEY_AUTO_DESTROY hKey;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
@@ -46,4 +50,7 @@ void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
if(instance->config.cpuTemp)
ffDetectSmbiosTemp(&cpu->temperature, NULL);
}
+10 -15
View File
@@ -6,23 +6,18 @@
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
natural_t numCPUs = 0U;
processor_info_array_t cpuInfo;
mach_msg_type_number_t numCpuInfo;
host_cpu_load_info_data_t cpustats;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
*inUseAll = *totalAll = 0;
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS)
return "host_processor_info() failed";
if (numCPUs * CPU_STATE_MAX != numCpuInfo)
return "Unexpected host_processor_info() result";
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)(&cpustats), &count) != KERN_SUCCESS)
return "host_statistics() failed";
*inUseAll = cpustats.cpu_ticks[CPU_STATE_USER]
+ cpustats.cpu_ticks[CPU_STATE_SYSTEM]
+ cpustats.cpu_ticks[CPU_STATE_NICE];
*totalAll = *inUseAll + cpustats.cpu_ticks[CPU_STATE_IDLE];
for (natural_t i = 0U; i < numCPUs; ++i) {
integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
*inUseAll += (uint64_t)inUse;
*totalAll += (uint64_t)total;
}
return NULL;
}
-25
View File
@@ -1,8 +1,6 @@
#include "fastfetch.h"
#include "cpuUsage.h"
#ifdef FF_USE_WIN_NTAPI
#include "util/mallocHelper.h"
#include <ntstatus.h>
@@ -37,26 +35,3 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
return NULL;
}
#else
#include <processthreadsapi.h>
static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime);
}
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
FILETIME idleTime, kernelTime, userTime;
if(!GetSystemTimes(&idleTime, &kernelTime, &userTime))
return "GetSystemTimes() failed";
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getsystemtimes
// `kernelTime` also includes the amount of time the system has been idle.
*totalAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime);
*inUseAll = *totalAll - fileTimeToUint64(&idleTime);
return NULL;
}
#endif
+52
View File
@@ -0,0 +1,52 @@
#include "cursor.h"
#import <Foundation/Foundation.h>
static void appendColor(FFstrbuf* str, NSDictionary* color)
{
int r = (int) (((NSNumber*) [color valueForKey:@"red"]).doubleValue * 255);
int g = (int) (((NSNumber*) [color valueForKey:@"green"]).doubleValue * 255);
int b = (int) (((NSNumber*) [color valueForKey:@"blue"]).doubleValue * 255);
int a = (int) (((NSNumber*) [color valueForKey:@"alpha"]).doubleValue * 255);
if (r == 255 && g == 255 && b == 255 && a == 255)
ffStrbufAppendS(str, "White");
else if (r == 0 && g == 0 && b == 0 && a == 255)
ffStrbufAppendS(str, "Black");
else
ffStrbufAppendF(str, "#%02X%02X%02X%02X", r, g, b, a);
}
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
{
NSError* error;
NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.apple.universalaccess.plist", instance->state.platform.homeDir.chars];
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
error:&error];
if(error)
{
ffStrbufAppendS(&result->error, error.localizedDescription.UTF8String);
return;
}
NSDictionary* color;
ffStrbufAppendS(&result->theme, "Fill - ");
if ((color = [dict valueForKey:@"cursorFill"]))
appendColor(&result->theme, color);
else
ffStrbufAppendS(&result->theme, "Black");
ffStrbufAppendS(&result->theme, ", Outline - ");
if ((color = [dict valueForKey:@"cursorOutline"]))
appendColor(&result->theme, color);
else
ffStrbufAppendS(&result->theme, "White");
NSNumber* mouseDriverCursorSize = [dict valueForKey:@"mouseDriverCursorSize"];
if (mouseDriverCursorSize)
ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32));
else
ffStrbufAppendS(&result->size, "32");
}
+18 -58
View File
@@ -3,12 +3,13 @@
#include "common/properties.h"
#include "common/parsing.h"
#include "common/settings.h"
#include "detection/gtk.h"
#include "detection/gtk_qt/gtk_qt.h"
#include "detection/displayserver/displayserver.h"
#include "util/stringUtils.h"
#include <stdlib.h>
static void detectCursorGTK(const FFinstance* instance, FFCursorResult* result)
static bool detectCursorGTK(const FFinstance* instance, FFCursorResult* result)
{
const FFGTKResult* gtk = ffDetectGTK4(instance);
@@ -19,25 +20,11 @@ static void detectCursorGTK(const FFinstance* instance, FFCursorResult* result)
gtk = ffDetectGTK2(instance);
if(gtk->cursor.length == 0)
{
ffStrbufAppendS(&result->error, "Couldn't detect GTK Cursor");
return;
}
return false;
ffStrbufAppend(&result->theme, &gtk->cursor);
ffStrbufAppend(&result->size, &gtk->cursorSize);
}
static void detectCursorXFCE(const FFinstance* instance, FFCursorResult* result)
{
ffStrbufAppendS(&result->theme, ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue);
if(result->theme.length == 0)
ffStrbufAppendS(&result->error, "Couldn't find xfce cursor in xfconf (xsettings::/Gtk/CursorThemeName)");
int cursorSizeVal = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue;
if(cursorSizeVal > 0)
ffStrbufAppendF(&result->size, "%i", cursorSizeVal);
return true;
}
static void detectCursorFromConfigFile(const FFinstance* instance, const char* relativeFilePath, const char* themeStart, const char* themeDefault, const char* sizeStart, const char* sizeDefault, FFCursorResult* result)
@@ -68,16 +55,6 @@ static bool detectCursorFromXResources(const FFinstance* instance, FFCursorResul
return result->theme.length > 0;
}
static bool detectCursorFromXDG(const FFinstance* instance, bool user, FFCursorResult* result)
{
if(user)
ffParsePropFileHome(instance, ".icons/default/index.theme", "Inherits =", &result->theme);
else
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/icons/default/index.theme", "Inherits =", &result->theme);
return result->theme.length > 0;
}
static bool detectCursorFromEnv(const FFinstance* instance, FFCursorResult* result)
{
FF_UNUSED(instance);
@@ -96,36 +73,19 @@ void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
{
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0)
{
if(ffStrbufCompS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG) == 0)
ffStrbufAppendS(&result->error, "WSLg uses native windows cursor");
return;
}
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
{
else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY");
return;
}
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0)
return detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "XFCE"))
return detectCursorXFCE(instance, result);
if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "LXQt"))
return detectCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result);
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0)
return detectCursorGTK(instance, result);
if(
detectCursorFromEnv(instance, result) ||
detectCursorFromXDG(instance, true, result) ||
detectCursorFromXResources(instance, result) ||
detectCursorFromXDG(instance, false, result)
) return;
detectCursorGTK(instance, result);
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0)
detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
detectCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result);
else if(
!detectCursorGTK(instance, result) &&
!detectCursorFromEnv(instance, result) &&
!ffParsePropFileHome(instance, ".icons/default/index.theme", "Inherits =", &result->theme) &&
!detectCursorFromXResources(instance, result) &&
!ffParsePropFileData(instance, "icons/default/index.theme", "Inherits =", &result->theme)
) ffStrbufAppendS(&result->error, "Couldn't find cursor");
}
+19 -12
View File
@@ -1,12 +1,19 @@
#include "cursor.h"
#include "util/windows/registry.h"
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
{
FF_UNUSED(instance);
FF_HKEY_AUTO_DESTROY hKey;
if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Control Panel\\Cursors", &hKey, &result->error))
ffRegReadStrbuf(hKey, NULL, &result->theme, &result->error);
}
#include "cursor.h"
#include "util/windows/registry.h"
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
{
FF_UNUSED(instance);
FF_HKEY_AUTO_DESTROY hKey;
if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Control Panel\\Cursors", &hKey, &result->error))
{
if (!ffRegReadStrbuf(hKey, NULL, &result->theme, &result->error))
return;
uint32_t cursorBaseSize;
ffRegReadUint(hKey, L"CursorBaseSize", &cursorBaseSize, &result->error);
ffStrbufAppendF(&result->size, "%u", (unsigned) cursorBaseSize);
}
}
@@ -1,5 +1,5 @@
#include "fastfetch.h"
#include "detection/datetime.h"
#include "detection/datetime/datetime.h"
#include "common/thread.h"
#include <time.h>
@@ -1,7 +1,7 @@
#pragma once
#ifndef FF_INCLUDED_detection_datetime
#define FF_INCLUDED_detection_datetime
#ifndef FF_INCLUDED_detection_datetime_datetime
#define FF_INCLUDED_detection_datetime_datetime
#include "fastfetch.h"
+13 -6
View File
@@ -18,11 +18,18 @@ const FFDiskResult* ffDetectDisks()
if(result.disks.length == 0 && result.error.length == 0)
ffStrbufAppendS(&result.error, "No disks found");
//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
//Note that we sort alphabetically here for a better ordering when printing the list,
// so the check must be done in reverse order
ffListSort(&result.disks, compareDisks);
else
{
//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
//Note that we sort alphabetically here for a better ordering when printing the list,
// so the check must be done in reverse order
ffListSort(&result.disks, compareDisks);
FF_LIST_FOR_EACH(FFDisk, disk, result.disks)
{
if(disk->bytesTotal == 0)
disk->type |= FF_DISK_TYPE_UNKNOWN_BIT;
}
}
);
}
-7
View File
@@ -5,13 +5,6 @@
#include "fastfetch.h"
typedef enum FFDiskType
{
FF_DISK_TYPE_REGULAR,
FF_DISK_TYPE_HIDDEN,
FF_DISK_TYPE_EXTERNAL
} FFDiskType;
typedef struct FFDisk
{
FFstrbuf mountpoint;
+3 -3
View File
@@ -7,11 +7,11 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk)
{
// FreeBSD doesn't support these flags
if(fs->f_flags & MNT_DONTBROWSE)
disk->type = FF_DISK_TYPE_HIDDEN;
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
else if(fs->f_flags & MNT_REMOVABLE)
disk->type = FF_DISK_TYPE_EXTERNAL;
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
else
disk->type = FF_DISK_TYPE_REGULAR;
disk->type = FF_DISK_TYPE_REGULAR_BIT;
ffStrbufInitS(&disk->name, [NSFileManager.defaultManager displayNameAtPath:@(fs->f_mntonname)].UTF8String);
}
+3 -3
View File
@@ -13,11 +13,11 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk)
ffStrbufStartsWithS(&disk->mountpoint, "/proc") ||
ffStrbufStartsWithS(&disk->mountpoint, "/zroot")
)
disk->type = FF_DISK_TYPE_HIDDEN;
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
else if((fs->f_flags & MNT_NOSUID) || !(fs->f_flags & MNT_LOCAL))
disk->type = FF_DISK_TYPE_EXTERNAL;
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
else
disk->type = FF_DISK_TYPE_REGULAR;
disk->type = FF_DISK_TYPE_REGULAR_BIT;
ffStrbufInit(&disk->name);
}
+202 -69
View File
@@ -1,31 +1,196 @@
#include "disk.h"
#include "util/stringUtils.h"
#include <limits.h>
#include <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
static void strbufAppendMountPoint(FFstrbuf* mountpoint, const char* source)
#ifdef __USE_LARGEFILE64
#define stat stat64
#define statvfs statvfs64
#define dirent dirent64
#define readdir readdir64
#endif
static bool isPhysicalDevice(FFstrbuf* device)
{
while(*source != '\0' && !isspace(*source))
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
if(ffStrbufEqualS(device, "drvfs"))
return true;
//ZFS root pool. The format is rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>
if(ffStrbufStartsWithS(device, "rpool/"))
return true;
struct stat deviceStat;
if(stat(device->chars, &deviceStat) != 0)
return false;
//Ignore all devices that are not block devices
if(!S_ISBLK(deviceStat.st_mode))
return false;
//Pseudo filesystems don't have a device in /dev
if(!ffStrbufStartsWithS(device, "/dev/"))
return false;
if(
ffStrbufStartsWithS(device, "/dev/loop") || //Ignore loop devices
ffStrbufStartsWithS(device, "/dev/ram") || //Ignore ram devices
ffStrbufStartsWithS(device, "/dev/fd") //Ignore fd devices
) return false;
return true;
}
static void appendNextEntry(FFstrbuf* buffer, char** source)
{
//Read the current entry into the buffer
while(**source != '\0' && !isspace(**source))
{
//After a backslash the next 3 characters are octal ascii codes
if(*source == '\\' && strnlen(source, 4) == 4)
if(**source == '\\' && strnlen(*source, 4) == 4)
{
char octal[4] = {0};
strncpy(octal, source + 1, 3);
strncpy(octal, *source + 1, 3);
long value = strtol(octal, NULL, 8); //Returns 0 on error, so no need to check endptr
if(value > 0 && value < CHAR_MAX)
{
ffStrbufAppendC(mountpoint, (char) value);
source += 4;
ffStrbufAppendC(buffer, (char) value);
*source += 4;
continue;
}
}
ffStrbufAppendC(mountpoint, *source);
++source;
ffStrbufAppendC(buffer, **source);
++*source;
}
//Skip whitespace
while(isspace(**source))
++*source;
}
static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFstrbuf* basePath)
{
DIR* dir = opendir(basePath->chars);
if(dir == NULL)
return;
uint32_t basePathLength = basePath->length;
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if(entry->d_name[0] == '.')
continue;
ffStrbufAppendS(basePath, entry->d_name);
struct stat entryStat;
bool ret = stat(basePath->chars, &entryStat) == 0;
ffStrbufSubstrBefore(basePath, basePathLength);
if(!ret || deviceStat->st_ino != entryStat.st_ino)
continue;
ffStrbufAppendS(&disk->name, entry->d_name);
break;
}
closedir(dir);
}
static void detectName(FFDisk* disk, const FFstrbuf* device)
{
struct stat deviceStat;
if(stat(device->chars, &deviceStat) != 0)
return;
FF_STRBUF_AUTO_DESTROY basePath;
ffStrbufInit(&basePath);
//Try partlabel first
ffStrbufSetS(&basePath, "/dev/disk/by-partlabel/");
detectNameFromPath(disk, &deviceStat, &basePath);
//Try label second
if(disk->name.length == 0)
{
ffStrbufSetS(&basePath, "/dev/disk/by-label/");
detectNameFromPath(disk, &deviceStat, &basePath);
}
//Use the mountpoint as a last resort
if(disk->name.length == 0)
ffStrbufAppend(&disk->name, &disk->mountpoint);
}
#ifdef __ANDROID__
static void detectType(FF_MAYBE_UNUSED const FFlist* devices, FFDisk* currentDisk, FF_MAYBE_UNUSED const char* options)
{
if(ffStrbufEqualS(&currentDisk->mountpoint, "/") || ffStrbufEqualS(&currentDisk->mountpoint, "/storage/emulated"))
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
else if(ffStrbufStartsWithS(&currentDisk->mountpoint, "/mnt/media_rw/"))
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
else
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
}
#else
static bool isSubvolume(const FFlist* devices)
{
const FFstrbuf* currentDevie = ffListGet(devices, devices->length - 1);
//Filter all disks which device was already found. This catches BTRFS subvolumes.
for(uint32_t i = 0; i < devices->length - 1; i++)
{
const FFstrbuf* otherDevice = ffListGet(devices, i);
if(ffStrbufEqual(currentDevie, otherDevice))
return true;
}
//ZFS subvolumes: rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>.
//Test if the third slash is present.
if(strncmp(currentDevie->chars, "rpool/", 6) == 0 && ffStrHasNChars(currentDevie->chars, '/', 3))
return true;
return false;
}
static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options)
{
if(isSubvolume(devices))
currentDisk->type = FF_DISK_TYPE_SUBVOLUME_BIT;
else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL)
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
else if(ffStrbufStartsWithS(&currentDisk->mountpoint, "/boot") || ffStrbufStartsWithS(&currentDisk->mountpoint, "/efi"))
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
else
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
}
#endif
static void detectStats(FFDisk* disk)
{
struct statvfs fs;
if(statvfs(disk->mountpoint.chars, &fs) != 0)
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize);
disk->filesTotal = (uint32_t) fs.f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
}
void ffDetectDisksImpl(FFDiskResult* disks)
@@ -37,6 +202,9 @@ void ffDetectDisksImpl(FFDiskResult* disks)
return;
}
FF_LIST_AUTO_DESTROY devices;
ffListInit(&devices, sizeof(FFstrbuf));
char* line = NULL;
size_t len = 0;
@@ -45,80 +213,45 @@ void ffDetectDisksImpl(FFDiskResult* disks)
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
char* currentPos = line;
//Non pseudo filesystems have their device in /dev/
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
if(strncmp(currentPos, "/dev/", 5) != 0 && strncmp(currentPos, "drvfs", 5) != 0)
continue;
//Skip /dev/ or drvfs
currentPos += 5;
//Don't show loop file systems
if(strncasecmp(currentPos, "loop", 4) == 0)
//detect device
FFstrbuf* device = ffListAdd(&devices);
ffStrbufInit(device);
appendNextEntry(device, &currentPos);
if(!isPhysicalDevice(device))
{
ffStrbufDestroy(device);
devices.length--;
continue;
}
//We have a valid device, add it to the list
FFDisk* disk = ffListAdd(&disks->disks);
//Go to mountpoint
while(!isspace(*currentPos) && *currentPos != '\0')
++currentPos;
while(isspace(*currentPos))
++currentPos;
//detect mountpoint
ffStrbufInit(&disk->mountpoint);
appendNextEntry(&disk->mountpoint, &currentPos);
ffStrbufInitA(&disk->mountpoint, 16);
strbufAppendMountPoint(&disk->mountpoint, currentPos);
//detect filesystem
ffStrbufInit(&disk->filesystem);
appendNextEntry(&disk->filesystem, &currentPos);
//Go to filesystem
currentPos += disk->mountpoint.length;
while(isspace(*currentPos))
++currentPos;
//detect name
ffStrbufInit(&disk->name);
detectName(disk, device);
ffStrbufInitA(&disk->filesystem, 16);
ffStrbufAppendSUntilC(&disk->filesystem, currentPos, ' ');
//Go to options, detect type
currentPos += disk->filesystem.length;
while(isspace(*currentPos))
++currentPos;
#ifdef __ANDROID__
if(ffStrbufEqualS(&disk->mountpoint, "/") || ffStrbufEqualS(&disk->mountpoint, "/storage/emulated"))
disk->type = FF_DISK_TYPE_REGULAR;
else if(ffStrbufStartsWithS(&disk->mountpoint, "/mnt/media_rw/"))
disk->type = FF_DISK_TYPE_EXTERNAL;
else
disk->type = FF_DISK_TYPE_HIDDEN;
#else
if(strstr(currentPos, "nosuid") != NULL || strstr(currentPos, "nodev") != NULL)
disk->type = FF_DISK_TYPE_EXTERNAL;
else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi"))
disk->type = FF_DISK_TYPE_HIDDEN;
else
disk->type = FF_DISK_TYPE_REGULAR;
#endif
//detect type
detectType(&devices, disk, currentPos);
//Detects stats
#ifdef __USE_LARGEFILE64
struct statvfs64 fs;
if(statvfs64(disk->mountpoint.chars, &fs) != 0)
memset(&fs, 0, sizeof(struct statvfs64)); //Set all values to 0, so our values get initialized to 0 too
#else
struct statvfs fs;
if(statvfs(disk->mountpoint.chars, &fs) != 0)
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
#endif
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
disk->bytesUsed = disk->bytesTotal - (fs.f_bavail * fs.f_frsize);
disk->filesTotal = (uint32_t) fs.f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
ffStrbufInit(&disk->name); //TODO: implement this
detectStats(disk);
}
if(line != NULL)
free(line);
FF_LIST_FOR_EACH(FFstrbuf, device, devices)
ffStrbufDestroy(device);
fclose(mountsFile);
}
+27 -27
View File
@@ -1,36 +1,31 @@
#include "disk.h"
#include "util/windows/unicode.h"
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <assert.h>
void ffDetectDisksImpl(FFDiskResult* disks)
{
uint32_t length = GetLogicalDriveStringsA(0, NULL);
if(length == 0)
{
ffStrbufAppendS(&disks->error, "GetLogicalDriveStringsA failed");
return;
}
char* buf = malloc(length + 1);
GetLogicalDriveStringsA(length, buf);
wchar_t buf[MAX_PATH + 1];
uint32_t length = GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf);
assert(length < sizeof(buf) / sizeof(*buf));
for(uint32_t i = 0; i < length; i++)
{
const char* mountpoint = buf + i;
const wchar_t* mountpoint = buf + i;
UINT driveType = GetDriveTypeA(mountpoint);
UINT driveType = GetDriveTypeW(mountpoint);
if(driveType == DRIVE_NO_ROOT_DIR)
{
i += (uint32_t)strlen(mountpoint);
i += (uint32_t)wcslen(mountpoint);
continue;
}
FFDisk* disk = ffListAdd(&disks->disks);
ffStrbufInitS(&disk->mountpoint, mountpoint);
ffStrbufInitWS(&disk->mountpoint, mountpoint);
uint64_t bytesFree;
if(!GetDiskFreeSpaceExA(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
if(!GetDiskFreeSpaceExW(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
{
disk->bytesTotal = 0;
bytesFree = 0;
@@ -38,26 +33,33 @@ void ffDetectDisksImpl(FFDiskResult* disks)
disk->bytesUsed = disk->bytesTotal - bytesFree;
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
disk->type = FF_DISK_TYPE_EXTERNAL;
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
else if(driveType == DRIVE_FIXED)
disk->type = FF_DISK_TYPE_REGULAR;
disk->type = FF_DISK_TYPE_REGULAR_BIT;
else
disk->type = FF_DISK_TYPE_HIDDEN;
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
ffStrbufInit(&disk->filesystem);
ffStrbufInit(&disk->name);
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
ffStrbufInitA(&disk->filesystem, MAX_PATH + 1);
ffStrbufInitA(&disk->name, MAX_PATH + 1);
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
GetVolumeInformationA(mountpoint,
disk->name.chars, disk->name.allocated, //Volume name
BOOL result = GetVolumeInformationW(mountpoint,
diskName, sizeof(diskName) / sizeof(*diskName), //Volume name
NULL, //Serial number
NULL, //Max component length
NULL, //File system flags
disk->filesystem.chars, disk->filesystem.allocated
diskFileSystem, sizeof(diskFileSystem) / sizeof(*diskFileSystem)
);
SetErrorMode(errorMode);
ffStrbufRecalculateLength(&disk->name);
ffStrbufRecalculateLength(&disk->filesystem);
if(result)
{
ffStrbufSetWS(&disk->filesystem, diskFileSystem);
ffStrbufSetWS(&disk->name, diskName);
}
//TODO: implement
disk->filesUsed = 0;
@@ -65,6 +67,4 @@ void ffDetectDisksImpl(FFDiskResult* disks)
i += disk->mountpoint.length;
}
free(buf);
}
+17 -23
View File
@@ -1,33 +1,27 @@
#include "displayserver.h"
#include "detection/internal.h"
uint32_t ffdsParseRefreshRate(int32_t refreshRate)
{
if(refreshRate <= 0)
return 0;
int remainder = refreshRate % 5;
if(remainder >= 3)
refreshRate += (5 - remainder);
else
refreshRate -= remainder;
//All other typicall refresh rates are dividable by 5
if(refreshRate == 145)
refreshRate = 144;
return (uint32_t) refreshRate;
}
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate)
bool ffdsAppendDisplay(
FFDisplayServerResult* result,
uint32_t width,
uint32_t height,
double refreshRate,
uint32_t scaledWidth,
uint32_t scaledHeight,
FFstrbuf* name,
FFDisplayType type)
{
if(width == 0 || height == 0)
return false;
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
resolution->width = width;
resolution->height = height;
resolution->refreshRate = refreshRate;
FFDisplayResult* display = ffListAdd(&result->displays);
display->width = width;
display->height = height;
display->refreshRate = refreshRate;
display->scaledWidth = scaledWidth;
display->scaledHeight = scaledHeight;
ffStrbufInitMove(&display->name, name);
display->type = type;
return true;
}
+52 -7
View File
@@ -5,12 +5,51 @@
#include "fastfetch.h"
typedef struct FFResolutionResult
#define FF_DE_PRETTY_PLASMA "KDE Plasma"
#define FF_DE_PRETTY_GNOME "Gnome"
#define FF_DE_PRETTY_XFCE4 "Xfce4"
#define FF_DE_PRETTY_CINNAMON "Cinnamon"
#define FF_DE_PRETTY_MATE "Mate"
#define FF_DE_PRETTY_LXDE "LXDE"
#define FF_DE_PRETTY_LXQT "LXQT"
#define FF_DE_PRETTY_BUDGIE "Budgie"
#define FF_DE_PRETTY_UNITY "Unity"
#define FF_WM_PRETTY_KWIN "KWin"
#define FF_WM_PRETTY_MUTTER "Mutter"
#define FF_WM_PRETTY_MUFFIN "Muffin"
#define FF_WM_PRETTY_MARCO "Marco"
#define FF_WM_PRETTY_XFWM4 "Xfwm4"
#define FF_WM_PRETTY_OPENBOX "Openbox"
#define FF_WM_PRETTY_I3 "i3"
#define FF_WM_PRETTY_WAYFIRE "Wayfire"
#define FF_WM_PRETTY_SWAY "Sway"
#define FF_WM_PRETTY_BSPWM "bspwm"
#define FF_WM_PRETTY_DWM "dwm"
#define FF_WM_PRETTY_WESTON "Weston"
#define FF_WM_PRETTY_XMONAD "XMonad"
#define FF_WM_PRETTY_WSLG "WSLg"
#define FF_WM_PROTOCOL_TTY "TTY"
#define FF_WM_PROTOCOL_X11 "X11"
#define FF_WM_PROTOCOL_WAYLAND "Wayland"
typedef enum FFDisplayType {
FF_DISPLAY_TYPE_UNKNOWN,
FF_DISPLAY_TYPE_BUILTIN,
FF_DISPLAY_TYPE_EXTERNAL,
} FFDisplayType;
typedef struct FFDisplayResult
{
uint32_t width;
uint32_t height;
uint32_t refreshRate;
} FFResolutionResult;
double refreshRate;
uint32_t scaledWidth;
uint32_t scaledHeight;
FFstrbuf name;
FFDisplayType type;
} FFDisplayResult;
typedef struct FFDisplayServerResult
{
@@ -20,13 +59,19 @@ typedef struct FFDisplayServerResult
FFstrbuf deProcessName;
FFstrbuf dePrettyName;
FFstrbuf deVersion;
FFlist resolutions; //List of FFResolutionResult
FFlist displays; //List of FFDisplayResult
} FFDisplayServerResult;
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance);
//Used internal
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate);
bool ffdsAppendDisplay(
FFDisplayServerResult* result,
uint32_t width,
uint32_t height,
double refreshRate,
uint32_t scaledWidth,
uint32_t scaledHeight,
FFstrbuf* name,
FFDisplayType type);
#endif
@@ -1,13 +1,18 @@
#include "displayserver.h"
#include "common/sysctl.h"
#include "util/apple/cf_helpers.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <CoreGraphics/CGDirectDisplay.h>
#include <CoreVideo/CVDisplayLink.h>
static void detectResolution(FFDisplayServerResult* ds)
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
static void detectDisplays(FFDisplayServerResult* ds, bool detectName)
{
CGDirectDisplayID screens[128];
uint32_t screenCount;
@@ -20,10 +25,42 @@ static void detectResolution(FFDisplayServerResult* ds)
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen);
if(mode)
{
ffdsAppendResolution(ds,
//https://github.com/glfw/glfw/commit/aab08712dd8142b642e2042e7b7ba563acd07a45
double refreshRate = CGDisplayModeGetRefreshRate(mode);
if (refreshRate == 0)
{
CVDisplayLinkRef link;
if(CVDisplayLinkCreateWithCGDisplay(screen, &link) == kCVReturnSuccess)
{
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
if (!(time.flags & kCVTimeIsIndefinite))
refreshRate = time.timeScale / (double) time.timeValue + 0.5; //59.97...
CVDisplayLinkRelease(link);
}
}
FF_STRBUF_AUTO_DESTROY name;
ffStrbufInit(&name);
if(detectName && CoreDisplay_DisplayCreateInfoDictionary)
{
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary(screen);
if(displayInfo)
{
CFDictionaryRef productNames;
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
ffCfDictGetString(productNames, CFSTR("en_US"), &name);
}
}
ffdsAppendDisplay(ds,
(uint32_t)CGDisplayModeGetPixelWidth(mode),
(uint32_t)CGDisplayModeGetPixelHeight(mode),
refreshRate,
(uint32_t)CGDisplayModeGetWidth(mode),
(uint32_t)CGDisplayModeGetHeight(mode),
(uint32_t)CGDisplayModeGetRefreshRate(mode)
&name,
CGDisplayIsBuiltin(screen) ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL
);
CGDisplayModeRelease(mode);
}
@@ -37,7 +74,7 @@ static void detectWMPlugin(FFstrbuf* name)
u_int requestLength = sizeof(request) / sizeof(*request);
size_t length = 0;
struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length);
FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length);
if(processes == NULL)
return;
@@ -58,21 +95,20 @@ static void detectWMPlugin(FFstrbuf* name)
name->chars[0] = (char) toupper(name->chars[0]);
break;
}
free(processes);
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
{
FF_UNUSED(instance);
ffStrbufInitS(&ds->wmProcessName, "quartz");
ffStrbufInitS(&ds->wmProcessName, "WindowServer");
ffStrbufInitS(&ds->wmPrettyName, "Quartz Compositor");
ffStrbufInit(&ds->wmProtocolName);
if(instance->config.allowSlowOperations)
{
FF_STRBUF_AUTO_DESTROY name;
ffStrbufInit(&name);
detectWMPlugin(&name);
if(name.length)
ffStrbufAppendF(&ds->wmPrettyName, " (with %s)", name.chars);
@@ -81,9 +117,9 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffStrbufAppendS(&ds->deProcessName, "aqua");
ffStrbufInit(&ds->deProcessName);
ffStrbufAppendS(&ds->dePrettyName, "Aqua");
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4);
detectResolution(ds);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
detectDisplays(ds, instance->config.displayDetectName);
}
@@ -10,5 +10,5 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
ffStrbufInitA(&ds->deProcessName, 0);
ffStrbufInitA(&ds->dePrettyName, 0);
ffStrbufInitA(&ds->deVersion, 0);
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 0);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 0);
}
@@ -1,13 +1,101 @@
#include "displayserver.h"
#include "detection/os/os.h"
#include "util/windows/unicode.h"
#include <dwmapi.h>
#include <WinUser.h>
static void detectDisplays(FFDisplayServerResult* ds, bool detectName)
{
DISPLAYCONFIG_PATH_INFO paths[128];
uint32_t pathCount = sizeof(paths) / sizeof(paths[0]);
DISPLAYCONFIG_MODE_INFO modes[256];
uint32_t modeCount = sizeof(modes) / sizeof(modes[0]);
if (QueryDisplayConfig(
QDC_ONLY_ACTIVE_PATHS,
&pathCount,
paths,
&modeCount,
modes,
NULL) == ERROR_SUCCESS)
{
for (uint32_t i = 0; i < pathCount; ++i)
{
DISPLAYCONFIG_PATH_INFO* path = &paths[i];
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {
.header = {
.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
.size = sizeof(sourceName),
.adapterId = path->sourceInfo.adapterId,
.id = path->sourceInfo.id,
},
};
uint32_t scaledWidth = 0, scaledHeight = 0;
if (DisplayConfigGetDeviceInfo(&sourceName.header) == ERROR_SUCCESS)
{
HDC hdc = CreateICW(sourceName.viewGdiDeviceName, NULL, NULL, NULL);
scaledWidth = (uint32_t) GetDeviceCaps(hdc, HORZRES);
scaledHeight = (uint32_t) GetDeviceCaps(hdc, VERTRES);
DeleteDC(hdc);
}
FF_STRBUF_AUTO_DESTROY name;
ffStrbufInit(&name);
if (detectName)
{
DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {
.header = {
.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME,
.size = sizeof(targetName),
.adapterId = path->targetInfo.adapterId,
.id = path->targetInfo.id,
},
};
if(DisplayConfigGetDeviceInfo(&targetName.header) == ERROR_SUCCESS)
{
if (targetName.flags.friendlyNameFromEdid)
ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName);
else
{
ffStrbufSetWS(&name, targetName.monitorDevicePath);
ffStrbufSubstrAfterFirstC(&name, '#');
ffStrbufSubstrBeforeFirstC(&name, '#');
}
}
}
uint32_t width = modes[path->sourceInfo.modeInfoIdx].sourceMode.width;
uint32_t height = modes[path->sourceInfo.modeInfoIdx].sourceMode.height;
if (path->targetInfo.rotation == DISPLAYCONFIG_ROTATION_ROTATE90 ||
path->targetInfo.rotation == DISPLAYCONFIG_ROTATION_ROTATE270)
{
uint32_t temp = width;
width = height;
height = temp;
}
ffdsAppendDisplay(ds,
width,
height,
path->targetInfo.refreshRate.Numerator / (double) path->targetInfo.refreshRate.Denominator,
scaledWidth,
scaledHeight,
&name,
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED
? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL
);
}
}
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
{
FF_UNUSED(instance);
BOOL enabled;
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled == TRUE)
{
@@ -23,19 +111,9 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffListInit(&ds->resolutions, sizeof(FFResolutionResult));
ffListInit(&ds->displays, sizeof(FFDisplayResult));
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) };
for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum)
{
if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
DEVMODEW devMode = { .dmSize = sizeof(DEVMODEW) };
if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0)
continue;
ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency);
}
detectDisplays(ds, instance->config.displayDetectName);
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
const FFOSResult* os = ffDetectOS(instance);
@@ -19,6 +19,9 @@ static void parseDRM(FFDisplayServerResult* result)
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
ffStrbufAppendS(&drmDir, entry->d_name);
ffStrbufAppendS(&drmDir, "/modes");
@@ -29,14 +32,16 @@ static void parseDRM(FFDisplayServerResult* result)
continue;
}
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
resolution->width = 0;
resolution->height = 0;
resolution->refreshRate = 0;
FFDisplayResult* display = ffListAdd(&result->displays);
display->width = 0;
display->height = 0;
display->refreshRate = 0;
display->scaledWidth = 0;
display->scaledHeight = 0;
int scanned = fscanf(modeFile, "%ux%u", &resolution->width, &resolution->height);
if(scanned < 2 || resolution->width == 0 || resolution->height == 0)
--result->resolutions.length;
int scanned = fscanf(modeFile, "%ux%u", &display->width, &display->height);
if(scanned < 2 || display->width == 0 || display->height == 0)
--result->displays.length;
fclose(modeFile);
ffStrbufSubstrBefore(&drmDir, drmDirLength);
@@ -54,31 +59,31 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
//We try wayland as our prefered display server, as it supports the most features.
//This method can't detect the name of our WM / DE
ffdsConnectWayland(instance, ds);
//Try the x11 libs, from most feature rich to least.
//We use the resolution list to detect if a connection is needed.
//They respect wmProtocolName, and only detect resolution if it is set.
//We use the display list to detect if a connection is needed.
//They respect wmProtocolName, and only detect display if it is set.
if(ds->resolutions.length == 0)
if(ds->displays.length == 0)
ffdsConnectXcbRandr(instance, ds);
if(ds->resolutions.length == 0)
if(ds->displays.length == 0)
ffdsConnectXrandr(instance, ds);
if(ds->resolutions.length == 0)
if(ds->displays.length == 0)
ffdsConnectXcb(instance, ds);
if(ds->resolutions.length == 0)
if(ds->displays.length == 0)
ffdsConnectXlib(instance, ds);
//This resolution detection method is display server independent.
//This display detection method is display server independent.
//Use it if all connections failed
if(ds->resolutions.length == 0)
if(ds->displays.length == 0)
parseDRM(ds);
//This fills in missing information about WM / DE by using env vars and iterating processes
@@ -5,10 +5,6 @@
#include "detection/displayserver/displayserver.h"
#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland"
#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11"
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result);
+153 -54
View File
@@ -5,20 +5,35 @@
#ifdef FF_HAVE_WAYLAND
#include "common/library.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/thread.h"
#include <wayland-client.h>
#include <sys/socket.h>
typedef struct WaylandData
{
FFlist* results;
FFDisplayServerResult* result;
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
FF_LIBRARY_SYMBOL(wl_display_roundtrip)
struct wl_display* display;
const struct wl_interface* ffwl_output_interface;
bool detectName;
} WaylandData;
typedef struct WaylandDisplay
{
int32_t width;
int32_t height;
int32_t refreshRate;
int32_t scale;
enum wl_output_transform transform;
FFDisplayType type;
FFstrbuf name;
bool detectName;
} WaylandDisplay;
#ifndef __FreeBSD__
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
{
@@ -47,25 +62,136 @@ static void stubListener(void* data, ...)
(void) data;
}
static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
{
WaylandData* wldata = data;
if(!(flags & WL_OUTPUT_MODE_CURRENT))
return;
wldata->ffwl_proxy_destroy((struct wl_proxy*) output);
WaylandDisplay* display = data;
display->width = width;
display->height = height;
display->refreshRate = refreshRate;
}
if(!(flags & WL_OUTPUT_MODE_CURRENT) || width <= 0 || height <= 0)
#ifdef WL_OUTPUT_SCALE_SINCE_VERSION
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale)
{
WaylandDisplay* display = data;
display->scale = scale;
}
#endif
static void waylandOutputGeometryListener(void *data,
FF_MAYBE_UNUSED struct wl_output *output,
FF_MAYBE_UNUSED int32_t x,
FF_MAYBE_UNUSED int32_t y,
FF_MAYBE_UNUSED int32_t physical_width,
FF_MAYBE_UNUSED int32_t physical_height,
FF_MAYBE_UNUSED int32_t subpixel,
const char *make,
const char *model,
int32_t transform)
{
WaylandDisplay* display = data;
display->transform = (enum wl_output_transform) transform;
if(display->detectName)
{
if(make && strcmp(make, "unknown") != 0)
ffStrbufAppendS(&display->name, make);
if(model && strcmp(model, "unknown") != 0)
{
if(display->name.length > 0)
ffStrbufAppendC(&display->name, '-');
ffStrbufAppendS(&display->name, model);
}
}
}
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
static void waylandOutputNameListener(void *data, FF_MAYBE_UNUSED struct wl_output *output, const char *name)
{
WaylandDisplay* display = data;
if(strncmp(name, "eDP-", strlen("eDP-")) == 0)
display->type = FF_DISPLAY_TYPE_BUILTIN;
else if(strncmp(name, "HDMI-", strlen("HDMI-")) == 0 || strncmp(name, "DP-", strlen("DP-")) == 0)
display->type = FF_DISPLAY_TYPE_EXTERNAL;
}
#endif
static void waylandOutputHandler(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
{
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
if(output == NULL)
return;
WaylandDisplay display = {
.detectName = wldata->detectName,
.width = 0,
.height = 0,
.refreshRate = 0,
.scale = 1,
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
.type = FF_DISPLAY_TYPE_UNKNOWN,
};
ffStrbufInit(&display.name);
struct wl_output_listener outputListener = {
.mode = waylandOutputModeListener,
.geometry = waylandOutputGeometryListener,
#ifdef WL_OUTPUT_DONE_SINCE_VERSION
.done = (void*) stubListener,
#endif
#ifdef WL_OUTPUT_SCALE_SINCE_VERSION
.scale = waylandOutputScaleListener,
#endif
#ifdef WL_OUTPUT_NAME_SINCE_VERSION
.name = waylandOutputNameListener,
#endif
#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
.description = (void*) stubListener,
#endif
};
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display);
wldata->ffwl_display_roundtrip(wldata->display);
wldata->ffwl_proxy_destroy(output);
if(display.width <= 0 || display.height <= 0)
return;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
ffThreadMutexLock(&mutex);
FFResolutionResult* result = ffListAdd(wldata->results);
switch(display.transform)
{
case WL_OUTPUT_TRANSFORM_90:
case WL_OUTPUT_TRANSFORM_270:
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_FLIPPED_270: {
int32_t temp = display.width;
display.width = display.height;
display.height = temp;
break;
}
default:
break;
}
ffdsAppendDisplay(wldata->result,
(uint32_t) display.width,
(uint32_t) display.height,
display.refreshRate / 1000.0,
(uint32_t) (display.width / display.scale),
(uint32_t) (display.height / display.scale),
&display.name,
display.type
);
ffThreadMutexUnlock(&mutex);
result->width = (uint32_t) width;
result->height = (uint32_t) height;
result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000);
}
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
@@ -73,31 +199,7 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
WaylandData* wldata = data;
if(strcmp(interface, wldata->ffwl_output_interface->name) == 0)
{
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
if(output == NULL)
return;
//Needs to be static, because the scope of the function will already be lost when calling the listener
static struct wl_output_listener outputListener = {
.mode = waylandOutputModeListener,
.geometry = (void*) stubListener,
//https://lists.freedesktop.org/archives/wayland-devel/2013-July/010278.html
#if WAYLAND_VERSION_MINOR >= 2
.done = (void*) stubListener,
.scale = (void*) stubListener,
#endif
//https://lists.freedesktop.org/archives/wayland-devel/2021-December/042064.html
#if WAYLAND_VERSION_MINOR >= 20
.name = (void*) stubListener,
.description = (void*) stubListener,
#endif
};
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, data);
}
waylandOutputHandler(wldata, registry, name, version);
}
bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
@@ -107,7 +209,6 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_roundtrip, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false)
@@ -117,26 +218,25 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_destroy, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_display_roundtrip, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false)
struct wl_display* display = ffwl_display_connect(NULL);
if(display == NULL)
{
dlclose(wayland);
data.display = ffwl_display_connect(NULL);
if(data.display == NULL)
return false;
}
waylandDetectWM(ffwl_display_get_fd(display), result);
data.detectName = instance->config.displayDetectName;
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
waylandDetectWM(ffwl_display_get_fd(data.display), result);
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
if(registry == NULL)
{
ffwl_display_disconnect(display);
dlclose(wayland);
ffwl_display_disconnect(data.display);
return false;
}
data.results = &result->resolutions;
data.result = result;
struct wl_registry_listener registry_listener = {
.global = waylandGlobalAddListener,
@@ -144,17 +244,16 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
};
data.ffwl_proxy_add_listener(registry, (void(**)(void)) &registry_listener, &data);
ffwl_display_dispatch(display);
ffwl_display_roundtrip(display);
ffwl_display_dispatch(data.display);
data.ffwl_display_roundtrip(data.display);
data.ffwl_proxy_destroy(registry);
ffwl_display_disconnect(display);
dlclose(wayland);
ffwl_display_disconnect(data.display);
//We successfully connected to wayland and detected the resolution.
//We successfully connected to wayland and detected the display.
//So we can set set the session type to wayland.
//This is used as an indicator that we are running wayland by the x11 backends.
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
return true;
}
#endif
@@ -185,5 +284,5 @@ void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* resul
//We are probably running a wayland compositor at this point,
//but fastfetch was compiled without the required library, or loading the library failed.
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
}
+70 -46
View File
@@ -1,8 +1,9 @@
#include "displayserver_linux.h"
#include "common/io.h"
#include "common/io/io.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#include <stdlib.h>
#include <ctype.h>
@@ -48,7 +49,7 @@ static const char* parseEnv()
if(
getenv("WAYLAND_DISPLAY") != NULL &&
ffFileExists("/mnt/wslg/", S_IFDIR)
ffPathExists("/mnt/wslg/", FF_PATHTYPE_DIRECTORY)
) return "WSLg";
return NULL;
@@ -65,31 +66,34 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* proce
strcasecmp(processName, "kwin_x11") == 0 ||
strcasecmp(processName, "kwin_x11_wrapper") == 0 ||
strcasecmp(processName, "kwin") == 0
) ffStrbufSetS(&result->wmPrettyName, "KWin");
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN);
else if(
strcasecmp(processName, "gnome-shell") == 0 ||
strcasecmp(processName, "gnome shell") == 0 ||
strcasecmp(processName, "gnome-session-binary") == 0 ||
strcasecmp(processName, "Mutter") == 0
) ffStrbufSetS(&result->wmPrettyName, "Mutter");
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER);
else if(
strcasecmp(processName, "cinnamon-session") == 0 ||
strcasecmp(processName, "Muffin") == 0
) ffStrbufSetS(&result->wmPrettyName, "Muffin");
strcasecmp(processName, "Muffin") == 0 ||
strcasecmp(processName, "Mutter (Muffin)") == 0
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUFFIN);
else if(strcasecmp(processName, "sway") == 0)
ffStrbufSetS(&result->wmPrettyName, "Sway");
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_SWAY);
else if(strcasecmp(processName, "weston") == 0)
ffStrbufSetS(&result->wmPrettyName, "Weston");
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WESTON);
else if(strcasecmp(processName, "wayfire") == 0)
ffStrbufSetS(&result->wmPrettyName, "Wayfire");
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WAYFIRE);
else if(strcasecmp(processName, "openbox") == 0)
ffStrbufSetS(&result->wmPrettyName, "Openbox");
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_OPENBOX);
else if(strcasecmp(processName, "xfwm4") == 0)
ffStrbufSetS(&result->wmPrettyName, "Xfwm4");
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XFWM4);
else if(strcasecmp(processName, "Marco") == 0)
ffStrbufSetS(&result->wmPrettyName, "Marco");
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MARCO);
else if(strcasecmp(processName, "xmonad") == 0)
ffStrbufSetS(&result->wmPrettyName, "XMonad");
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XMONAD);
else if(strcasecmp(processName, "WSLg") == 0)
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WSLG);
else if( // WMs where the pretty name matches the process name
strcasecmp(processName, "dwm") == 0 ||
strcasecmp(processName, "bspwm") == 0 ||
@@ -116,44 +120,50 @@ static void applyBetterWM(FFDisplayServerResult* result, const char* processName
ffStrbufAppend(&result->wmPrettyName, &result->wmProcessName);
}
static void getKDE(FFDisplayServerResult* result)
static void getKDE(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "plasmashell");
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_PLASMA);
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
ffParsePropFileData(instance, "xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
ffParsePropFileData(instance, "xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
ffParsePropFileData(instance, "wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/local/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/local/share/wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
ffParsePropFileData(instance, "wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
applyBetterWM(result, getenv("KDEWM"));
}
static void getGnome(FFDisplayServerResult* result)
static void getGnome(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "gnome-shell");
ffStrbufSetS(&result->dePrettyName, "GNOME");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_GNOME);
ffParsePropFileData(instance, "gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
if (result->deVersion.length == 0)
{
if (ffProcessAppendStdOut(&result->deVersion, (char* const[]){
"gnome-shell",
"--version",
NULL
}) == NULL) // GNOME Shell 44.1
ffStrbufSubstrAfterLastC(&result->deVersion, ' ');
}
}
static void getCinnamon(FFDisplayServerResult* result)
static void getCinnamon(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "cinnamon");
ffStrbufSetS(&result->dePrettyName, "Cinnamon");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON);
ffParsePropFileData(instance, "applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
}
static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "mate-session");
ffStrbufSetS(&result->dePrettyName, "MATE");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE);
FFstrbuf major;
ffStrbufInit(&major);
@@ -164,7 +174,7 @@ static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
FFstrbuf micro;
ffStrbufInit(&micro);
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR"/share/mate-about/mate-version.xml", 3, (FFpropquery[]) {
ffParsePropFileDataValues(instance, "mate-about/mate-version.xml", 3, (FFpropquery[]) {
{"<platform>", &major},
{"<minor>", &minor},
{"<micro>", &micro}
@@ -192,8 +202,8 @@ static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "xfce4-session");
ffStrbufSetS(&result->dePrettyName, "Xfce4");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
ffParsePropFileData(instance, "gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
@@ -213,13 +223,13 @@ static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result)
static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "lxqt-session");
ffStrbufSetS(&result->dePrettyName, "LXQt");
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion);
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT);
ffParsePropFileData(instance, "gconfig/lxqt.pc", "Version:", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
ffParsePropFileData(instance, "cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
if(result->deVersion.length == 0)
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
ffParsePropFileData(instance, "cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
@@ -243,6 +253,13 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
ffStrbufDestroy(&wmProcessNameBuffer);
}
static void getBudgie(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE);
ffParsePropFileData(instance, "budgie/budgie-version.xml", "<str>", &result->deVersion);
}
static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResult* result, const char* name)
{
if(!ffStrSet(name))
@@ -253,19 +270,19 @@ static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResul
strcasecmp(name, "plasma") == 0 ||
strcasecmp(name, "plasmashell") == 0 ||
strcasecmp(name, "plasmawayland") == 0
) getKDE(result);
) getKDE(instance, result);
else if(
strcasecmp(name, "Gnome") == 0 ||
strcasecmp(name, "ubuntu:GNOME") == 0 ||
strcasecmp(name, "ubuntu") == 0 ||
strcasecmp(name, "gnome-shell") == 0
) getGnome(result);
) getGnome(instance, result);
else if(
strcasecmp(name, "X-Cinnamon") == 0 ||
strcasecmp(name, "Cinnamon") == 0
) getCinnamon(result);
) getCinnamon(instance, result);
else if(
strcasecmp(name, "XFCE") == 0 ||
@@ -286,6 +303,13 @@ static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResul
strcasecmp(name, "X-LXQT") == 0 ||
strcasecmp(name, "lxqt-session") == 0
) getLXQt(instance, result);
else if(
strcasecmp(name, "Budgie") == 0 ||
strcasecmp(name, "X-Budgie") == 0 ||
strcasecmp(name, "budgie-desktop") == 0 ||
strcasecmp(name, "Budgie:GNOME") == 0
) getBudgie(instance, result);
}
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
@@ -297,9 +321,9 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
if(ffStrSet(env))
{
if(strcasecmp(env, "x11") == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
else if(strcasecmp(env, "tty") == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
else
ffStrbufSetS(&result->wmProtocolName, env);
@@ -309,14 +333,14 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
env = getenv("DISPLAY");
if(ffStrSet(env))
{
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
return;
}
env = getenv("TERM");
if(ffStrSet(env))
if(ffStrSet(env) && strcasecmp(env, "linux") == 0)
{
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
return;
}
}
@@ -398,7 +422,7 @@ void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result)
//We don't want to detect anything in TTY
//This can't happen if a connection succeeded, so we don't need to clear wmProcessName
if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY) == 0)
if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
return;
const char* env = parseEnv();
+35 -26
View File
@@ -62,7 +62,7 @@ static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection,
static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t rootWindow, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0)
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0)
return;
xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK");
@@ -103,10 +103,7 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
xcb_connection_t* connection = ffxcb_connect(NULL, NULL);
if(connection == NULL)
{
dlclose(xcb);
return;
}
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(connection));
@@ -115,21 +112,23 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
while(iterator.rem > 0)
{
ffdsAppendResolution(
result,
ffdsAppendDisplay(result,
(uint32_t) iterator.data->width_in_pixels,
(uint32_t) iterator.data->height_in_pixels,
0
0,
(uint32_t) iterator.data->width_in_pixels,
(uint32_t) iterator.data->height_in_pixels,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
ffxcb_screen_next(&iterator);
}
ffxcb_disconnect(connection);
dlclose(xcb);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
}
#else
@@ -176,21 +175,23 @@ typedef struct XcbRandrData
static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo)
{
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
modeInfo->dot_clock / (uint32_t) (modeInfo->htotal * modeInfo->vtotal)
));
double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal);
return ffdsAppendResolution(
return ffdsAppendDisplay(
data->result,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
refreshRate == 0 ? data->defaultRefreshRate : refreshRate
refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
}
static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode)
{
//We do the check here, because we want the best fallback resolution if this call failed
//We do the check here, because we want the best fallback display if this call failed
if(data->screenResources == NULL)
return false;
@@ -215,11 +216,15 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
return false;
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode);
res = res ? true : ffdsAppendResolution(
res = res ? true : ffdsAppendDisplay(
data->result,
(uint32_t) crtcInfoReply->width,
(uint32_t) crtcInfoReply->height,
data->defaultRefreshRate
data->defaultRefreshRate,
(uint32_t) crtcInfoReply->width,
(uint32_t) crtcInfoReply->height,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
free(crtcInfoReply);
@@ -258,11 +263,15 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
data->ffxcb_randr_output_next(&outputIterator);
};
return foundOutput ? true : ffdsAppendResolution(
return foundOutput ? true : ffdsAppendDisplay(
data->result,
(uint32_t) monitor->width,
(uint32_t) monitor->height,
data->defaultRefreshRate
data->defaultRefreshRate,
(uint32_t) monitor->width,
(uint32_t) monitor->height,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
}
@@ -316,11 +325,15 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
return;
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
ffdsAppendResolution(
ffdsAppendDisplay(
data->result,
(uint32_t) screen->width_in_pixels,
(uint32_t) screen->height_in_pixels,
data->defaultRefreshRate
data->defaultRefreshRate,
(uint32_t) screen->width_in_pixels,
(uint32_t) screen->height_in_pixels,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
}
@@ -358,10 +371,7 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu
data.connection = ffxcb_connect(NULL, NULL);
if(data.connection == NULL)
{
dlclose(xcbRandr);
return;
}
data.result = result;
@@ -377,11 +387,10 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu
}
ffxcb_disconnect(data.connection);
dlclose(xcbRandr);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
}
#else
+38 -28
View File
@@ -3,6 +3,7 @@
#ifdef FF_HAVE_X11
#include "common/library.h"
#include "common/parsing.h"
#include "util/stringUtils.h"
#include <X11/Xlib.h>
typedef struct X11PropertyData
@@ -39,7 +40,7 @@ static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Wi
static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND) == 0)
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0)
return;
Window* wmWindow = (Window*) x11GetProperty(data, display, DefaultRootWindow(display), "_NET_SUPPORTING_WM_CHECK");
@@ -68,10 +69,7 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
Display* display = ffXOpenDisplay(x11);
if(display == NULL)
{
dlclose(x11);
return;
}
if(propertyDataInitialized && ScreenCount(display) > 0)
x11DetectWMFromEWMH(&propertyData, display, result);
@@ -79,20 +77,22 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
for(int i = 0; i < ScreenCount(display); i++)
{
Screen* screen = ScreenOfDisplay(display, i);
ffdsAppendResolution(
result,
(uint32_t) screen->width,
(uint32_t) screen->height,
0
ffdsAppendDisplay(result,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
0,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
}
ffXCloseDisplay(display);
dlclose(x11);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
}
#else
@@ -134,15 +134,17 @@ typedef struct XrandrData
static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo)
{
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)
));
double refreshRate = (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal);
return ffdsAppendResolution(
return ffdsAppendDisplay(
data->result,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
refreshRate == 0 ? data->defaultRefreshRate : refreshRate
refreshRate == 0 ? data->defaultRefreshRate : refreshRate,
(uint32_t) modeInfo->width,
(uint32_t) modeInfo->height,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
}
@@ -158,7 +160,7 @@ static bool xrandrHandleMode(XrandrData* data, RRMode mode)
static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
{
//We do the check here, because we want the best fallback resolution if this call failed
//We do the check here, because we want the best fallback display if this call failed
if(data->screenResources == NULL)
return false;
@@ -167,11 +169,15 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
return false;
bool res = xrandrHandleMode(data, crtcInfo->mode);
res = res ? true : ffdsAppendResolution(
res = res ? true : ffdsAppendDisplay(
data->result,
(uint32_t) crtcInfo->width,
(uint32_t) crtcInfo->height,
data->defaultRefreshRate
data->defaultRefreshRate,
(uint32_t) crtcInfo->width,
(uint32_t) crtcInfo->height,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
data->ffXRRFreeCrtcInfo(crtcInfo);
@@ -201,11 +207,15 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
foundOutput = true;
}
return foundOutput ? true : ffdsAppendResolution(
return foundOutput ? true : ffdsAppendDisplay(
data->result,
(uint32_t) monitorInfo->width,
(uint32_t) monitorInfo->height,
data->defaultRefreshRate
data->defaultRefreshRate,
(uint32_t) monitorInfo->width,
(uint32_t) monitorInfo->height,
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
}
@@ -253,11 +263,15 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
return;
//Fallback to screen
ffdsAppendResolution(
ffdsAppendDisplay(
data->result,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
data->defaultRefreshRate
data->defaultRefreshRate,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
NULL,
FF_DISPLAY_TYPE_UNKNOWN
);
}
@@ -287,10 +301,7 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result
data.display = ffXOpenDisplay(NULL);
if(data.display == NULL)
{
dlclose(xrandr);
return;
}
if(propertyDataInitialized && ScreenCount(data.display) > 0)
x11DetectWMFromEWMH(&propertyData, data.display, result);
@@ -301,11 +312,10 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result
xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i));
ffXCloseDisplay(data.display);
dlclose(xrandr);
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
if(result->wmProtocolName.length == 0)
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
}
#else
+1
View File
@@ -9,6 +9,7 @@ static void detectFont(const FFinstance* instance, FFFontResult* font)
for(uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i)
ffStrbufInit(&font->fonts[i]);
ffStrbufInit(&font->display);
ffDetectFontImpl(instance, font);
+1
View File
@@ -18,6 +18,7 @@ typedef struct FFFontResult
* Other: Unset, Unset, Unset, Unset
*/
FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS];
FFstrbuf display;
} FFFontResult;
const FFFontResult* ffDetectFont(const FFinstance* instance);
+19 -1
View File
@@ -1,9 +1,26 @@
#include "common/font.h"
#include "common/io.h"
#include "common/io/io.h"
#include "font.h"
#import <AppKit/NSFont.h>
static void generateString(FFFontResult* font)
{
if(font->fonts[0].length > 0)
{
ffStrbufAppend(&font->display, &font->fonts[0]);
ffStrbufAppendS(&font->display, " [System]");
if(font->fonts[1].length > 0)
ffStrbufAppendS(&font->display, ", ");
}
if(font->fonts[1].length > 0)
{
ffStrbufAppend(&font->display, &font->fonts[1]);
ffStrbufAppendS(&font->display, " [User]");
}
}
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
{
FF_UNUSED(instance);
@@ -11,4 +28,5 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
ffStrbufAppendS(&result->fonts[1], [NSFont userFontOfSize:12].familyName.UTF8String);
ffStrbufAppendS(&result->fonts[2], [NSFont monospacedSystemFontOfSize:12 weight:400].familyName.UTF8String);
ffStrbufAppendS(&result->fonts[3], [NSFont userFixedPitchFontOfSize:12].familyName.UTF8String);
generateString(result);
}
+33 -2
View File
@@ -1,10 +1,39 @@
#include "detection/qt.h"
#include "detection/gtk.h"
#include "common/font.h"
#include "common/parsing.h"
#include "detection/displayserver/displayserver.h"
#include "detection/gtk_qt/gtk_qt.h"
#include "font.h"
static void generateString(FFFontResult* font)
{
if(font->fonts[0].length > 0)
{
ffStrbufAppend(&font->display, &font->fonts[0]);
ffStrbufAppendS(&font->display, " [QT]");
for(uint8_t i = 1; i < sizeof(font->fonts) / sizeof(font->fonts[0]); i++)
{
if(font->fonts[i].length > 0)
{
ffStrbufAppendS(&font->display, ", ");
break;
}
}
}
ffParseGTK(&font->display, &font->fonts[1], &font->fonts[2], &font->fonts[3]);
}
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
{
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
{
ffStrbufAppendS(&result->error, "Font isn't supported in TTY");
return;
}
FFfont qt;
ffFontInitQt(&qt, ffDetectQt(instance)->font.chars);
ffStrbufAppend(&result->fonts[0], &qt.pretty);
@@ -24,4 +53,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
ffFontInitPango(&gtk4, ffDetectGTK4(instance)->font.chars);
ffStrbufAppend(&result->fonts[3], &gtk4.pretty);
ffFontDestroy(&gtk4);
generateString(result);
}
+23 -1
View File
@@ -1,7 +1,27 @@
#include "font.h"
#include "util/windows/unicode.h"
#include <winuser.h>
#include <windows.h>
static void generateString(FFFontResult* font)
{
const char* types[] = { "Caption", "Menu", "Message", "Status" };
for(uint32_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i)
{
if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i]))
{
if(i > 0)
ffStrbufAppendS(&font->display, "], ");
ffStrbufAppendF(&font->display, "%s [%s", font->fonts[i].chars, types[i]);
}
else
{
ffStrbufAppendS(&font->display, " / ");
ffStrbufAppendS(&font->display, types[i]);
}
}
ffStrbufAppendC(&font->display, ']');
}
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
{
@@ -19,4 +39,6 @@ void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
if(fonts[i]->lfHeight < 0)
ffStrbufAppendF(&result->fonts[i], " (%dpt)", (int)-fonts[i]->lfHeight);
}
generateString(result);
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#ifndef FF_INCLUDED_detection_gamepad_gamepad
#define FF_INCLUDED_detection_gamepad_gamepad
#include "fastfetch.h"
typedef struct FFGamepadDevice
{
FFstrbuf identifier;
FFstrbuf name;
} FFGamepadDevice;
const char* ffDetectGamepad(const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */);
#endif
+41
View File
@@ -0,0 +1,41 @@
#include "gamepad.h"
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
static void enumSet(const void* value, void *context)
{
CFStringRef product = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDProductKey));
CFStringRef serialNumber = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDSerialNumberKey));
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd((FFlist*) context);
ffStrbufInit(&device->identifier);
ffCfStrGetString(serialNumber, &device->identifier);
ffStrbufInit(&device->name);
ffCfStrGetString(product, &device->name);
}
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
{
IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
return "IOHIDManagerOpen() failed";
CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop);
CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
CFSTR(kIOHIDDeviceUsagePageKey),
CFSTR(kIOHIDDeviceUsageKey)
}, (const void **)(CFNumberRef[]){
genericDesktop,
gamePad
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
IOHIDManagerSetDeviceMatching(manager, matching);
CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager);
if (set)
CFSetApplyFunction(set, &enumSet, devices);
IOHIDManagerClose(manager, 0);
return NULL;
}
+42
View File
@@ -0,0 +1,42 @@
#include "gamepad.h"
#include "common/io/io.h"
#include <dirent.h>
#include <ctype.h>
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
{
DIR* dirp = opendir("/sys/class/input/");
if(dirp == NULL)
return "opendir(\"/sys/class/input/\") == NULL";
FF_STRBUF_AUTO_DESTROY path;
ffStrbufInitS(&path, "/sys/class/input/");
uint32_t baseLen = path.length;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(strncmp(entry->d_name, "js", 2) != 0)
continue;
if(!isdigit(entry->d_name[2]))
continue;
ffStrbufAppendS(&path, entry->d_name);
ffStrbufAppendS(&path, "/device/name");
if (ffPathExists(path.chars, FF_PATHTYPE_FILE))
{
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitS(&device->identifier, entry->d_name);
ffStrbufInit(&device->name);
ffAppendFileBuffer(path.chars, &device->name);
}
ffStrbufSubstrBefore(&path, baseLen);
}
closedir(dirp);
return NULL;
}
@@ -0,0 +1,6 @@
#include "gamepad.h"
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFGamepadDevice */)
{
return "Not supported on this platform";
}
+138
View File
@@ -0,0 +1,138 @@
#include "gamepad.h"
#include "common/io/io.h"
#include "util/mallocHelper.h"
#include "util/windows/unicode.h"
#include <windows.h>
#include <hidsdi.h>
static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
{
switch (vendorId)
{
// Nintendo
case 0x057E:
{
switch (productId)
{
case 0x2006: return "Nintendo Switch Joycon L";
case 0x2007: return "Nintendo Switch Joycon R";
case 0x2009: return "Nintendo Switch Pro Controller";
case 0x200E: return "Nintendo Switch Charging Grip";
case 0x2017: return "Nintendo Switch SNES Controller";
default: return NULL;
}
}
// Sony
case 0x054C:
{
switch (productId)
{
case 0x0268: return "Sony Playstation 3 Controller";
case 0x05C4: return "Sony DualShock 4 Gen1";
case 0x09CC: return "Sony DualShock 4 Gen2";
case 0x0BA0: return "Sony PS4 Controller USB receiver";
case 0x0CE6: return "Sony DualSense";
default: return NULL;
}
}
// Microsoft
case 0x045E:
{
switch (productId)
{
case 0x02E0: return "Microsoft X-Box One S pad (Wireless)";
case 0x02FD: return "Microsoft X-Box One S pad (Wireless, 2016 FW)";
case 0x0B05: return "Microsoft X-Box One Elite Series 2 pad (Wireless)";
case 0x0B13: return "Microsoft X-Box Series X (Wireless)";
case 0x028E: return "Microsoft XBox 360";
case 0x028F: return "Microsoft XBox 360 v2";
case 0x02A1: return "Microsoft XBox 360";
case 0x0291: return "Microsoft XBox 360 USB receiver";
case 0x02A0: return "Microsoft XBox 360 Big Button IR";
case 0x02DD: return "Microsoft XBox One";
case 0xB326: return "Microsoft XBox One Firmware 2015";
case 0x02E3: return "Microsoft XBox One Elite";
case 0x02FF: return "Microsoft XBox One Elite";
case 0x02EA: return "Microsoft XBox One S";
default: return NULL;
}
}
// Logitech
case 0x046D:
{
switch (productId)
{
case 0xC216: return "Logitech F310, DirectInput";
case 0xC218: return "Logitech F510, DirectInput";
case 0xC219: return "Logitech F710, DirectInput";
case 0xC21D: return "Logitech F310";
case 0xC21E: return "Logitech F510";
case 0xC21F: return "Logitech F710";
default: return NULL;
}
}
default: return NULL;
}
}
const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */)
{
UINT nDevices = 0;
if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)))
return "GetRawInputDeviceList(NULL) failed";
if (nDevices == 0)
return "No HID devices found";
RAWINPUTDEVICELIST* FF_AUTO_FREE pRawInputDeviceList = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices);
if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1)
return "GetRawInputDeviceList(pRawInputDeviceList) failed";
for (UINT i = 0; i < nDevices; ++i) {
if (pRawInputDeviceList[i].dwType != 2) continue;
HANDLE hDevice = pRawInputDeviceList[i].hDevice;
RID_DEVICE_INFO rdi;
UINT rdiSize = sizeof(rdi);
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1)
continue;
if (rdi.hid.usUsagePage != 1 || rdi.hid.usUsage != 5) // Gamepad
continue;
WCHAR devName[MAX_PATH] = L"";
UINT nameSize = MAX_PATH;
if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, devName, &nameSize) == (UINT) -1)
continue;
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitWS(&device->identifier, devName);
ffStrbufInit(&device->name);
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
if (knownGamepad)
ffStrbufSetS(&device->name, knownGamepad);
else
{
wchar_t displayName[126];
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
ffStrbufSetWS(&device->name, displayName);
else
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", rdi.hid.dwVendorId, rdi.hid.dwProductId);
}
}
return NULL;
}
+31 -5
View File
@@ -1,16 +1,42 @@
#include "gpu.h"
#include "detection/internal.h"
#include "detection/vulkan.h"
#include "detection/vulkan/vulkan.h"
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance);
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance);
const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
static inline bool arrayContains(const unsigned arr[], unsigned vendorId, unsigned length)
{
for (unsigned i = 0; i < length; ++i)
{
if (arr[i] == vendorId)
return true;
}
return false;
}
const char* ffGetGPUVendorString(unsigned vendorId)
{
if(vendorId == 0x106b)
return FF_GPU_VENDOR_NAME_APPLE;
if(arrayContains((const unsigned[]) {0x1002, 0x1022}, vendorId, 2))
return FF_GPU_VENDOR_NAME_AMD;
else if(arrayContains((const unsigned[]) {0x03e7, 0x8086, 0x8087}, vendorId, 3))
return FF_GPU_VENDOR_NAME_INTEL;
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
return FF_GPU_VENDOR_NAME_NVIDIA;
return NULL;
}
const FFlist* ffDetectGPU(const FFinstance* instance)
{
FF_DETECTION_INTERNAL_GUARD(FFlist,
ffListInit(&result, sizeof(FFGPUResult));
ffDetectGPUImpl(&result, instance);
if(result.length == 0)
if(instance->config.gpuForceVulkan || ffDetectGPUImpl(&result, instance) != NULL)
{
const FFVulkanResult* vulkan = ffDetectVulkan(instance);
result = vulkan->gpus;
+24 -3
View File
@@ -7,20 +7,41 @@
#define FF_GPU_TEMP_UNSET (0/0.0)
#define FF_GPU_CORE_COUNT_UNSET -1
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1)
#define FF_GPU_VENDOR_NAME_AMD "AMD"
#define FF_GPU_VENDOR_NAME_INTEL "Intel"
#define FF_GPU_VENDOR_NAME_NVIDIA "NVIDIA"
extern const char* FF_GPU_VENDOR_NAME_APPLE;
extern const char* FF_GPU_VENDOR_NAME_AMD;
extern const char* FF_GPU_VENDOR_NAME_INTEL;
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
typedef enum FFGpuType
{
FF_GPU_TYPE_UNKNOWN,
FF_GPU_TYPE_INTEGRATED,
FF_GPU_TYPE_DISCRETE,
} FFGpuType;
typedef struct FFGPUMemory
{
uint64_t total;
uint64_t used;
} FFGPUMemory;
typedef struct FFGPUResult
{
FFGpuType type;
FFstrbuf vendor;
FFstrbuf name;
FFstrbuf driver;
double temperature;
int coreCount;
FFGPUMemory dedicated;
FFGPUMemory shared;
uint32_t vulkanDeviceId; // Only used for vulkan
} FFGPUResult;
const FFlist* ffDetectGPU(const FFinstance* instance);
const char* ffGetGPUVendorString(unsigned vendorId);
#endif
+15 -1
View File
@@ -5,6 +5,7 @@
#include "util/apple/cf_helpers.h"
#include <IOKit/graphics/IOGraphicsLib.h>
#include <wchar.h>
static double detectGpuTemp(const FFstrbuf* gpuName)
{
@@ -59,7 +60,20 @@ const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
FFGPUResult* gpu = ffListAdd(gpus);
ffStrbufInitA(&gpu->vendor, 0);
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
ffStrbufInit(&gpu->vendor);
int vendorId;
if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId))
{
const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId);
ffStrbufAppendS(&gpu->vendor, vendorStr);
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL)
gpu->type = FF_GPU_TYPE_INTEGRATED;
else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD)
gpu->type = FF_GPU_TYPE_DISCRETE;
}
ffStrbufInit(&gpu->driver);
ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver);
+91 -40
View File
@@ -1,14 +1,16 @@
#include "gpu.h"
#include "detection/vulkan.h"
#include "detection/gpu/gpu.h"
#include "detection/vulkan/vulkan.h"
#ifdef FF_HAVE_LIBPCI
#include "common/library.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "detection/temps/temps_linux.h"
#include "util/stringUtils.h"
#include <string.h>
#include <unistd.h>
#include <pci/pci.h>
#include <setjmp.h>
typedef struct PCIData
{
@@ -23,25 +25,9 @@ typedef struct PCIData
#endif
} PCIData;
static bool pciIDsContains(u16 searched, const u16* ids)
{
while(*ids != 0)
{
if(*ids == searched)
return true;
ids++;
}
return false;
}
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
if(pciIDsContains(device->vendor_id, (const u16[]) {0x1002, 0x1022, 0}))
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x03e7, 0x8086, 0x8087, 0}))
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(pciIDsContains(device->vendor_id, (const u16[]) {0x0955, 0x10de, 0x12d2, 0}))
ffStrbufAppendS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
ffStrbufAppendS(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
if(gpu->vendor.length > 0)
return;
@@ -50,18 +36,18 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) gpu->vendor.allocated, PCI_LOOKUP_VENDOR, device->vendor_id);
ffStrbufRecalculateLength(&gpu->vendor);
if(ffStrbufFirstIndexS(&gpu->vendor, "AMD") < gpu->vendor.length || ffStrbufFirstIndexS(&gpu->vendor, "ATI") < gpu->vendor.length)
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(ffStrbufFirstIndexS(&gpu->vendor, "Intel") < gpu->vendor.length)
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(ffStrbufFirstIndexS(&gpu->vendor, "NVIDIA") < gpu->vendor.length)
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
}
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
static void drmDetectDeviceName(const FFinstance* instance, FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
u8 revId;
bool revIdSet = false;;
bool revIdSet = false;
#if PCI_LIB_VERSION >= 0x030800
revIdSet = pci->ffpci_fill_info(device, PCI_FILL_CLASS_EXT) & PCI_FILL_CLASS_EXT;
@@ -82,7 +68,7 @@ static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufInit(&query);
ffStrbufAppendF(&query, "%X, %X,", device->device_id, revId);
ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/libdrm/amdgpu.ids", query.chars, &gpu->name);
ffParsePropFileData(instance, "libdrm/amdgpu.ids", query.chars, &gpu->name);
ffStrbufDestroy(&query);
@@ -94,11 +80,11 @@ static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufRemoveStringsA(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
}
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
static void pciDetectDeviceName(const FFinstance* instance, FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
{
if(ffStrbufCompS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD) == 0)
{
drmDetectDeviceName(gpu, pci, device);
drmDetectDeviceName(instance, gpu, pci, device);
if(gpu->name.length > 0)
return;
}
@@ -146,20 +132,16 @@ static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev*
ffStrbufDestroy(&path);
}
static void pciDetectTemperatur(const FFinstance* instance, FFGPUResult* gpu, struct pci_dev* device)
static void pciDetectTemperatur(FFGPUResult* gpu, struct pci_dev* device)
{
const FFTempsResult* tempsResult = ffDetectTemps(instance);
const FFTempsResult* tempsResult = ffDetectTemps();
for(uint32_t i = 0; i < tempsResult->values.length; i++)
{
FFTempValue* tempValue = ffListGet(&tempsResult->values, i);
uint32_t tempClass;
if(sscanf(tempValue->deviceClass.chars, "%x", &tempClass) != 1)
continue;
//The kernel exposes the device class multiplied by 256 for some reason
if(tempClass == device->device_class * 256)
if(tempValue->deviceClass == device->device_class * 256)
{
gpu->temperature = tempValue->value;
return;
@@ -167,6 +149,38 @@ static void pciDetectTemperatur(const FFinstance* instance, FFGPUResult* gpu, st
}
}
static void detectType(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* device)
{
//There is no straightforward way to detect the type of a GPU.
//The approach taken here is to look at the memory sizes of the device.
//Since integrated GPUs usually use the system ram, they don't have expansive ROMs
//and their memory sizes are usually smaller than 1GB.
if(!(pci->ffpci_fill_info(device, PCI_FILL_SIZES) & PCI_FILL_SIZES))
{
gpu->type = FF_GPU_TYPE_UNKNOWN;
return;
}
if(device->rom_size > 0)
{
gpu->type = FF_GPU_TYPE_DISCRETE;
return;
}
uint32_t numSizes = sizeof(device->size) / sizeof(device->size[0]);
for(uint32_t i = 0; i < numSizes; i++)
{
if(device->size[i] >= 1024 * 1024 * 1024) //1GB
{
gpu->type = FF_GPU_TYPE_DISCRETE;
return;
}
}
gpu->type = FF_GPU_TYPE_INTEGRATED;
}
static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData* pci, struct pci_dev* device)
{
pci->ffpci_fill_info(device, PCI_FILL_CLASS);
@@ -175,7 +189,9 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
if(
//https://pci-ids.ucw.cz/read/PD/03
strcasecmp("VGA compatible controller", class) != 0 &&
strcasecmp("XGA compatible controller", class) != 0 &&
strcasecmp("3D controller", class) != 0 &&
strcasecmp("Display controller", class) != 0
) return;
@@ -184,20 +200,48 @@ static void pciHandleDevice(const FFinstance* instance, FFlist* results, PCIData
FFGPUResult* gpu = ffListAdd(results);
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
ffStrbufInit(&gpu->vendor);
pciDetectVendorName(gpu, pci, device);
ffStrbufInit(&gpu->name);
pciDetectDeviceName(gpu, pci, device);
pciDetectDeviceName(instance, gpu, pci, device);
ffStrbufInit(&gpu->driver);
pciDetectDriverName(gpu, pci, device);
detectType(gpu, pci, device);
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
if(instance->config.gpuTemp)
pciDetectTemperatur(instance, gpu, device);
pciDetectTemperatur(gpu, device);
}
jmp_buf pciInitJmpBuf;
static void __attribute__((__noreturn__))
handlePciInitError(FF_MAYBE_UNUSED char *msg, ...)
{
longjmp(pciInitJmpBuf, 1);
}
// https://github.com/pciutils/pciutils/blob/bca0412843fa650c749128ade03f35ab3e8fe2b9/lib/init.c#L186
static void __attribute__((__noreturn__))
handlePciGenericError(char *msg, ...)
{
va_list args;
va_start(args, msg);
fputs("pcilib: ", stderr);
vfprintf(stderr, msg, args);
va_end(args);
fputc('\n', stderr);
exit(1);
}
static void handlePciWarning(FF_MAYBE_UNUSED char *msg, ...)
{
// noop
}
static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
@@ -220,7 +264,14 @@ static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
#endif
pci.access = ffpci_alloc();
ffpci_init(pci.access);
pci.access->warning = handlePciWarning;
pci.access->error = handlePciInitError;
if(setjmp(pciInitJmpBuf) == 0) // https://github.com/pciutils/pciutils/issues/136
ffpci_init(pci.access);
else
return "pcilib: Cannot find any working access method.";
pci.access->error = handlePciGenericError; // set back to generic error so we don't mess up error handling in other places
ffpci_scan_bus(pci.access);
struct pci_dev* device = pci.access->devices;
@@ -231,17 +282,17 @@ static const char* pciDetectGPUs(const FFinstance* instance, FFlist* gpus)
}
ffpci_cleanup(pci.access);
dlclose(libpci);
return NULL;
}
#endif
void ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
{
#ifdef FF_HAVE_LIBPCI
pciDetectGPUs(instance, gpus);
return pciDetectGPUs(instance, gpus);
#else
FF_UNUSED(gpus, instance);
return "fastfetch is built without libpci support";
#endif
}
+57
View File
@@ -0,0 +1,57 @@
#include "gpu.h"
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
#include <inttypes.h>
const char* ffDetectGPUImpl(FFlist* gpus, FF_MAYBE_UNUSED const FFinstance* instance)
{
DISPLAY_DEVICEW displayDevice = {.cb = sizeof(displayDevice) };
wchar_t regKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
const uint32_t regKeyPrefixLength = strlen("SYSTEM\\CurrentControlSet\\Control\\Video\\{");
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\{");
for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i)
{
if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue;
const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey);
if (wmemcmp(&displayDevice.DeviceKey[deviceKeyLength - 4], L"0000", 4) != 0) continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInit(&gpu->vendor);
ffStrbufInitWS(&gpu->name, displayDevice.DeviceString);
ffStrbufInit(&gpu->driver);
gpu->temperature = FF_GPU_TEMP_UNSET;
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;
if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{')
{
wmemcpy(regKey + regKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, 100 - regKeyPrefixLength + 1);
FF_HKEY_AUTO_DESTROY hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regKey, &hKey, NULL)) continue;
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL);
if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(ffStrbufContainS(&gpu->vendor, "Intel"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(ffStrbufContainS(&gpu->vendor, "NVIDIA"))
ffStrbufSetS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
{
uint32_t vmem = 0;
if (ffRegReadUint(hKey, L"HardwareInformation.MemorySize", &vmem, NULL))
gpu->dedicated.total = vmem;
}
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
}
return NULL;
}
-101
View File
@@ -1,101 +0,0 @@
extern "C" {
#include "gpu.h"
#include "util/windows/unicode.h"
}
#ifdef FF_USE_WIN_GPU_DXGI
#include <dxgi.h>
#include <wchar.h>
static const char* detectWithDxgi(FFlist* gpus)
{
IDXGIFactory1* pFactory;
if(FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory))))
return "CreateDXGIFactory1() failed";
for(unsigned iAdapter = 0;; ++iAdapter)
{
IDXGIAdapter1* adapter;
if(FAILED(pFactory->EnumAdapters1(iAdapter, &adapter)))
break;
DXGI_ADAPTER_DESC1 desc;
if(FAILED(adapter->GetDesc1(&desc)) || (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE))
continue;
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
if(wmemchr((const wchar_t[]) {0x1002, 0x1022}, (wchar_t)desc.VendorId, 2))
ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if(wmemchr((const wchar_t[]) {0x03e7, 0x8086, 0x8087}, (wchar_t)desc.VendorId, 3))
ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if(wmemchr((const wchar_t[]) {0x0955, 0x10de, 0x12d2}, (wchar_t)desc.VendorId, 3))
ffStrbufInitS(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufSetWS(&gpu->name, desc.Description);
ffStrbufInit(&gpu->driver);
adapter->Release();
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
}
pFactory->Release();
return NULL;
}
#else
#include "util/windows/wmi.hpp"
static const char* detectWithWmi(FFlist* gpus)
{
FFWmiQuery query(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr);
if(!query)
return "Query WMI service failed";
while(FFWmiRecord record = query.next())
{
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInit(&gpu->vendor);
record.getString(L"AdapterCompatibility", &gpu->vendor);
if(ffStrbufStartsWithS(&gpu->vendor, "Intel "))
{
//Intel returns "Intel Corporation", not sure about AMD
ffStrbufSetS(&gpu->vendor, "Intel");
}
ffStrbufInit(&gpu->name);
record.getString(L"Name", &gpu->name);
ffStrbufInit(&gpu->driver);
record.getString(L"DriverVersion", &gpu->driver);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
}
return nullptr;
}
#endif
extern "C"
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
{
FF_UNUSED(instance);
#ifdef FF_USE_WIN_GPU_DXGI
return detectWithDxgi(gpus);
#else
return detectWithWmi(gpus);
#endif
}

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