Compare commits

..

505 Commits

Author SHA1 Message Date
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
Linus Dierheimer 70df34caf9 Merge pull request #370 from LinusDierheimer/dev
Release 1.8.2
2022-12-31 12:45:13 +01:00
李通洲 c04b421f26 README: fix unexpectedly concated paragraphs 2022-12-31 19:33:44 +08:00
李通洲 e292470ade Release 1.8.2 2022-12-31 19:25:59 +08:00
李通洲 c0d3dc30e1 Changelog: update 1.8.2 2022-12-31 18:56:45 +08:00
李通洲 01df2ae3e4 CI: align artifact names to other platforms (Windows) 2022-12-31 18:56:45 +08:00
李通洲 f8174a67d7 Wifi: don't use libcJSON as wlanapi's dll name 2022-12-31 18:12:23 +08:00
李通洲 53265f6b7f Users: fix memleaks (Windows) 2022-12-31 18:12:23 +08:00
李通洲 f245492679 TerminalShell: fix shell detection when installed with scoop 2022-12-31 12:42:19 +08:00
Linus Dierheimer 6f92524ada Merge pull request #369 from LinusDierheimer/dev
Release 1.8.1
2022-12-30 18:51:52 +01:00
Linus Dierheimer b2ff1501aa Update Changelog 2022-12-30 18:49:58 +01:00
Linus Dierheimer fbb4ab590f Local IP: Key: Clear before reuse
#368
2022-12-30 18:42:26 +01:00
李通洲 e2cadf85f8 Changelog: credit #365 2022-12-30 22:03:53 +08:00
李通洲 b5c2c9ee7a Release 1.8.1 2022-12-30 22:00:11 +08:00
李通洲 1dabac9782 Media: remove the alias name Song to avoid confusion
So we don't have code like `#define FF_SONG_MODULE_NAME "Media"`.
Also fix the error `unknown option: --media-format`
2022-12-30 11:21:11 +08:00
Linus Dierheimer 50983f83f5 Generic decoding for mountpoints
#364
2022-12-29 23:19:44 +01:00
Linus Dierheimer 5026be2d28 Fix parsing mountpoints with backslashes
#364
2022-12-29 22:58:29 +01:00
Linus Dierheimer 70aad5c320 Fix parsing mountpoints with spaces
#364
2022-12-29 22:51:23 +01:00
Linus Dierheimer e74d21c0e5 Merge pull request #365 from IanManske/parse-color-fix
Fix color parsing.
2022-12-29 22:33:59 +01:00
Ian Manske 90d8677b7a Add missing else statement. 2022-12-29 12:51:00 -05:00
李通洲 7a5d88270e macOS: fix building with old xcode
Makes homebrew happy
https://github.com/Homebrew/homebrew-core/pull/119329
2022-12-30 01:13:04 +08:00
Linus Dierheimer 5599335965 Zip windows artifacts 2022-12-29 14:40:37 +01:00
Linus Dierheimer e829589875 Merge pull request #363 from LinusDierheimer/dev
Bump CMakeList version
2022-12-29 13:47:18 +01:00
李通洲 98acd516b8 CMake: bump version 2022-12-29 20:24:30 +08:00
李通洲 584d792f5a Bios: try supporting FreeBSD
It prints nothing on my VM. Don't know if it works on a physical machine.
2022-12-29 20:23:44 +08:00
Carter Li e6db860861 Merge pull request #362 from LinusDierheimer/dev
Merge macOS Bios module support for 1.8.0
2022-12-29 12:54:32 +08:00
李通洲 f0ec3cb9ec README: update building instructions for Windows
Fixes #336
2022-12-29 12:51:20 +08:00
Carter Li 0801e22dce Bios: support macOS 2022-12-29 11:03:33 +08:00
李通洲 5efd7b9ac4 FFstrbuf: add ffStrbufContainC 2022-12-29 11:03:33 +08:00
Linus Dierheimer f2bae200d3 Merge pull request #361 from LinusDierheimer/dev
Release 1.8.0
2022-12-28 15:26:12 +01:00
李通洲 fd14513aef Changelog: add changes for 1.8.0 2022-12-28 21:28:23 +08:00
李通洲 6becc8f334 Swap: improve performance on Linux
We can't do the same thing with memory because there is no `cachedram` in `struct sysinfo`
2022-12-28 17:27:35 +08:00
李通洲 90359d227e Global: don't require sysinfo.h globally
... which is Linux specific
2022-12-28 17:20:20 +08:00
李通洲 6ff67e87eb Memory: refactor, don't cache results 2022-12-28 17:20:20 +08:00
李通洲 0a83423731 Packages: support eopkg for Solus (#360)
UNTESTED
2022-12-27 17:36:58 +08:00
李通洲 5160644016 Logo: add Solus logo (#360) 2022-12-27 17:32:19 +08:00
李通洲 d956bd2643 Image: update cache folder's name 2022-12-27 17:25:19 +08:00
Carter Li 7a6a2ad530 Chassis: fix compiler warnings
My fault
2022-12-25 23:24:50 +08:00
李通洲 21c76f31c4 Chassis: fix compiler warnings 2022-12-25 12:43:48 +08:00
李通洲 cb48c1277a Chassis: seperate module
It's only supported on Linux
2022-12-24 23:00:38 +08:00
Carter Li 3c18fd8920 Merge pull request #358 from doubletimedan/dev
Spelling and grammer fixes
2022-12-24 20:58:59 +08:00
Daniel Coughlan 83c6e809c6 Correct Windows version 2022-12-24 12:09:11 +00:00
李通洲 dc35fedd74 TerminalShell: detect Windows Terminal Preview 2022-12-24 13:00:43 +08:00
李通洲 947923567f TerminalShell: fix mintty detection (Windows) 2022-12-24 12:52:13 +08:00
Daniel Coughlan 3d19388086 Spelling and grammer fixes 2022-12-23 22:17:40 +00:00
李通洲 051f6643a6 Image: fix build 2022-12-23 15:23:37 +08:00
李通洲 47e01a7157 Image: print more debug info when errored 2022-12-23 12:51:37 +08:00
李通洲 a336145ed9 Image: add fast path for kitty protocol 2022-12-23 12:45:57 +08:00
李通洲 ecc6b477dc TerminalFont: support Kitty 2022-12-23 11:11:27 +08:00
李通洲 e0c6c462a6 README: update document of Windows 10- and image logo support 2022-12-22 22:10:49 +08:00
李通洲 3e607680e2 Image: dont leak memories 2022-12-22 21:47:30 +08:00
李通洲 89347b7bee Image: add dirty support of iTerm image protocol
iTerm image protocol supports most commonly used image formats so we don't need image magick to convert image format.
However, since we don't know anything about the image, `--logo-width` `--logo-height` must be specified to make sure that logo will not be covered by texts.
2022-12-22 21:37:16 +08:00
李通洲 c45ef08926 Image: expose more chafa settings 2022-12-22 11:36:13 +08:00
Linus Dierheimer 8d40b2cd0e Merge pull request #355 from kojq/dev
Update help.txt
2022-12-21 21:37:24 +01:00
kojq 14e318c273 Merge branch 'dev' into dev 2022-12-21 15:20:20 -05:00
李通洲 f50b478966 Image: try fixing caching 2022-12-22 02:40:56 +08:00
李通洲 0cacedfc5d Image: enable Chafa on Windows
It's not built by default, as imagemagick requires too many dlls.
2022-12-22 02:07:57 +08:00
Linus Dierheimer 5283f10189 Merge pull request #357 from AloneER0/dev
Added OpenMandriva
2022-12-21 18:42:22 +01:00
AloneER0 c9c2526f08 Added OpenMandriva 2022-12-21 17:27:00 +01:00
kojq fba4bca46e Merge branch 'dev' into dev 2022-12-21 07:51:49 -05:00
Carter Li a95eb65faa Merge pull request #352 from CarterLi/dev
Global: remove caching functions except image caching
2022-12-21 19:29:55 +08:00
kojq bcc7b630ae Update help.txt 2022-12-21 04:38:28 -05:00
kojq a247a8d6ba Update help.txt 2022-12-21 04:23:57 -05:00
kojq 620adc0ec6 Update help.txt 2022-12-21 04:10:33 -05:00
kojq d5b3ae9056 Update help.txt 2022-12-21 04:02:02 -05:00
kojq afe56a36c9 Update help.txt 2022-12-21 03:52:16 -05:00
kojq 265b98311a Update help.txt 2022-12-21 03:51:02 -05:00
kojq 89983a28b4 Update help.txt 2022-12-21 03:44:48 -05:00
kojq c9918035ed Update help.txt 2022-12-21 03:31:23 -05:00
李通洲 225d1dd4d2 Init: don't try to find config files in XDG folders on platforms other than Linux and BSD 2022-12-20 23:29:23 +08:00
李通洲 985fc991e8 Revert "Image: tidy"
This reverts commit d21ce9b10f.
2022-12-20 22:44:45 +08:00
李通洲 8f3900a9df Windows: add manifest file to indicate that we use UTF-8 and support Windows 10+ 2022-12-20 22:40:06 +08:00
李通洲 d21ce9b10f Image: tidy 2022-12-20 22:37:15 +08:00
李通洲 1153d29099 TerminalFont: improve conhost font detection (Windows) 2022-12-20 12:03:05 +08:00
李通洲 75341e8172 Image: make it compile on Windows
Doesn't work yet.
2022-12-20 11:37:54 +08:00
李通洲 2f5cbfb03a Image: enable im7 on macOS 2022-12-20 11:04:57 +08:00
李通洲 01d2d77efd Image: fix resource leaks 2022-12-20 11:01:42 +08:00
李通洲 1b2a61ed49 Image: init MagickCore environment before using it
I don't know why im6 works without initialization, but im7 doesn't.
2022-12-20 11:01:13 +08:00
李通洲 10584eb01a Image: document macOS support; update CI 2022-12-19 22:34:29 +08:00
李通洲 d4ec500b1b Image: fix compile error when building with chafa enabled
It should be `#include <chafa.h>` because `pkg-config chafa --cflags` prints `-I/usr/include/chafa` even in Linux. It was working because `chafa` folder was installed in the standard `/usr/include` directory, but it was not the case for macOS (brew)
2022-12-19 22:34:29 +08:00
李通洲 c7bec3d0c9 Image: enable imagemagick 6 on macOS
Program crashed when imagemagick 7 used, for some reason.
2022-12-19 22:34:29 +08:00
李通洲 ff6e982050 Global: remove caching except image caching 2022-12-17 12:41:11 +08:00
李通洲 6a49ae60a1 Locale: silence warnings (Windows) 2022-12-17 12:34:21 +08:00
李通洲 27fb0c6c06 Battery: improve performance (Windows) 2022-12-17 12:31:37 +08:00
李通洲 047b32e7d9 CpuUsage: make the result more accurate 2022-12-17 12:31:31 +08:00
李通洲 eeb008f505 Global: replace all ".so" to FF_LIBRARY_EXTENSION
... no matter whether the libraries are linux specific or not
2022-12-17 12:22:11 +08:00
Linus Dierheimer 704834b370 Merge pull request #350 from JackGannonUK/dev
Add Enso Logo
2022-12-16 19:06:53 +01:00
李通洲 a3cb6608ce Locale: refactor 2022-12-16 11:51:32 +08:00
Jack Gannon 7640042905 add enso logo
Added Enso Logo in `src/logo/builtin.c`
Added Enso in `README.md`
2022-12-15 16:57:45 +00:00
李通洲 d601cc823c DisplayServer: make 3rd party window manager plugin detection a slow operation (macOS)
The display server of macOS is [Quartz Compositor](https://en.wikipedia.org/wiki/Quartz_Compositor), not other 3rd party apps.
2022-12-14 19:03:01 +08:00
李通洲 338cc1db40 Add back trailing white spaces which are unexpectedly removed by IDE
This partially reverts commit 6710967d19.
2022-12-14 16:51:45 +08:00
李通洲 6710967d19 README: update notes for Windows 10- 2022-12-14 16:46:52 +08:00
李通洲 e4a5194115 Rework stdout buffering on Windows.
Windows doesn't support line-buffering. We enable full-buffering instead and flush buffers per module.
2022-12-14 16:27:04 +08:00
李通洲 d151901049 Common: improve resolution of ffTimeGetTick 2022-12-14 15:43:53 +08:00
李通洲 c9e9ec3a80 CI: print time usage 2022-12-14 14:10:42 +08:00
李通洲 54912df237 Option: enable --show-errors if --stat is set 2022-12-14 13:52:16 +08:00
李通洲 b09aa3240a Global: support --stat option for benchmark 2022-12-14 11:30:50 +08:00
李通洲 c9bc1f8306 Vulkan: build with vulkan-loader (macOS)
... so cmake can find it
2022-12-13 13:12:13 +08:00
李通洲 7e98fa8626 Vulkan: don't require vulkan-loader (macOS)
Which also avoids requiring portability_enumeration extension
2022-12-13 11:21:26 +08:00
李通洲 3b2c189083 Packages: split brew-cellar and brew-cask (macOS)
`brew info` shows number of `brew-cellar` packages only. Split `brew-cellar` out of `brew` to avoid users from confusion.
2022-12-13 11:13:00 +08:00
Linus Dierheimer c242001a77 Fix build without chafa 2022-12-12 13:58:16 +01:00
Linus Dierheimer b21cfc127a Termialshell: ignore sh 2022-12-12 13:55:19 +01:00
Linus Dierheimer 3a5af1bbb3 Logo: data source option
#345
2022-12-12 13:43:10 +01:00
李通洲 68b98c1bd2 Windows: disable stdout buffer 2022-12-10 22:47:53 +08:00
李通洲 24ae7ec6e0 Windows: build msvcrt version for Windows 10-
However we don't include it in release package to prevent users from confusion.

Also clarify we only support FreeBSD
2022-12-10 22:47:44 +08:00
李通洲 e3590bc673 Wmtheme: fix detection on Windows 10- 2022-12-10 22:22:09 +08:00
李通洲 72dcc5223d Global: rename --disable-stdout-buffer to --unbuffered 2022-12-10 13:11:41 +08:00
李通洲 4558af2e43 Windows: fix build 2022-12-10 13:10:06 +08:00
李通洲 ed259fad9c Windows: tweaks 2022-12-08 18:33:43 +08:00
李通洲 b4e2997389 Tests: don't include fastfetch.h 2022-12-08 18:29:24 +08:00
李通洲 d946a46d3f TerminalFont: fix memleaks (Linux) 2022-12-08 18:27:04 +08:00
李通洲 983bd50a09 FFstrbuf: improve performance of InitF 2022-12-06 16:27:00 +08:00
李通洲 4f0be4f72c Wifi: silence compiler warnings 2022-12-05 18:02:10 +08:00
李通洲 58aa3e94e4 Init: add --disable-stdout-buffer option 2022-12-03 22:21:24 +08:00
李通洲 19ec59cca5 Wifi: init basic support for Linux 2022-12-02 22:43:46 +08:00
李通洲 911780ba3c Cursor: silence compiler warnings 2022-12-02 22:20:23 +08:00
李通洲 8b0d034a94 FFstrbuf: fix bug of AppendF when string len == ffStrbufGetFree 2022-12-02 22:20:01 +08:00
李通洲 2a8235ae38 Host: improve performance (macOS) 2022-12-02 22:18:39 +08:00
李通洲 15a98a83cd Linux: fix some memleaks 2022-12-02 16:39:02 +08:00
李通洲 1dc578badb Wifi: silence warnings 2022-12-02 01:20:06 +08:00
李通洲 be698bd806 Processes: don't hard code magic numbers (Windows) 2022-12-02 01:12:56 +08:00
李通洲 0cad657ce2 Swap: correct implementation (Windows) 2022-12-02 01:12:48 +08:00
李通洲 7991abab0b TerminalFont: support deepin-terminal 2022-12-01 17:45:17 +08:00
李通洲 b3e635a923 Wifi: support macOS 2022-11-28 16:59:11 +08:00
李通洲 57b794cbd9 macOS: fix build 2022-11-28 16:29:51 +08:00
李通洲 974dc96259 Wifi: support multiple interfaces 2022-11-28 16:29:30 +08:00
李通洲 db33d246cb common/io: improve performance for large files 2022-11-28 01:57:45 +08:00
李通洲 5e5442426c Wifi: load wlanapi.dll dynamically
Windows Server doesn't support it
2022-11-27 16:22:30 +08:00
李通洲 a55add190c Wifi: add new module
Only Windows is supported currently
2022-11-27 12:21:53 +08:00
李通洲 5c381460ce util: rename register -> registry 2022-11-27 12:21:53 +08:00
李通洲 4cf1d5bf94 util: rename unicode helper function names 2022-11-27 12:21:32 +08:00
李通洲 4316ba988b CpuUsage: optimise performance further 2022-11-25 23:14:41 +08:00
李通洲 c6a9217c74 Windows: silense compiler warnings 2022-11-25 23:13:57 +08:00
李通洲 34d3021b80 Build: fix Android is incorrectly detected as Linux 2022-11-25 19:17:37 +08:00
李通洲 c57417e834 Logo: adjust ubuntu logo style 2022-11-25 18:09:49 +08:00
Linus Dierheimer 00f86c6346 CMake: Don't require pkg-config 2022-11-24 18:10:49 +01:00
李通洲 0ab38bb4d7 CPU: fix cpu freq detection in WSL
`/sys/devices/system/cpu/cpufreq/policy0/` doesn't exist in WSL
2022-11-24 23:30:54 +08:00
李通洲 7da45d6c2c DE: fix detection for Windows Server 2022-11-24 23:30:54 +08:00
Linus Dierheimer 3c7f02bee3 Merge pull request #338 from CarterLi/dev
Improve performance and various fixes
2022-11-24 14:14:03 +01:00
Linus Dierheimer 686a66e5f1 Merge pull request #340 from draumaz/dev
add CRUX logo
2022-11-24 14:12:08 +01:00
李通洲 c50d7bf974 Logo: remove Windows 11 Old, add Windows 11 Small 2022-11-24 21:06:08 +08:00
李通洲 d70b3100f2 BSD: fix build 2022-11-24 18:59:40 +08:00
李通洲 d500bdff96 WmTheme: convert known color values to readable strings 2022-11-24 17:38:40 +08:00
draumaz 8de88adc0b add CRUX logo, update README.md 2022-11-23 23:31:11 -08:00
李通洲 4b3ed67877 TerminalShell: detect Clink 2022-11-24 11:24:12 +08:00
李通洲 11258c0d8d TerminalShell: code cleanup (Windows) 2022-11-24 11:23:45 +08:00
李通洲 325aa536c4 Font: improve performance (Windows) 2022-11-23 20:01:41 +08:00
李通洲 31863baee2 CpuUsage: remove unused code (Windows) 2022-11-23 20:01:41 +08:00
李通洲 0f08233581 Users: improve performance (Windows) 2022-11-23 20:01:40 +08:00
李通洲 b28da1057c WmTheme: detect accent color (Windows) 2022-11-23 20:01:40 +08:00
李通洲 4fa3ca98a2 util/register: fix crashing when value string contains non-ascii chars
We can't use RegGetValueA because RegGetValueA converts wide string to non UTF-8 string, which results in crashing when printing
2022-11-23 17:44:57 +08:00
李通洲 66f8a8cdd0 TerminalFont: fix Windows Terminal font detection when running inside msys2 2022-11-23 17:44:57 +08:00
李通洲 051423e75e util: add mallocHelper and use it 2022-11-23 17:44:57 +08:00
李通洲 ae562ac962 Cursor: support Windows (not working yet) 2022-11-23 17:44:57 +08:00
李通洲 772dd1e294 GPU: improve performance (Windows) 2022-11-23 15:38:59 +08:00
李通洲 27212e8b98 Battery: improve performance (Windows) 2022-11-23 15:38:59 +08:00
李通洲 629c2de253 util: add a helper function to convert wide strings (Windows) 2022-11-23 15:38:59 +08:00
李通洲 9ef95e43a3 CPU: improve performance (Windows) 2022-11-22 19:40:57 +08:00
李通洲 6a304dbb4d OS: improve performance (Windows) 2022-11-22 19:40:57 +08:00
李通洲 4355039329 Host: improve performance (Windows) 2022-11-22 19:40:56 +08:00
李通洲 5aebb400da Board: improve performance (Windows) 2022-11-22 19:40:56 +08:00
李通洲 fbd8c0237f BIOS: improve performance (Windows) 2022-11-22 19:40:56 +08:00
李通洲 04c9d16c16 util: introduce register helpers and use them (Windows) 2022-11-22 19:40:56 +08:00
李通洲 308408a962 Processes: improve performance (Windows) 2022-11-22 19:40:56 +08:00
李通洲 19c5904561 Memory: improve performance by not querying WMI (Windows) 2022-11-21 15:45:53 +08:00
Linus Dierheimer c0037c99e4 Refactor CMakeLists.txt 2022-11-20 18:14:32 +01:00
Linus Dierheimer b85c1c44b8 Merge pull request #332 from CarterLi/dev
Various improvements
2022-11-20 12:51:51 +01:00
李通洲 1c69d6c788 Disk: use statvfs64 only when __USE_LARGEFILE64 is defined 2022-11-20 19:43:02 +08:00
李通洲 b6b95581cd Windows: partially revert a5306d60ee to fix crashes on Windows 7
Very strange behavior. Needs further investigation
2022-11-20 02:18:06 +08:00
李通洲 55c6374949 WmTheme: support Windows 7 2022-11-20 00:57:32 +08:00
李通洲 0a65867937 Windows: fix memleaks 2022-11-20 00:52:52 +08:00
李通洲 859f645fe5 Disk: fix size detection on 32bit Linux
Ref: #337
2022-11-18 00:10:16 +08:00
李通洲 f1cc94207e Host: detect WSL version 2022-11-17 22:36:49 +08:00
李通洲 70847857f7 GPU: remove special handling for WSL
WSL2 is VM, which can only provide virtual GPUs, like other VMs do. We should honor it.

As of WSL 1.0, it prints `Microsoft Corporation Basic Render Driver`
2022-11-17 22:36:49 +08:00
李通洲 2a34978487 Thread: silence compiler warnings 2022-11-17 22:36:49 +08:00
李通洲 fde9379bb2 Android: simplify code; fix mistakes in terminal font detection code 2022-11-17 20:19:27 +08:00
李通洲 e8e586ce7c Windows / macOS: simplify code
1. simplify resource management by using C++ RAII like GCC attribute extension `cleanup`
2. simplify HEKY reading

Actually `__attribute__((__cleanup__(cleanupFn)))` is supported on all major C compiler ( gcc, clang and icc ) except MSVC I only used it on Windows and macOS for now. Let's see if the project author like it.
2022-11-17 19:54:36 +08:00
李通洲 fb78d9bbb9 TerminalFont: support Warp; improve performance of Apple Terminal (macOS) 2022-11-17 19:53:12 +08:00
李通洲 a498e9e142 CPU: don't remove (R) in CPU name to be consistant with GPU name 2022-11-17 10:33:50 +08:00
李通洲 d0d6f48751 osascript: simplify code (macOS) 2022-11-17 10:18:29 +08:00
李通洲 0361a30c40 Font: simplify code; fix memleaks (macOS) 2022-11-17 10:18:13 +08:00
李通洲 d0c18c4679 DisplayServer: don't use private API (macOS) 2022-11-17 10:18:13 +08:00
李通洲 8aca8a2229 Temps: silence compiler warnings 2022-11-17 10:18:13 +08:00
李通洲 0bbecb3b33 Thread: silence compiler warnings 2022-11-17 00:13:25 +08:00
李通洲 3f008c4b6d CpuUsage: improve performance 2022-11-15 17:48:57 +08:00
李通洲 227eb707d2 CpuUsage: fix calucation on Windows 2022-11-15 17:30:16 +08:00
李通洲 a5306d60ee Windows: enable console processing, disable output buffer
UCRT doesn't support line buffering, which makes modules being not printed ASAP
2022-11-15 14:50:57 +08:00
李通洲 e3de39d3ab Windows: add version info in binaries 2022-11-12 21:33:31 +08:00
李通洲 f4666fcb0a README: document Windows 10- support 2022-11-12 21:33:31 +08:00
李通洲 85a554b60d CPU: support Windows 7 2022-11-12 21:33:31 +08:00
李通洲 1ea44417d0 TerminalFont: add support for ConEmu 2022-11-12 21:33:31 +08:00
李通洲 0605cb754b OS: fix Windows 7 detection 2022-11-12 21:33:31 +08:00
李通洲 f889d919f8 TerminalShell: add basic support for ConEmu 2022-11-12 21:33:31 +08:00
李通洲 d670a9a584 Kernel: support Windows 7 2022-11-12 21:33:31 +08:00
Linus Dierheimer e51b8276cd Merge pull request #333 from kbdharun/dev
Add Vanilla OS logo
2022-11-10 18:01:03 +01:00
K.B.Dharun Krishna 67feba6171 Add Vanilla OSlogo
Adding logo for Vanilla OS a new and upcoming Ubuntu based distribution that uses Vanilla GNOME and uses on-demand immutability.

Signed-off-by: K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
2022-11-08 10:50:04 +05:30
Linus Dierheimer 922de3755b Merge pull request #330 from CarterLi/dev
Networking: support nowait connection
2022-11-04 11:51:55 +01:00
李通洲 9da7bb3f30 Networking: support nowait connection (Posix)
Thread was used for now.
It's possible to do nonblocking connect & send with io_uring on Linux, but it requires newer kernel and linking to liburing. I don't think it is worth the effort.
2022-11-03 20:25:09 +08:00
李通洲 46ebb52afa Thread: split ffThreadCreateAndDetach; add ffThreadJoin 2022-11-03 20:25:09 +08:00
李通洲 4f97692245 Networking: support nowait connection (Windows) 2022-11-03 20:25:09 +08:00
Linus Dierheimer 25a833207e Merge pull request #329 from wvlab/dev
Add Nobara logo
2022-11-02 19:36:47 +01:00
WVlab 8224f8c4c6 README: Add Nobara to avaliable logos section 2022-11-02 16:27:03 +00:00
WVlab c455718ada add nobara logo 2022-11-02 16:00:00 +00:00
Linus Dierheimer 37b1d24575 Merge pull request #328 from jumps-are-op/fix_cpu_format_setting
Fix setting `cpu-format`
2022-11-01 16:34:40 +01:00
jumps 449d121f19 Fix setting cpu-format
`--cpu-format` set `terminal-format` instead of `cpu-format` because of
a typo in fastfetch.c
2022-11-01 18:25:42 +03:00
Linus Dierheimer 9a51d203de Merge pull request #327 from jumps-are-op/add_parabola_logo
Logo: Add Parabola GNU/Linux-libre logo (instead of #324)
2022-11-01 16:11:15 +01:00
jumps 0e92fc2289 README: Add Parabola to logos sections 2022-11-01 18:08:06 +03:00
jumps 54c649e76e Add Parabola GNU/Linux-libre logo 2022-11-01 17:53:59 +03:00
Linus Dierheimer 45f8b86f13 Don't segfault if 0 is given as argument index
#326
2022-11-01 14:54:27 +01:00
Linus Dierheimer a8a1f98a8f Merge pull request #323 from CarterLi/dev
Improve detection on Android
2022-11-01 14:34:38 +01:00
李通洲 b8f14c964a Disk: detect Windows volumes on WSL 2022-10-28 16:29:31 +08:00
李通洲 de964d3e77 Disk: only prints useful mount points on Android
fix #322
2022-10-28 16:29:31 +08:00
李通洲 4634606a36 CpuUsage: clearify the restriction on Android 2022-10-28 16:29:31 +08:00
Linus Dierheimer 5d306ed9f3 Don't print vulkan driver info, if it contains new lines
#316
2022-10-27 13:23:24 +02:00
Linus Dierheimer ba1fc7a03e Merge pull request #319 from CarterLi/dev
Improvements for FreeBSD and a small fix for macOS
2022-10-27 11:37:02 +02:00
李通洲 8b43605abf README: document Chocolatey support 2022-10-27 17:03:53 +08:00
李通洲 2ee5b3b7a5 TerminalShell: add support for tcsh
which is the default shell for freebsd
2022-10-27 16:45:59 +08:00
李通洲 302a588812 TerminalShell: fix shellExe detection on macOS
`proc_pidpath()` works only if bufsize >= PROC_PIDPATHINFO_MAXSIZE
2022-10-27 16:45:59 +08:00
李通洲 2a1330dea3 README: clearify we support FreeBSD only, not OpenBSD or NetBSD 2022-10-27 16:45:59 +08:00
李通洲 5472621ac0 Disk: support freebsd
Also rewrite macOS detection to share code with bsd
2022-10-27 16:45:59 +08:00
李通洲 9ad7ba7144 CpuTemp: support freebsd
Untested
2022-10-27 11:15:53 +08:00
李通洲 895d151e2e Host: support freebsd 2022-10-27 11:15:53 +08:00
李通洲 3ee15d0401 CpuUsage: add to presets/all 2022-10-27 10:17:29 +08:00
李通洲 60ad6792ba CpuUsage: support freebsd 2022-10-27 10:17:29 +08:00
Linus Dierheimer b878d3ccf6 Merge pull request #315 from CarterLi/dev
Improvements and bug fix for terminal font detection
2022-10-26 15:18:07 +02:00
李通洲 f93bd9e28b TerminalFont: fix platform font detection
my bad...
2022-10-26 20:02:15 +08:00
李通洲 9c73f6b787 TerminalShell: support freebsd 2022-10-26 19:49:25 +08:00
李通洲 64b9f69fb1 Swap: support freebsd 2022-10-26 17:43:08 +08:00
李通洲 aca2c01c9e Processes: support freebsd 2022-10-26 17:43:08 +08:00
李通洲 470d160346 Uptime: support freebsd 2022-10-26 17:43:08 +08:00
李通洲 e225b496b1 Disk: don't print hidden removable volumes (macOS) 2022-10-25 20:02:26 +08:00
李通洲 f470744e44 Kernel: improve performance, detect code name (Windows) 2022-10-25 20:02:26 +08:00
李通洲 42fec6e61f Logo: add new Windows 11 logo
Ref: https://github.com/dylanaraps/neofetch/pull/2187
2022-10-24 22:20:59 +08:00
李通洲 883a535441 Packages: support Chocolatey (Windows) 2022-10-23 23:28:49 +08:00
Linus Dierheimer 65b342cac7 Merge pull request #314 from CarterLi/dev
Improve performance on Windows
2022-10-23 15:55:33 +02:00
李通洲 1395abcf09 TerminalFont: improve Windows Terminal terminal font detection on Windows 2022-10-23 18:48:31 +08:00
李通洲 e59d64513f Silence warnings 2022-10-23 17:54:19 +08:00
李通洲 ed85b8249a Init: enable buffering on Windows 2022-10-23 17:54:02 +08:00
Linus Dierheimer bddf1c67bf Merge pull request #313 from CarterLi/fix
Fixes and performance improvements
2022-10-23 09:48:11 +02:00
李通洲 62ab091350 Printing: improve performace of ffPrintCharTimes 2022-10-23 10:46:09 +08:00
李通洲 1588f58726 Windows: silence warnings when building with clang 2022-10-23 10:11:54 +08:00
李通洲 688a16c941 Disk: fix --disk-folder parsing on Windows 2022-10-23 10:11:53 +08:00
李通洲 69b3a6871f Init: improve option parsing performance 2022-10-23 10:11:53 +08:00
李通洲 0aac358e33 Init: simplify module arg parsing code 2022-10-23 10:08:02 +08:00
Linus Dierheimer 7f82f8d679 Merge pull request #312 from CarterLi/android
Android: add vulkan support for GPU detection
2022-10-22 18:19:32 +02:00
Linus Dierheimer 5fb96223a8 Merge pull request #308 from CarterLi/bar
Global: support bar output for percentage value #294
2022-10-22 18:18:44 +02:00
李通洲 e13c88cea6 Global: support bar output for percentage value #294 2022-10-22 16:15:12 +08:00
李通洲 fbc76714f5 Android: add vulkan support for GPU detection
Termux does have package pciutils, but it's put inside of root-repo and
and doesn't provide libpci.pc. So I think use vulkan can be a better
option than libpci because vulkan.so is provided by Android system.

To build with android support, install `vulkan-headers` and
`vulkan-loader-android` (for `vulkan.pc`).
2022-10-20 17:42:01 +08:00
Linus Dierheimer c7adbc1309 Merge pull request #311 from LinusDierheimer/revert-306-dev
Revert "Add Univalent GNU/Linux's logo"
2022-10-19 08:29:53 +02:00
Linus Dierheimer b27453d275 Revert "Add Univalent GNU/Linux's logo" 2022-10-19 08:29:39 +02:00
Linus Dierheimer aa0501b853 Merge pull request #306 from Jin-Asanami/dev
Add Univalent GNU/Linux's logo
2022-10-19 08:23:12 +02:00
Jin Asanami 596c776463 fix univalent's colours 2022-10-19 12:18:39 +09:00
Linus Dierheimer eb1738b1c6 Merge pull request #309 from CarterLi/swap
Swap: split code out from memory detection
2022-10-18 20:34:03 +02:00
Linus Dierheimer 0505926c75 Merge pull request #307 from CarterLi/dev
Disk: add volume name detection; don't print 0B / 0B (0%)
2022-10-18 20:25:13 +02:00
李通洲 581c6f547d Swap: split code out from memory detection
1. Since swap module is disabled by default, swap detection is unnecessary in most cases.
2. On platform other than Linux, swap detection doesn't share code with memory.
3. Swap detection can be expensive. On Windows, it requires another WMI query which can lag heavily in some cases. Don't pay for you don't use.
2022-10-19 00:24:17 +08:00
李通洲 3d5ef186ba Disk: don't convert NAN to integer; don't print 0B / 0B (0%)
fix ASAN warning: `runtime error: nan is outside the range of representable values of type 'unsigned char'`
2022-10-18 21:23:29 +08:00
李通洲 e3ea39afaa Disk: add volume name detection 2022-10-18 21:23:29 +08:00
Jin Asanami 7f9269cff2 Update builtin.c 2022-10-18 11:30:48 +09:00
Jin Asanami bbcc040dc4 Update README.md 2022-10-18 11:27:54 +09:00
Jin Asanami 727a6988c2 Update builtin.c 2022-10-18 11:26:31 +09:00
Linus Dierheimer 7bbd2aee94 Merge pull request #305 from LinusDierheimer/work/disk_refactor
Work/disk refactor
2022-10-17 18:24:29 +02:00
Linus Dierheimer b812f1dcb4 Disk: Fix build on windows 2022-10-17 17:52:43 +02:00
Linus Dierheimer fb2dca2eaf Merge pull request #303 from CarterLi/win
Windows: fix kernel detection; simplify WMI query code
2022-10-17 17:48:15 +02:00
Linus Dierheimer a03eaed4e2 Disk: add options# 2022-10-17 17:35:06 +02:00
Linus Dierheimer ee705363c1 Disk: Don't always build apple code 2022-10-17 17:13:45 +02:00
Linus Dierheimer c1fec9b411 Disk: Apple implementation working 2022-10-17 08:10:58 -07:00
Linus Dierheimer 19a9b18c69 Disk: Linux impl working 2022-10-17 13:19:48 +02:00
李通洲 38b3aae1e3 Windows: simplify WMI query code
by making C++ code more C++
2022-10-17 00:17:26 +08:00
李通洲 5d5663e2a7 Kernel: fix detection on Windows
According to MSDN, GetVersionExA is not reliable. We have to query WMI instead.
2022-10-17 00:17:19 +08:00
Linus Dierheimer 973eb8127e Merge pull request #302 from VitoFe/dev
Add Garuda small variant
2022-10-15 23:04:03 +02:00
VitoFe 2499cbdab8 Add Garuda small variant 2022-10-15 18:05:21 +00:00
Linus Dierheimer ec80a41871 Merge pull request #298 from CarterLi/dev
TerminalShell: improve speed on Windows
2022-10-15 19:49:44 +02:00
李通洲 a829e85ef5 LocalIP: support --localip-name-prefix on Windows 2022-10-16 01:34:26 +08:00
李通洲 a090bed6c0 Logo: try printing logo on Windows Server
Completely untested
2022-10-15 23:46:00 +08:00
李通洲 76684e49ca TerminalShell: speed up PowerShell version detection by querying the version of pwsh.exe file
Also add cmd version detection
2022-10-15 22:45:30 +08:00
李通洲 c1fc6e2762 Processing: handle a possible error 2022-10-15 21:59:50 +08:00
李通洲 437431a821 TerminalShell: support Windows PowerShell version detection 2022-10-15 21:44:28 +08:00
李通洲 5749a8f7c1 TerminalShell: improve speed on Windows
[NtQueryInformationProcess](https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess) is an internal NT syscall which may change in the future. However, unlike other NT syscalls NtQueryInformationProcess is well documented on MSDN, so I think it's safe to use.

Boost shell detection by 0.3s on my machine. Note querying PowerShell's version `pwsh --version` costs another 0.2s
2022-10-15 21:20:58 +08:00
Linus Dierheimer 54e271c985 Merge pull request #297 from CarterLi/dev
Update information on different platforms
2022-10-15 12:21:43 +02:00
李通洲 b042b90d9b TerminalShell: improve shell detection on Windows 2022-10-15 11:36:24 +08:00
李通洲 a99ca9a1a1 macOS: remove unneeded dependencies 2022-10-15 01:02:46 +08:00
李通洲 f05d036023 README: update description on different platforms 2022-10-15 01:02:16 +08:00
Linus Dierheimer 5a55691358 Merge pull request #296 from CarterLi/dev
TerminalShell: fix bash version detection on Windows
2022-10-14 17:43:00 +02:00
李通洲 4f0dd51761 TerminalShell: fix bash version detection on Windows
Currently we use `env -i /path/to/bash --norc --noprofile -c printf "%s" "$BASH_VERSION"` to detect bash version.
This is problematic on Windows because there is no `env` in $PATH ( there is env in $PATH of msys2 but not in $PATH of Windows )
With this modification the detection is also faster because 1 process is created only
2022-10-14 22:58:56 +08:00
Linus Dierheimer 0ca6f76e88 Merge pull request #295 from CarterLi/dev
Remove msys target and other improvements
2022-10-14 13:56:04 +02:00
李通洲 869f544bab ci: fix errors 2022-10-14 19:40:13 +08:00
李通洲 4f67ed2b77 TerminalShell: add some pretty names 2022-10-14 19:16:55 +08:00
李通洲 3f4926cbd5 TerminalShell: detect platform specific terminal on correct system only 2022-10-14 19:16:55 +08:00
李通洲 af93157a76 TerminalShell: handle nested shell 2022-10-14 19:16:55 +08:00
李通洲 220a7d24bc TerminalShell: detect first shell we found only.
Previously we always detect login shell as current shell, which seems duplicate with userShell
2022-10-14 18:33:11 +08:00
李通洲 3b541d3670 Thread: fix compile errors 2022-10-14 18:33:11 +08:00
李通洲 4bd6f2da89 TerminalShell: add lock ( Windows ) 2022-10-14 18:33:11 +08:00
李通洲 d5e00c3517 ci: package Windows artifacts; run tests on Windows 2022-10-14 18:33:11 +08:00
李通洲 1b7a2c2ed5 MSYS2: remove support
MSYS2 version was built for smooth transition from POSIX api to Win32 api. It has almost identical output as Windows native version, except requiring msys runtime dll and being a bit slower.
2022-10-14 18:33:11 +08:00
李通洲 11ad7a8a3d TerminalShell: unify shell version detection code 2022-10-14 18:33:11 +08:00
李通洲 622f84c971 Kernel: remove special handling for Windows
Since we have an implementation for it
2022-10-14 17:39:07 +08:00
李通洲 779a33349a OS: don't print msys2 logo for native Windows 2022-10-14 17:39:07 +08:00
李通洲 135ca1eeba Packages: don't rely on environment variables 2022-10-14 17:38:53 +08:00
Linus Dierheimer 2dee7f5982 Update CI 2022-10-14 10:49:08 +02:00
Linus Dierheimer 1513b8c0db Fix more build errors 2022-10-13 22:12:31 +02:00
Linus Dierheimer 693cc1e730 Fix build errors 2022-10-13 22:02:58 +02:00
Linus Dierheimer e18980be9f Require sucessfull windows and msys build for release 2022-10-13 21:47:28 +02:00
Linus Dierheimer cf048bc723 Refactor package detection code 2022-10-13 21:43:31 +02:00
Linus Dierheimer 3004d8c9dc Merge pull request #293 from CarterLi/dev
Support Native Windows
2022-10-13 18:01:10 +02:00
李通洲 6f66b87262 Windows: support --list-presets 2022-10-13 23:49:09 +08:00
李通洲 79cfa96616 Processing: fix Windows impl 2022-10-13 23:49:09 +08:00
李通洲 952cacf3ff ci: build with Windows native 2022-10-13 23:49:09 +08:00
李通洲 3cc6611614 Windows: support native Windows 2022-10-13 23:49:09 +08:00
李通洲 457c2da67d Packages: silence warnings 2022-10-13 23:49:08 +08:00
李通洲 13769e0e52 Disk: removes unnecessary #includes 2022-10-13 23:49:08 +08:00
李通洲 b33e042cd4 Library: support Windows 2022-10-13 23:49:08 +08:00
李通洲 2689a20889 Uptime: support Windows 2022-10-13 23:49:08 +08:00
Linus Dierheimer d769fd32f0 Merge pull request #292 from Edsploration/logofix
Fix Alpine, EndeavourOS, Rocky, and Rosa logos
2022-10-13 11:15:29 +02:00
Edward Piper 2c82c9a6dc Fixed Alpine, EndeavourOS, Rocky, and Rosa logos 2022-10-12 10:26:38 -07:00
Linus Dierheimer 3850130583 Merge pull request #291 from CarterLi/dev
Windows: improve Win32 API compatibility
2022-10-12 16:00:45 +02:00
李通洲 06262c078d TerminaFont: move windows specific code into its own file 2022-10-12 21:59:21 +08:00
李通洲 b64a234f8a Networking: support Windows 2022-10-12 21:59:21 +08:00
李通洲 dfed3812ce Title: don't include unnecessary headers 2022-10-12 21:59:21 +08:00
李通洲 1b594d9ed1 Thread: add common thread abstraction layer, and make threading optional 2022-10-12 21:59:21 +08:00
李通洲 d0f589bb3e Disk: silence warning on macOS 2022-10-12 14:03:03 +08:00
Linus Dierheimer bc72f3cd64 Don't build dmg 2022-10-11 19:41:37 +02:00
Linus Dierheimer de8f1a86c6 Merge pull request #289 from CarterLi/dev
Make CI actually work on Windows
2022-10-11 19:22:48 +02:00
李通洲 4bae08c159 OS: detect Windows Server 2022-10-12 01:12:58 +08:00
李通洲 34cd81b4d9 ci: run fastfetch on Windows 2022-10-12 00:19:31 +08:00
李通洲 8c127a175c TerminalShell: try detecting more shells 2022-10-12 00:19:31 +08:00
李通洲 5e3e2b6137 Windows: fix possible crashes 2022-10-12 00:19:31 +08:00
Linus Dierheimer 88a16d4c7d Merge pull request #286 from CarterLi/dev
Improvements, see commit list
2022-10-11 16:00:45 +02:00
Linus Dierheimer 296674cfd6 Merge branch 'master' into dev 2022-10-11 14:35:36 +02:00
Linus Dierheimer 875174e2e0 Release 1.7.5 2022-10-11 14:29:13 +02:00
Linus Dierheimer 4393fa1a47 ffStrbufLastIndexC: account for empty strings
#285
2022-10-11 14:28:35 +02:00
Linus Dierheimer 5ae2031bcf Manually cherry pick shell process name detection 2022-10-11 14:28:21 +02:00
Linus Dierheimer 779266e61e Release 1.7.5 2022-10-11 14:26:00 +02:00
李通洲 8e8d283959 Windows: fix crashing 2022-10-11 20:13:44 +08:00
李通洲 2cb7be67bd ci: add Windows 2022-10-11 19:44:43 +08:00
李通洲 9bc5c99fc8 Font: fix memleak on Linux 2022-10-11 19:44:43 +08:00
李通洲 424fbfc9c9 TerminalShell: actually support macOS 2022-10-11 19:44:43 +08:00
李通洲 3d2497f963 macOS: fix compile warnings 2022-10-11 19:19:43 +08:00
李通洲 2e42bbb1a2 Don't enable LTO on Debug mode
which breaks debuging on macOS
2022-10-11 19:19:43 +08:00
李通洲 9879a95570 Packages: fix scoop detection when it's not installed 2022-10-11 19:19:43 +08:00
Linus Dierheimer d54f14a14c ffStrbufLastIndexC: account for empty strings
#285
2022-10-11 12:37:54 +02:00
Linus Dierheimer cdcac06dbf Merge pull request #284 from LinusDierheimer/master
Print the last element of the default structure
2022-10-10 10:49:54 +02:00
Linus Dierheimer 6b81223002 Print the last element of the default structure
#283
2022-10-10 10:30:52 +02:00
Linus Dierheimer df986d36a2 Print the last element of the default structure
#283
2022-10-10 10:16:43 +02:00
Linus Dierheimer 173c9043e3 Merge pull request #282 from CarterLi/msys2
Introduce Windows support
2022-10-09 22:24:19 +02:00
Linus Dierheimer 488986e42e Release 1.7.3 2022-10-09 21:36:53 +02:00
253 changed files with 10284 additions and 4741 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ trim_trailing_whitespace = true
[*.{md,fflogo}]
trim_trailing_whitespace = false
[*.{txt,fflogo}]
[*.{fflogo}]
insert_final_newline = false
[*.yml]
+1 -1
View File
@@ -39,5 +39,5 @@ Output of `fastfetch --list-features`:
<!--
If you get the following error: `Error: couldn't find config: [...]`, copy the files in [presets](../../presets/) to `/usr/share/fastfetch/presets/` or `~/.local/share/fastfetch/presets/`.
If this isn't possible (or too much work) for you, post the output of `fastfetch --show-errors --recache --multithreading false --disable-linewrap false`.
If this isn't possible (or too much work) for you, post the output of `fastfetch --show-errors --multithreading false --disable-linewrap false`.
-->
+99 -14
View File
@@ -18,7 +18,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 libcjson-dev libnm-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -34,18 +34,21 @@ jobs:
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: ./flashfetch
run: time ./flashfetch
- name: run tests
run: ctest
- name: get fastfetch version
id: ffversion
run: echo "::set-output name=ffversion::$(./fastfetch --version-raw)"
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
- name: upload artifacts
uses: actions/upload-artifact@v3
@@ -64,7 +67,7 @@ jobs:
uses: actions/checkout@v3
- name: install required packages
run: brew install vulkan-loader molten-vk
run: brew install vulkan-loader molten-vk imagemagick chafa
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -80,11 +83,14 @@ jobs:
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: ./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
- name: run flashfetch
run: ./flashfetch
run: time ./flashfetch
- name: run tests
run: ctest
@@ -95,8 +101,8 @@ jobs:
name: fastfetch-macos
path: ./fastfetch-*.*
bsd:
name: BSD
freebsd:
name: FreeBSD
runs-on: macos-12
permissions:
security-events: write
@@ -113,16 +119,94 @@ jobs:
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package
./fastfetch --recache --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
./flashfetch
./fastfetch --list-features
time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors true --load-config presets/all
time ./flashfetch
ctest
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-bsd
name: fastfetch-freebsd
path: ./fastfetch-*.*
windows:
name: Windows
runs-on: windows-latest
permissions:
security-events: write
contents: read
defaults:
run:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: setup-msys2
uses: msys2/setup-msys2@v2
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
- 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:
languages: c, cpp
- name: configure project
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build .
- name: perform CodeQL analysis
uses: github/codeql-action/analyze@v2
- name: copy necessary dlls
run: cp /clang64/bin/{libcjson,libOpenCL,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
- name: run flashfetch
run: time ./flashfetch
- name: run tests
run: ctest
- name: create zip archive
run: zip fastfetch-$(./fastfetch --version-raw)-Windows.zip *.dll fastfetch.exe flashfetch.exe
- name: upload artifacts
uses: actions/upload-artifact@v3
with:
name: fastfetch-windows
path: ./fastfetch-*-Windows.zip
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'LinusDierheimer/fastfetch'
name: Release
@@ -130,7 +214,8 @@ jobs:
needs:
- linux
- macos
- bsd
- freebsd
- windows
permissions:
contents: write
steps:
@@ -150,4 +235,4 @@ jobs:
tag: ${{ needs.linux.outputs.ffversion }}
commit: ${{ github.sha }}
artifactErrorsFailBuild: true
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-bsd/*
artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-windows/*
+1
View File
@@ -3,6 +3,7 @@
**/.cache/
**/.kdev4/
**/.DS_Store
/.vs
cscope.*
tags
fastfetch.kdev4
+173 -3
View File
@@ -1,3 +1,173 @@
# 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:
* Fix memleaks Users module (Windows)
* Fix shell detection when installed with scoop (Windows)
* Don't use libcJSON as wlanapi's dll name (Windows)
* Align artifact names to other platforms (Windows)
# 1.8.1
Notable Changes:
* `Song` was used as an alias to `Media` module. It's removed to avoid confusion. All song related flags (`--song-key`, etc) should change to media (`--media-key`, etc). (@CarterLi)
Bugfixes:
* Mountpoint paths on linux get decoded correctly (#364)
* Color parsing once again works (@IanManske, #365)
* Using a custom key with a placeholder for the local ip module now does work correctly if multiple interfaces are present (#368)
# 1.8.0
This release introduces Windows support! Fastfetch now fully support all major desktop OSes (Linux, macOS, Windows and FreeBSD)
Notable Changes:
* Bios / Board / Chassis modules are splitted against Host module for performance reasons
* Caching is removed. Option `--nocache` is removed accordingly
Features:
* Windows (7 and newer) is officially and fully supported
* FreeBSD support is improved greatly (Bios, Cpu Temp, Cpu Usage, Disk, Host, Processes, Swap, Terminal / Shell, Uptime)
* Adds a new flag `--stat`, which prints time usage for individual modules
* Adds Wifi module which supports Windows and macOS
* Adds data source option for logo printing
* Detects Homebrew Cellar and Cask seperately
* Detects WSL version
* Detects disk based on mount point
* Exposes more chafa configs
* Improves performance for Cpu Usage, Public IP, Weather modules
* Improves performance for Kitty image protocol when both image width / height specified
* Improves performance for large file loading
* Improves performance for macOS WM and Host detection
* Improves shell and terminal detection on macOS
* Supports Deepin Terminal terminal font
* Supports GPU detection on Android
* Supports Kitty Terminal terminal font
* Supports bar output for percentage values
* Supports Bios module on macOS
* Supports eopkg package manager detection
* Supports iTerm image logo protocol
* Supports image logo printing on macOS
* Supports tcsh version detection
* Vulkan module on macOS no longer requires vulkan-loader to work
Logos:
* Alpine
* CRUX
* EndeavourOS
* Enso
* Garuda small
* Nobara
* OpenMandriva
* Parabola GNU/Linux-libre
* Rocky
* Rosa
* Solus
* Univalent
* Vanilla OS
Bugfixes:
* Fixes disk size detection on 32bit Linux (#337)
* Fixes cpu freq detection in WSL
* Fixes internal bug of FFstrbuf
* Fixes some memory leaks
* Fixes segfault if 0 is given as argument index
* Lots of code refactors
# 1.7.5
Fixes a crash on linux that could happen when getting zsh version (#285)
# 1.7.4
The last element in the default structure (currently the color blocks) is now printed again (#283)
# 1.7.3
A lot of small improvements for MacOS & BSD platforms.
Features:
* BSD is now officially supported (#228)
* MacPorts package manager support (@SladeGetz, #234)
* Battery support for MacOS (@CarterLi, #235)
* Processes, swap & terminal font support for MacOS(@CarterLi, #237)
* Media support for MacOS (@CarterLi, #242)
* Player support for MacOS (@CarterLi, #245)
* WM theme support for MacOS (@CarterLi, #246)
* CPU usage support for MacOS (@CarterLi, #247)
* Power Adapter module (@CarterLi, #249)
* Windows terminal font for WSL (@CarterLi, #254)
* Temps & Font support for MacOS (@CarterLi, #258)
* Terminal font support for Termux (@CarterLi, #263)
* Weather module (@CarterLi, #266)
Logos
* Crystal linux (@AloneER0, #239)
* FreeBSD (@draumaz, #244)
* New Ubuntu (@AloneER0, #259)
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)
# 1.7.2
Fixes the bash completions
@@ -30,12 +200,12 @@ Other:
# 1.7.0
This release brings support for MacOS!
This release brings support for MacOS!
The basics things are working, but it is far from feature parity with Linux.
I developed this in a VM, so bugs on real hardware are likely.
If you have a Mac and no idea what to do with your free time, i am very happy to accept pull requests / work on issues.
A lot of things were changed under the hood to make this possible, which should bring better performance and stability on all platforms.
A lot of things were changed under the hood to make this possible, which should bring better performance and stability on all platforms.
Besides that, the following things have changed:
@@ -101,7 +271,7 @@ Features:
* Load `/etc/fastfetch/config.conf` before user config
* Disk: print one decimal point if size < 100GB
* `--title-fqdn` option, to print fully qualified domain name instead of host name in title
Logos:
* updated old NixOS logo
+470 -259
View File
@@ -1,28 +1,45 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 1.7.2
VERSION 1.9.1
LANGUAGES C
DESCRIPTION "Fast system information tool"
HOMEPAGE_URL "https://github.com/LinusDierheimer/fastfetch"
)
set(PROJECT_LICENSE "MIT license")
###################
# Target Platform #
###################
if("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Ll]inux.*")
if(ANDROID)
set(LINUX FALSE)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Ll]inux.*")
set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Bb][Ss][Dd].*")
set(BSD TRUE CACHE BOOL "..." FORCE)
elseif(NOT APPLE AND NOT ANDROID AND NOT MSYS)
elseif(NOT APPLE AND NOT WIN32)
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()
if(MSYS)
if(WIN32)
enable_language(CXX)
endif()
#############################
# Compile time dependencies #
#############################
set(THREADS_PREFER_PTHREAD_FLAG NOT WIN32)
find_package(Threads)
find_package(PkgConfig)
if(NOT PKG_CONFIG_FOUND)
message(WARNING "pkg-config not found, library detection might be limited")
endif()
include(CheckIncludeFile)
#####################
# Configure options #
#####################
@@ -30,7 +47,7 @@ endif()
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR MSYS" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD" OFF)
@@ -42,31 +59,25 @@ 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_RPM "Enable rpm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD" 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)
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR 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 MSYS" OFF)
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR MSYS" 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_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
#############################
# Compile time dependencies #
#############################
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
include(CheckIncludeFile)
####################
# Compiler options #
####################
@@ -76,13 +87,23 @@ if(NOT CMAKE_BUILD_TYPE)
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
if(ENABLE_THREADS)
if(CMAKE_USE_WIN32_THREADS_INIT)
message(STATUS "Threads type: Win32 thread")
elseif(CMAKE_USE_PTHREADS_INIT)
message(STATUS "Threads type: pthread")
endif()
else()
message(STATUS "Threads type: disabled")
endif()
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
if(MSYS)
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
@@ -92,16 +113,18 @@ if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
endif()
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
if(NOT MSYS)
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")
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
#######################
@@ -160,6 +183,11 @@ if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
)
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}")
endif()
if(PROJECT_VERSION_TWEAK)
string(REGEX MATCH "[0-9]+" PROJECT_VERSION_TWEAK_NUM "${PROJECT_VERSION_TWEAK}")
else()
set(PROJECT_VERSION_TWEAK_NUM 0)
endif()
#############
# Text data #
@@ -167,9 +195,10 @@ endif()
function(fastfetch_load_text FILENAME OUTVAR)
file(READ "${FILENAME}" TEMP)
string(REPLACE "\n" "\\n" TEMP "${TEMP}")
string(REPLACE "\"" "\\\"" TEMP "${TEMP}")
string(REPLACE "$\\" "" TEMP "${TEMP}")
string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline
string(REPLACE "\n" "\\n" TEMP "${TEMP}") # Replace newlines with \n
string(REPLACE "\"" "\\\"" TEMP "${TEMP}") # Replace quotes with \"
string(REPLACE "$\\" "" TEMP "${TEMP}") # Remove $\, so we can unescape some things
set("${OUTVAR}" "${TEMP}" PARENT_SCOPE)
endfunction(fastfetch_load_text)
@@ -193,225 +222,284 @@ configure_file(src/fastfetch_config.h.in fastfetch_config.h)
#######################
set(LIBFASTFETCH_SRC
src/util/FFstrbuf.c
src/util/FFlist.c
src/util/FFvaluestore.c
src/common/init.c
src/common/io.c
src/common/printing.c
src/common/caching.c
src/common/properties.c
src/common/bar.c
src/common/font.c
src/common/format.c
src/common/parsing.c
src/common/settings.c
src/common/init.c
src/common/io.c
src/common/library.c
src/common/networking.c
src/logo/logo.c
src/logo/builtin.c
src/logo/image/image.c
src/logo/image/im7.c
src/logo/image/im6.c
src/detection/vulkan.c
src/detection/datetime.c
src/detection/title.c
src/detection/host/host.c
src/detection/os/os.c
src/common/parsing.c
src/common/printing.c
src/common/properties.c
src/common/settings.c
src/detection/cpu/cpu.c
src/detection/cpuUsage/cpuUsage.c
src/detection/gpu/gpu.c
src/detection/memory/memory.c
src/detection/font/font.c
src/detection/datetime.c
src/detection/disk/disk.c
src/detection/displayserver/displayserver.c
src/detection/terminalfont/terminalfont.c
src/detection/font/font.c
src/detection/gpu/gpu.c
src/detection/host/host.c
src/detection/locale/locale.c
src/detection/media/media.c
src/modules/break.c
src/modules/custom.c
src/modules/title.c
src/modules/separator.c
src/modules/os.c
src/modules/host.c
src/detection/os/os.c
src/detection/packages/packages.c
src/detection/terminalfont/terminalfont.c
src/detection/terminalshell/terminalshell.c
src/detection/vulkan.c
src/logo/builtin.c
src/logo/image/im6.c
src/logo/image/im7.c
src/logo/image/image.c
src/logo/logo.c
src/modules/battery.c
src/modules/bios.c
src/modules/board.c
src/modules/kernel.c
src/modules/uptime.c
src/modules/processes.c
src/modules/packages.c
src/modules/shell.c
src/modules/resolution.c
src/modules/de.c
src/modules/wm.c
src/modules/wmtheme.c
src/modules/theme.c
src/modules/icons.c
src/modules/font.c
src/modules/cursor.c
src/modules/terminal.c
src/modules/terminalfont.c
src/modules/brightness.c
src/modules/break.c
src/modules/chassis.c
src/modules/colors.c
src/modules/cpu.c
src/modules/cpuUsage.c
src/modules/gpu.c
src/modules/memory.c
src/modules/disk.c
src/modules/battery.c
src/modules/poweradapter.c
src/modules/locale.c
src/modules/vulkan.c
src/modules/localip.c
src/modules/publicip.c
src/modules/weather.c
src/modules/player.c
src/modules/song.c
src/modules/datetime.c
src/modules/cursor.c
src/modules/custom.c
src/modules/command.c
src/modules/date.c
src/modules/time.c
src/modules/colors.c
src/modules/opengl.c
src/modules/datetime.c
src/modules/de.c
src/modules/disk.c
src/modules/font.c
src/modules/gpu.c
src/modules/host.c
src/modules/icons.c
src/modules/kernel.c
src/modules/locale.c
src/modules/localip.c
src/modules/memory.c
src/modules/opencl.c
src/modules/opengl.c
src/modules/os.c
src/modules/packages.c
src/modules/player.c
src/modules/poweradapter.c
src/modules/processes.c
src/modules/publicip.c
src/modules/display.c
src/modules/separator.c
src/modules/shell.c
src/modules/media.c
src/modules/terminal.c
src/modules/terminalfont.c
src/modules/theme.c
src/modules/time.c
src/modules/title.c
src/modules/uptime.c
src/modules/users.c
src/modules/vulkan.c
src/modules/weather.c
src/modules/wifi.c
src/modules/wm.c
src/modules/wmtheme.c
src/util/FFlist.c
src/util/FFstrbuf.c
src/util/FFvaluestore.c
src/util/platform/FFPlatform.c
)
if(LINUX OR APPLE OR ANDROID OR BSD)
if(LINUX)
list(APPEND LIBFASTFETCH_SRC
src/detection/users/users_linux.c
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/disk/disk.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/packages/packages_linux.c
src/detection/kernel/kernel_linux.c
src/detection/localip/localip_linux.c
)
endif()
if(BSD OR APPLE)
list(APPEND LIBFASTFETCH_SRC
src/common/sysctl.c
)
endif()
if(LINUX OR ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/detection/cpu/cpu_linux.c
src/detection/memory/memory_linux.c
)
endif()
if(LINUX OR ANDROID OR BSD)
list(APPEND LIBFASTFETCH_SRC
src/detection/cpuUsage/cpuUsage_linux.c
src/detection/disk/disk_linux.c
src/detection/temps/temps_linux.c
src/detection/opengl/opengl_linux.c
src/detection/processes/processes_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
)
endif()
if(LINUX OR BSD)
list(APPEND LIBFASTFETCH_SRC
src/detection/host/host_linux.c
src/detection/battery/battery_linux.c
src/detection/bios/bios_linux.c
src/detection/board/board_linux.c
src/detection/os/os_linux.c
src/detection/gpu/gpu_linux.c
src/detection/battery/battery_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/disk/disk_linux.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/displayserver/linux/wmde.c
src/detection/terminalfont/terminalfont_linux.c
src/detection/media/media_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/font/font_linux.c
src/detection/qt.c
src/detection/gpu/gpu_linux.c
src/detection/gtk.c
)
endif()
if(MSYS)
list(APPEND LIBFASTFETCH_SRC
src/common/processing_linux.c
src/detection/host/host_windows.cpp
src/detection/bios/bios_windows.cpp
src/detection/board/board_windows.cpp
src/detection/cpu/cpu_windows.cpp
src/detection/gpu/gpu_windows.cpp
src/detection/battery/battery_windows.cpp
src/detection/displayserver/displayserver_windows.c
src/detection/wmtheme/wmtheme_windows.c
src/detection/opengl/opengl_windows.c
src/detection/users/users_windows.cpp
src/detection/os/os_windows.cpp
src/detection/processes/processes_windows.cpp
src/detection/disk/disk_windows.c
src/detection/cpuUsage/cpuUsage_windows.c
src/detection/cpuUsage/cpuUsage_nowait_windows.cpp
src/detection/memory/memory_windows.cpp
src/detection/font/font_windows.cpp
src/detection/terminalshell/terminalshell_linux.c
src/detection/terminalshell/terminalshell_windows.cpp
src/detection/terminalfont/terminalfont_linux.c
src/detection/host/host_linux.c
src/detection/localip/localip_linux.c
src/detection/media/media_linux.c
src/detection/memory/memory_linux.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
src/detection/packages/packages_windows.c
src/detection/kernel/kernel_windows.cpp
src/detection/localip/localip_windows.c
src/util/windows/wmi.cpp
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/media/media_nosupport.c
src/detection/processes/processes_linux.c
src/detection/qt.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/uptime/uptime_linux.c
src/detection/users/users_linux.c
src/detection/wifi/wifi_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/util/platform/FFPlatform_unix.c
)
endif()
if(APPLE)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_android.c
src/detection/bios/bios_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
src/detection/cpuUsage/cpuUsage_linux.c
src/detection/disk/disk_linux.c
src/detection/displayserver/displayserver_nosupport.c
src/detection/font/font_nosupport.c
src/detection/gpu/gpu_nosupport.c
src/detection/host/host_android.c
src/detection/localip/localip_linux.c
src/detection/media/media_nosupport.c
src/detection/memory/memory_linux.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_android.c
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_linux.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/uptime/uptime_linux.c
src/detection/users/users_linux.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/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_bsd.c
src/detection/bios/bios_bsd.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
src/detection/cursor/cursor_linux.c
src/detection/disk/disk_bsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
src/detection/displayserver/linux/xcb.c
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gtk.c
src/detection/host/host_bsd.c
src/detection/localip/localip_linux.c
src/detection/media/media_linux.c
src/detection/memory/memory_bsd.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_bsd.c
src/detection/qt.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/uptime/uptime_bsd.c
src/detection/users/users_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/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/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/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/localip/localip_linux.c
src/detection/media/media_apple.m
src/detection/memory/memory_apple.c
src/detection/opengl/opengl_apple.c
src/detection/os/os_apple.m
src/detection/packages/packages_apple.c
src/detection/poweradapter/poweradapter_apple.c
src/detection/processes/processes_bsd.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/uptime/uptime_bsd.c
src/detection/users/users_linux.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/detection/host/host_apple.c
src/detection/os/os_apple.m
src/detection/cpu/cpu_apple.c
src/detection/gpu/gpu_apple.c
src/detection/battery/battery_apple.c
src/detection/poweradapter/poweradapter_apple.c
src/detection/memory/memory_apple.c
src/detection/displayserver/displayserver_apple.c
src/detection/terminalfont/terminalfont_apple.m
src/detection/media/media_apple.m
src/detection/disk/disk_apple.m
src/detection/wmtheme/wmtheme_apple.m
src/detection/temps/temps_apple.c
src/detection/font/font_apple.m
src/detection/opengl/opengl_apple.c
src/detection/processes/processes_apple.c
src/detection/bios/bios_nosupport.c
src/detection/board/board_nosupport.c
src/util/platform/FFPlatform_unix.c
)
endif()
if(BSD)
elseif(WIN32)
list(APPEND LIBFASTFETCH_SRC
src/detection/cpu/cpu_bsd.c
src/detection/memory/memory_bsd.c
)
endif()
if(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/detection/host/host_android.c
src/detection/os/os_android.c
src/detection/terminalfont/terminalfont_android.c
src/detection/bios/bios_nosupport.c
src/detection/board/board_nosupport.c
src/detection/displayserver/displayserver_nosupport.c
src/detection/battery/battery_nosupport.c
src/detection/gpu/gpu_nosupport.c
src/detection/font/font_nosupport.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/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
src/detection/cursor/cursor_windows.c
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/host/host_windows.c
src/detection/localip/localip_windows.c
src/detection/media/media_nosupport.c
src/detection/wmtheme/wmtheme_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/terminalfont/terminalfont_windows.c
src/detection/terminalshell/terminalshell_windows.cpp
src/detection/uptime/uptime_windows.c
src/detection/users/users_windows.c
src/detection/wifi/wifi_windows.c
src/detection/wmtheme/wmtheme_windows.c
src/util/windows/getline.c
src/util/windows/registry.c
src/util/windows/unicode.c
src/util/windows/wmi.cpp
src/util/platform/FFPlatform_windows.c
)
endif()
@@ -421,31 +509,38 @@ add_library(libfastfetch OBJECT
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
CHECK_INCLUDE_FILE("sys/sysinfo.h" HAVE_SYSINFO_H)
if(HAVE_SYSINFO_H)
# needs to be public, because changes fastfech.h ABI
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_SYSINFO_H)
endif()
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX_H)
if(HAVE_UTMPX_H)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX_H)
endif()
function(ff_lib_enable VARNAME)
function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
if(NOT ENABLE_${VARNAME})
return()
endif()
pkg_search_module(${VARNAME} ${ARGN})
if(PKG_CONFIG_FOUND)
pkg_search_module(${VARNAME} QUIET ${PKGCONFIG_NAMES})
endif()
if(NOT ${VARNAME}_FOUND)
message(WARNING "Package ${ARGV1} not found, building without support.")
find_package(${CMAKE_NAME} QUIET)
set(${VARNAME}_FOUND ${${CMAKE_NAME}_FOUND})
set(${VARNAME}_INCLUDE_DIRS ${${CMAKE_NAME}_INCLUDE_DIRS})
set(${VARNAME}_LIBRARIES ${${CMAKE_NAME}_LIBRARIES})
set(${VARNAME}_CFLAGS_OTHER ${${CMAKE_NAME}_CFLAGS_OTHER})
endif()
if(NOT ${VARNAME}_FOUND)
message(STATUS "Library: missing: ${VARNAME}")
return()
endif()
message(STATUS "Library: found ${VARNAME}")
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_${VARNAME}=1)
target_include_directories(libfastfetch PRIVATE ${${VARNAME}_INCLUDE_DIRS})
target_link_directories(libfastfetch PRIVATE ${${VARNAME}_LIBRARY_DIRS})
foreach(FLAG ${${VARNAME}_CFLAGS_OTHER})
if(FLAG MATCHES "-D.*")
@@ -455,50 +550,150 @@ function(ff_lib_enable VARNAME)
endforeach()
endfunction()
ff_lib_enable(LIBPCI libpci)
ff_lib_enable(VULKAN vulkan)
ff_lib_enable(WAYLAND wayland-client)
ff_lib_enable(XCB_RANDR xcb-randr)
ff_lib_enable(XCB xcb)
ff_lib_enable(XRANDR xrandr)
ff_lib_enable(X11 x11)
ff_lib_enable(GIO gio-2.0)
ff_lib_enable(DCONF dconf)
ff_lib_enable(DBUS dbus-1)
ff_lib_enable(XFCONF libxfconf-0)
ff_lib_enable(SQLITE3 sqlite3)
ff_lib_enable(RPM rpm)
ff_lib_enable(IMAGEMAGICK7 MagickCore-7.Q16HDRI MagickCore-7.Q16 MagickCore-7 /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc /usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc /usr/lib/imagemagick7/pkgconfig/MagickCore-7.pc)
ff_lib_enable(IMAGEMAGICK6 MagickCore-6.Q16HDRI MagickCore-6.Q16 MagickCore-6 /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc /usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc /usr/lib/imagemagick6/pkgconfig/MagickCore-6.pc)
ff_lib_enable(ZLIB zlib)
ff_lib_enable(CHAFA chafa>=1.10)
ff_lib_enable(EGL egl)
ff_lib_enable(GLX glx)
ff_lib_enable(OSMESA osmesa)
ff_lib_enable(OPENCL OpenCL)
ff_lib_enable(LIBCJSON libcjson)
ff_lib_enable(FREETYPE freetype2)
ff_lib_enable(LIBPCI
"libpci"
"Pci"
)
ff_lib_enable(VULKAN
"vulkan"
"Vulkan"
)
ff_lib_enable(WAYLAND
"wayland-client"
"WaylandClient"
)
ff_lib_enable(XCB_RANDR
"xcb-randr"
"XcbRandr"
)
ff_lib_enable(XCB
"xcb"
"Xcb"
)
ff_lib_enable(XRANDR
"xrandr"
"XRandr"
)
ff_lib_enable(X11
"x11"
"X11"
)
ff_lib_enable(GIO
"gio-2.0"
"GIO"
)
ff_lib_enable(DCONF
"dconf"
"DConf"
)
ff_lib_enable(DBUS
"dbus-1"
"DBus"
)
ff_lib_enable(XFCONF
"libxfconf-0"
"XFConf"
)
ff_lib_enable(SQLITE3
"sqlite3"
"SQLite3"
)
ff_lib_enable(RPM
"rpm"
"RPM"
)
ff_lib_enable(IMAGEMAGICK7
"MagickCore-7.Q16HDRI;MagickCore-7.Q16;MagickCore-7;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16HDRI.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.Q16.pc;/usr/lib/imagemagick7/pkgconfig/MagickCore-7.pc"
"ImageMagick7"
)
ff_lib_enable(IMAGEMAGICK6
"MagickCore-6.Q16HDRI;MagickCore-6.Q16;MagickCore-6;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16HDRI.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.Q16.pc;/usr/lib/imagemagick6/pkgconfig/MagickCore-6.pc"
"ImageMagick6"
)
ff_lib_enable(ZLIB
"zlib"
"ZLIB"
)
ff_lib_enable(CHAFA
"chafa>=1.10"
"Chafa"
)
ff_lib_enable(EGL
"egl"
"EGL"
)
ff_lib_enable(GLX
"glx"
"GLX"
)
ff_lib_enable(OSMESA
"osmesa"
"OSMesa"
)
ff_lib_enable(OPENCL
"OpenCL"
"OpenCL"
)
ff_lib_enable(LIBCJSON
"libcjson"
"CJson"
)
ff_lib_enable(LIBNM
"libnm"
"libnm"
)
ff_lib_enable(FREETYPE
"freetype2"
"FreeType2"
)
if(ENABLE_THREADS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32
target_link_libraries(libfastfetch PRIVATE Threads::Threads)
endif()
endif()
if(ENABLE_BUFFER)
target_compile_definitions(libfastfetch PRIVATE FF_ENABLE_BUFFER)
endif()
if(APPLE)
target_link_libraries(libfastfetch
PRIVATE "-framework CoreFoundation"
PRIVATE "-framework IOKit"
PRIVATE "-framework CoreGraphics"
PRIVATE "-framework OpenGL"
PRIVATE "-framework OpenCL"
PRIVATE "-framework Cocoa"
PRIVATE "-framework CoreWLAN"
PRIVATE "-framework CoreVideo"
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks"
)
elseif(MSYS)
elseif(WIN32)
target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601)
target_link_libraries(libfastfetch
PRIVATE "wbemuuid"
PRIVATE "ole32"
PRIVATE "oleaut32"
PRIVATE "dwmapi"
PRIVATE "opengl32"
PRIVATE "gdi32"
PRIVATE "iphlpapi"
PRIVATE "ole32"
PRIVATE "oleaut32"
PRIVATE "opengl32"
PRIVATE "wbemuuid"
PRIVATE "ws2_32"
PRIVATE "ntdll"
PRIVATE "version"
PRIVATE "setupapi"
PRIVATE "dxgi"
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
@@ -508,7 +703,6 @@ target_include_directories(libfastfetch
target_link_libraries(libfastfetch
PRIVATE ${CMAKE_DL_LIBS}
PRIVATE Threads::Threads
)
######################
@@ -518,6 +712,9 @@ target_link_libraries(libfastfetch
add_executable(fastfetch
src/fastfetch.c
)
target_compile_definitions(fastfetch
PRIVATE FASTFETCH_TARGET_BINARY_NAME=fastfetch
)
target_link_libraries(fastfetch
PRIVATE libfastfetch
)
@@ -525,10 +722,30 @@ target_link_libraries(fastfetch
add_executable(flashfetch
src/flashfetch.c
)
target_compile_definitions(flashfetch
PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
)
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
PRIVATE src/util/windows/version.rc
)
set(TARGET_NAME flashfetch)
target_sources(flashfetch
PRIVATE src/util/windows/version.rc
)
endif()
###################
# Testing targets #
###################
@@ -600,12 +817,6 @@ if(LINUX)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
elseif(APPLE)
set(CPACK_GENERATOR "${CPACK_GENERATOR};DragNDrop")
set(CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK TRUE)
elseif(BSD)
set(CPACK_GENERATOR "${CPACK_GENERATOR};FreeBSD")
endif()
set(CPACK_SET_DESTDIR ON)
+67 -29
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, BSD, MacOS and Windows on [MSYS2](https://www.msys2.org/) 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,27 +10,36 @@ 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 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.
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 `$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. Therefore its only hard dependencies are `libc` (any implementation of the c standard library), `libdl` and `libpthread`. They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most linux distributions, so you probably don't have to worry about it.
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.
The following libraries are used if present at runtime:
### Linux and FreeBSD
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
* [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output.
* [`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.
@@ -44,50 +53,72 @@ The following libraries are used if present at runtime:
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
* [`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 ( Windows, WSL ).
* [`freetype`](https://www.freetype.org/): Needed for Termux font detection ( Android ).
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection on Linux.
### 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)
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
### Windows
* [`wlanapi`](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/): A system dll which isn't supported by Windows Server by default. Used for Wifi info detection.
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Used for Windows Terminal font detection. [`cjson`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-cjson)
* [`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, 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.
### Android
* [`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, DateTime, Date, Time, Locale, Colors, Break, Custom
Battery, Bios, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, GPU, Host, Icons, Kernel, Locale, LocalIP, Media, Memory, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator OS, Shell, Swap, Terminal, Terminal Font, Theme, Time, Title, Uptime, Vulkan, Wifi, WM, WMTheme
```
##### Logos
##### Builtin logos
```
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal, Debian, Devuan, Deepin, Endeavour, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Ubuntu, 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, 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 graphics protocol or chafas image to text conversion.
##### Package managers
```
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop
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, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal, Termux, mintty
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, mintty, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal
```
## Building
fastfetch uses [`cmake`](https://cmake.org/) and [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) for building. The simplest steps to build the fastfetch and flashfetch binaries are:
fastfetch uses [`cmake`](https://cmake.org/) for building. [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) is recommended for better library detection. The simplest steps to build the fastfetch and flashfetch binaries are:
```bash
mkdir -p build
cd build
@@ -95,13 +126,20 @@ cmake ..
cmake --build . --target fastfetch --target flashfetch
```
If pkg-config fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
If the build process fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
### Building on Windows
Currently [MSYS2](https://www.msys2.org/) is required to build fastfetch. Running fastfetch requires msys2 runtime library (`msys-2.0.dll`) but not full MSYS2 environment.
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.
Full native Windows executable is planned.
1. Install [MSYS2](https://www.msys2.org/#installation)
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
```
Follow the building instructions of Linux next.
## Packaging
@@ -117,7 +155,7 @@ Full native Windows executable is planned.
## FAQ
Q: Why do you need a very performant version of neofetch?
> I like putting neofetch in my ~/.bashrc to have a system overwiew whenever i use the terminal, but the slow speed annoyed me, so i created this. Also neofetch didn't output everything correctly (e.g Font is displayed as "[Plasma], Noto Sans, 10 [GTK2/3]") and writing my own tool gave me the possibility to fine tune it to run perfectly on at least my configuration.
> I like putting neofetch in my ~/.bashrc to have a system overwiew whenever I use the terminal, but the slow speed annoyed me, so I created this. Also neofetch didn't output everything correctly (e.g Font is displayed as "[Plasma], Noto Sans, 10 [GTK2/3]") and writing my own tool gave me the possibility to fine tune it to run perfectly on at least my configuration.
Q: It does not display [*] correctly for me, what can i do?
> This is most likely because your system is not implemented (yet). At the moment i am focusing more on making the core app better, than adding more configurations. Feel free to open a pull request if you want to add support for your configuration
Q: It does not display [*] correctly for me, what can I do?
> This is most likely because your system is not implemented (yet). At the moment I am focusing more on making the core app better, than adding more configurations. Feel free to open a pull request if you want to add support for your configuration
+21 -6
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"
@@ -160,6 +160,8 @@ __fastfetch_completion()
"--print-config-system"
"--print-config-user"
"--print-structure"
"--gen-config"
"--gen-config-force"
)
local FF_OPTIONS_HELP=(
@@ -169,11 +171,10 @@ __fastfetch_completion()
local FF_OPTIONS_BOOL=(
"-r"
"--recache"
"--nocache"
"--show-errors"
"--logo-print-remaining"
"--multithreading"
"--stat"
"--allow-slow-operations"
"--disable-linewrap"
"--hide-cursor"
@@ -188,6 +189,15 @@ __fastfetch_completion()
"--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"
"--disk-show-unknown"
)
local FF_OPTIONS_STRING=(
@@ -195,6 +205,7 @@ __fastfetch_completion()
"--logo-padding"
"--logo-padding-left"
"--logo-padding-right"
"--logo-padding-top"
"--logo-color-1"
"--logo-color-2"
"--logo-color-3"
@@ -216,6 +227,7 @@ __fastfetch_completion()
"--set"
"--set-keyless"
"--player-name"
"--percent-type"
"--public-ip-url"
"--public-ip-timeout"
"--weather-output-format"
@@ -241,9 +253,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"
@@ -304,6 +316,9 @@ __fastfetch_completion()
"--public-ip-key"
"--public-ip-format"
"--public-ip-error"
"--wifi-key"
"--wifi-format"
"--wifi-error"
"--weather-key"
"--weather-format"
"--weather-error"
+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:Kernel:Uptime:Processes:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Song:PublicIP:LocalIP: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:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Weather:Break:Colors
-1
View File
@@ -1,4 +1,3 @@
--disable-linewrap false
--multithreading false
--show-errors
--recache
+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 -4
View File
@@ -1,11 +1,11 @@
--os-format System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}
--host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; bios_date: {}; bios_release: {}; bios_vendor: {}; bios_version: {}; board_name: {}; board_vendor: {}; board_version: {}; chassis_type: {}; chassis_vendor: {}; chassis_version: {}; sys_vendor: {}
--host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; sys_vendor: {}
--kernel-format Sysname: {}; Release: {}; Version: {}
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
--processes-format Count: {}
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; xbps: {}; apk: {}; flatpak: {}; snap: {}; brew: {}
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak: {}; 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: {}
--de-format Process name: {}; Pretty name: {}; Version: {}
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
--wm-theme-format Name: {}
@@ -19,7 +19,7 @@
--cpu-usage-format Percentage: {}
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}
--memory-format Used: {}; Total: {}; Percentage: {}
--disk-format Used: {}; Total: {}; Files: {}; Percentage: {}
--disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; Removable: {}; Hidden: {}; Filesystem: {}; Name: {}
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
--poweradapter-format Watts: {}; Name: {}; Manufactor: {}; Model: {}; Description: {}
--player-format Pretty: {}; Name: {}; Bus: {}; Url: {}
+49
View File
@@ -0,0 +1,49 @@
#include "util/textModifier.h"
#include "bar.h"
// green, yellow, red: print the color on nth (0~9) block
// set its value == 10 means the color will not be printed
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red)
{
assert(green <= 10 && yellow <= 10 && red <= 10);
// [ 0%, 5%) prints 0 blocks
// [ 5%, 15%) prints 1 block;
// ...
// [85%, 95%) prints 9 blocks;
// [95%,100%] prints 10 blocks
percent = (uint8_t)(percent + 5) / 10;
assert(percent <= 10);
if(!instance->config.pipe)
ffStrbufAppendS(buffer, "\033[97m[ ");
else
ffStrbufAppendS(buffer, "[ ");
for (uint8_t i = 0; i < percent; ++i)
{
if(!instance->config.pipe)
{
if (i == green)
ffStrbufAppendS(buffer, "\033[32m");
else if (i == yellow)
ffStrbufAppendS(buffer, "\033[93m");
else if (i == red)
ffStrbufAppendS(buffer, "\033[91m");
}
ffStrbufAppendS(buffer, "");
}
if (percent < 10)
{
if(!instance->config.pipe)
ffStrbufAppendS(buffer, "\033[97m");
for (uint8_t i = percent; i < 10; ++i)
ffStrbufAppendS(buffer, "-");
}
if(!instance->config.pipe)
ffStrbufAppendS(buffer, "\033[97m ]" FASTFETCH_TEXT_MODIFIER_RESET);
else
ffStrbufAppendS(buffer, " ]");
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#ifndef FF_INCLUDED_common_bar
#define FF_INCLUDED_common_bar
#include "fastfetch.h"
enum
{
FF_PERCENTAGE_TYPE_NUM_BIT = 1,
FF_PERCENTAGE_TYPE_BAR_BIT = 2,
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 4,
};
void ffAppendPercentBar(FFinstance* instance, FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
#endif
-327
View File
@@ -1,327 +0,0 @@
#include "fastfetch.h"
#include "common/caching.h"
#include "common/io.h"
#include "common/printing.h"
#include <stdlib.h>
#include <string.h>
#define FF_CACHE_VERSION_NAME "cacheversion"
#define FF_CACHE_VERSION_EXTENSION "ffv"
#define FF_CACHE_VALUE_EXTENSION "ffcv"
#define FF_CACHE_SPLIT_EXTENSION "ffcs"
#define FF_CACHE_EXTENSION_V1 "ffc1"
static void getCacheFilePath(const FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* buffer)
{
ffStrbufAppend(buffer, &instance->state.cacheDir);
ffStrbufAppendS(buffer, moduleName);
if(extension != NULL)
{
ffStrbufAppendC(buffer, '.');
ffStrbufAppendS(buffer, extension);
}
}
static void readCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* buffer)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
getCacheFilePath(instance, moduleName, extension, &path);
ffAppendFileBuffer(path.chars, buffer);
ffStrbufDestroy(&path);
}
static void writeCacheFile(FFinstance* instance, const char* moduleName, const char* extension, FFstrbuf* content)
{
FFstrbuf path;
ffStrbufInitA(&path, 64);
getCacheFilePath(instance, moduleName, extension, &path);
ffWriteFileBuffer(path.chars, content);
ffStrbufDestroy(&path);
}
void ffCacheValidate(FFinstance* instance)
{
FFstrbuf content;
ffStrbufInit(&content);
readCacheFile(instance, FF_CACHE_VERSION_NAME, FF_CACHE_VERSION_EXTENSION, &content);
const char exactVersion[] = FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK;
bool isSameVersion = ffStrbufCompS(&content, exactVersion) == 0;
ffStrbufDestroy(&content);
if(isSameVersion)
return;
instance->config.recache = true;
FFstrbuf version;
ffStrbufInitA(&version, sizeof(exactVersion));
ffStrbufAppendS(&version, exactVersion);
writeCacheFile(instance, FF_CACHE_VERSION_NAME, FF_CACHE_VERSION_EXTENSION, &version);
ffStrbufDestroy(&version);
}
void ffCacheOpenWrite(FFinstance* instance, const char* moduleName, FFcache* cache)
{
FFstrbuf cacheFileValue;
ffStrbufInitA(&cacheFileValue, 64);
getCacheFilePath(instance, moduleName, FF_CACHE_VALUE_EXTENSION, &cacheFileValue);
cache->value = fopen(cacheFileValue.chars, "w");
ffStrbufDestroy(&cacheFileValue);
FFstrbuf cacheFileSplit;
ffStrbufInitA(&cacheFileSplit, 64);
getCacheFilePath(instance, moduleName, FF_CACHE_SPLIT_EXTENSION, &cacheFileSplit);
cache->split = fopen(cacheFileSplit.chars, "w");
ffStrbufDestroy(&cacheFileSplit);
}
void ffCacheClose(FFcache* cache)
{
if(cache->value != NULL)
fclose(cache->value);
if(cache->split != NULL)
fclose(cache->split);
}
static bool printCachedValue(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
readCacheFile(instance, moduleName, FF_CACHE_VALUE_EXTENSION, &content);
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
if(content.length == 0)
{
ffStrbufDestroy(&content);
return false;
}
uint8_t moduleCounter = 1;
uint32_t startIndex = 0;
while(startIndex < content.length)
{
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
ffPrintLogoAndKey(instance, moduleName, moduleIndex, &moduleArgs->key);
puts(content.chars + startIndex);
startIndex = nullByteIndex + 1;
++moduleCounter;
}
ffStrbufDestroy(&content);
return moduleCounter > 1;
}
static bool printCachedFormat(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs)
{
FFstrbuf content;
ffStrbufInitA(&content, 512);
readCacheFile(instance, moduleName, FF_CACHE_SPLIT_EXTENSION, &content);
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
if(content.length == 0)
return false;
uint8_t moduleCounter = 1;
FFformatarg* arguments = calloc(numArgs, sizeof(FFformatarg));
uint32_t argumentCounter = 0;
uint32_t startIndex = 0;
while(startIndex < content.length)
{
arguments[argumentCounter].type = FF_FORMAT_ARG_TYPE_STRING;
arguments[argumentCounter].value = &content.chars[startIndex];
++argumentCounter;
uint32_t nullByteIndex = ffStrbufNextIndexC(&content, startIndex, '\0');
if(argumentCounter == numArgs)
{
uint8_t moduleIndex = (moduleCounter == 1 && nullByteIndex == content.length) ? 0 : moduleCounter;
ffPrintFormat(instance, moduleName, moduleIndex, moduleArgs, numArgs, arguments);
++moduleCounter;
argumentCounter = 0;
}
startIndex = nullByteIndex + 1;
}
free(arguments);
ffStrbufDestroy(&content);
return moduleCounter > 1;
}
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs)
{
if(instance->config.recache)
return false;
if(moduleArgs->outputFormat.length == 0)
return printCachedValue(instance, moduleName, moduleArgs);
else
return printCachedFormat(instance, moduleName, moduleArgs, numArgs);
}
void ffPrintAndAppendToCache(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFcache* cache, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments)
{
if(moduleArgs->outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, moduleName, moduleIndex, &moduleArgs->key);
ffStrbufPutTo(value, stdout);
}
else
{
ffPrintFormat(instance, moduleName, moduleIndex, moduleArgs, numArgs, arguments);
}
if(cache->value != NULL)
{
ffStrbufWriteTo(value, cache->value);
fputc('\0', cache->value);
}
if(cache->split == NULL)
return;
for(uint32_t i = 0; i < numArgs; i++)
{
FFstrbuf buffer;
ffStrbufInitA(&buffer, 64);
ffFormatAppendFormatArg(&buffer, &arguments[i]);
ffStrbufWriteTo(&buffer, cache->split);
ffStrbufDestroy(&buffer);
fputc('\0', cache->split);
}
}
void ffPrintAndWriteToCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments)
{
FFcache cache;
ffCacheOpenWrite(instance, moduleName, &cache);
ffPrintAndAppendToCache(instance, moduleName, 0, moduleArgs, &cache, value, numArgs, arguments);
ffCacheClose(&cache);
}
typedef struct FFCacheRead
{
FFstrbuf data;
uint32_t position;
} FFCacheRead;
static bool cacheReadStrbuf(FFCacheRead* cacheRead, FFstrbuf* strbuf)
{
if(cacheRead->position >= cacheRead->data.length)
return false;
ffStrbufAppendS(strbuf, cacheRead->data.chars + cacheRead->position);
cacheRead->position += strbuf->length + 1; // skip the null byte too
return true;
}
static bool cacheReadData(FFCacheRead* cacheRead, size_t dataSize, void* data)
{
if(cacheRead->position + dataSize > cacheRead->data.length)
return false;
memcpy(data, cacheRead->data.chars + cacheRead->position, dataSize);
cacheRead->position += (uint32_t) dataSize;
return true;
}
static bool cacheResetStrbuf(FFCache* cache, FFstrbuf* strbuf)
{
FF_UNUSED(cache);
ffStrbufClear(strbuf);
return true;
}
static bool cacheResetData(FFCache* cacheRead, size_t dataSize, void* data)
{
FF_UNUSED(cacheRead, dataSize, data);
return true;
}
bool ffCacheRead(const FFinstance* instance, void* obj, const char* cacheName, FFCacheMethodCallback callback)
{
if(instance->config.recache)
return false;
FFCacheRead cache;
bool result;
FFstrbuf path;
ffStrbufInitA(&path, 128);
getCacheFilePath(instance, cacheName, FF_CACHE_EXTENSION_V1, &path);
cache.position = 0;
ffStrbufInitA(&cache.data, 256);
result = ffAppendFileBuffer(path.chars, &cache.data);
if(result)
result = callback(obj, &cache, (FFCacheMethodStrbuf) cacheReadStrbuf, (FFCacheMethodData) cacheReadData);
if(result)
result = cache.position == cache.data.length;
if(!result)
callback(obj, NULL, (FFCacheMethodStrbuf) cacheResetStrbuf, (FFCacheMethodData) cacheResetData);
ffStrbufDestroy(&cache.data);
ffStrbufDestroy(&path);
return result;
}
typedef struct FFCacheWrite
{
FFstrbuf data;
} FFCacheWrite;
static bool cacheWriteStrbuf(FFCacheWrite* cacheWrite, FFstrbuf* strbuf)
{
ffStrbufEnsureFree(&cacheWrite->data, strbuf->length);
memcpy(cacheWrite->data.chars + cacheWrite->data.length, strbuf->chars, strbuf->length +1); //Copy the nullbyte too
cacheWrite->data.length += strbuf->length + 1;
return true;
}
static bool cacheWriteData(FFCacheWrite* cacheWrite, size_t dataSize, const void* data)
{
ffStrbufEnsureFree(&cacheWrite->data, (uint32_t) dataSize);
memcpy(cacheWrite->data.chars + cacheWrite->data.length, data, dataSize);
cacheWrite->data.length += (uint32_t) dataSize;
return true;
}
void ffCacheWrite(const FFinstance* instance, void* obj, const char* cacheName, FFCacheMethodCallback callback)
{
if(!instance->config.cacheSave)
return;
FFCacheWrite cache;
FFstrbuf path;
ffStrbufInitA(&path, 128);
getCacheFilePath(instance, cacheName, FF_CACHE_EXTENSION_V1, &path);
ffStrbufInitA(&cache.data, 256);
callback(obj, &cache, (FFCacheMethodStrbuf) cacheWriteStrbuf, (FFCacheMethodData) cacheWriteData);
ffWriteFileBuffer(path.chars, &cache.data);
ffStrbufDestroy(&cache.data);
ffStrbufDestroy(&path);
}
-33
View File
@@ -1,33 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_common_caching
#define FF_INCLUDED_common_caching
#include "fastfetch.h"
#include "common/format.h"
typedef struct FFcache
{
FILE* value;
FILE* split;
} FFcache;
void ffCacheValidate(FFinstance* instance);
void ffCacheOpenWrite(FFinstance* instance, const char* moduleName, FFcache* cache);
void ffCacheClose(FFcache* cache);
bool ffPrintFromCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, uint32_t numArgs);
void ffPrintAndAppendToCache(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFcache* cache, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments);
void ffPrintAndWriteToCache(FFinstance* instance, const char* moduleName, const FFModuleArgs* moduleArgs, const FFstrbuf* value, uint32_t numArgs, const FFformatarg* arguments);
typedef void FFCache;
typedef bool(*FFCacheMethodStrbuf)(FFCache* cache, FFstrbuf* strbuf);
typedef bool(*FFCacheMethodData)(FFCache* cache, size_t dataSize, void* data);
typedef bool(*FFCacheMethodCallback)(void* data, FFCache* cache, FFCacheMethodStrbuf strbufMethod, FFCacheMethodData dataMethod);
bool ffCacheRead(const FFinstance* instance, void* obj, const char* cacheName, FFCacheMethodCallback callback);
void ffCacheWrite(const FFinstance* instance, void* obj, const char* cacheName, FFCacheMethodCallback callback);
#endif
+21 -5
View File
@@ -1,23 +1,30 @@
#include "fastfetch.h"
#include "common/format.h"
#include "common/parsing.h"
#include "util/textModifier.h"
#include <inttypes.h>
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
{
if(formatarg->type == FF_FORMAT_ARG_TYPE_INT)
ffStrbufAppendF(buffer, "%i", *(int*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT)
ffStrbufAppendF(buffer, "%u", *(uint32_t*)formatarg->value);
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
ffStrbufAppendF(buffer, "%hu", *(uint16_t*)formatarg->value);
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
ffStrbufAppendF(buffer, "%hhu", *(uint8_t*)formatarg->value);
ffStrbufAppendF(buffer, "%" PRIu8, *(uint8_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRING)
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)
ffStrbufAppendS(buffer, formatarg->value != NULL ? "true" : "false");
else if(formatarg->type == FF_FORMAT_ARG_TYPE_LIST)
{
const FFlist* list = formatarg->value;
@@ -34,6 +41,14 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
}
}
/**
* @brief parses a string to a uint32_t
*
* If the string can't be parsed, or is < 1, uint32_t max is returned.
*
* @param placeholderValue the string to parse
* @return uint32_t the parsed value
*/
static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
{
uint32_t result = UINT32_MAX;
@@ -41,7 +56,7 @@ static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
if(placeholderValue->chars[0] != '-')
sscanf(placeholderValue->chars, "%u", &result);
return result;
return result == 0 ? UINT32_MAX : result;
}
static inline void appendInvalidPlaceholder(FFstrbuf* buffer, const char* start, const FFstrbuf* placeholderValue, uint32_t index, uint32_t formatStringLength)
@@ -72,7 +87,8 @@ static inline bool formatArgSet(const FFformatarg* arg)
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet(arg->value)) ||
(arg->type == FF_FORMAT_ARG_TYPE_UINT8 && *(uint8_t*)arg->value > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_UINT16 && *(uint16_t*)arg->value > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0)
(arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0) ||
(arg->type == FF_FORMAT_ARG_TYPE_BOOL && arg->value != NULL)
);
}
+5 -1
View File
@@ -12,8 +12,10 @@ 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_LIST,
FF_FORMAT_ARG_TYPE_BOOL
} FFformatargtype;
typedef struct FFformatarg
@@ -25,4 +27,6 @@ typedef struct FFformatarg
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
#define FF_FORMAT_ARG_VALUE_BOOL(xpr) ((xpr) ? (const void*) 1 : NULL)
#endif
+127 -197
View File
@@ -1,133 +1,37 @@
#include "fastfetch.h"
#include "common/caching.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"
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <pthread.h>
static bool strbufEqualsAdapter(const void* first, const void* second)
{
return ffStrbufComp(second, first) == 0;
}
static void initConfigDirs(FFstate* state)
{
ffListInit(&state->configDirs, sizeof(FFstrbuf));
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
if(ffStrSet(xdgConfigHome))
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigHome);
ffStrbufEnsureEndsWithC(buffer, '/');
}
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
if(ffListFirstIndexComp(&state->configDirs, element, strbufEqualsAdapter) < 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)
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)
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 initCacheDir(FFstate* state)
{
ffStrbufInitA(&state->cacheDir, 64);
ffStrbufAppendS(&state->cacheDir, getenv("XDG_CACHE_HOME"));
if(state->cacheDir.length == 0)
{
ffStrbufAppendS(&state->cacheDir, state->passwd->pw_dir);
ffStrbufAppendS(&state->cacheDir, "/.cache/");
}
else
ffStrbufEnsureEndsWithC(&state->cacheDir, '/');
mkdir(state->cacheDir.chars, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH); //I hope everybody has a cache folder, but who knows
ffStrbufAppendS(&state->cacheDir, "fastfetch/");
mkdir(state->cacheDir.chars, S_IRWXU | S_IRGRP | S_IROTH);
}
#ifdef _WIN32
#include <wincon.h>
#include <locale.h>
#include <shlobj.h>
#include "util/windows/unicode.h"
#else
#include <signal.h>
#endif
static void initState(FFstate* state)
{
state->logoWidth = 0;
state->logoHeight = 0;
state->keysHeight = 0;
state->passwd = getpwuid(getuid());
uname(&state->utsname);
#if FF_HAVE_SYSINFO_H
sysinfo(&state->sysinfo);
#endif
initConfigDirs(state);
initCacheDir(state);
ffPlatformInit(&state->platform);
}
static void initModuleArg(FFModuleArgs* args)
{
ffStrbufInitA(&args->key, 0);
ffStrbufInitA(&args->outputFormat, 0);
ffStrbufInitA(&args->errorFormat, 0);
ffStrbufInit(&args->key);
ffStrbufInit(&args->outputFormat);
ffStrbufInit(&args->errorFormat);
}
static void defaultConfig(FFinstance* instance)
@@ -138,9 +42,17 @@ 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;
instance->config.logo.preserveAspectRadio = false;
instance->config.logo.chafaFgOnly = false;
ffStrbufInitS(&instance->config.logo.chafaSymbols, "block+border+space-wide-inverted"); // Chafa default
instance->config.logo.chafaCanvasMode = UINT32_MAX;
instance->config.logo.chafaColorSpace = UINT32_MAX;
instance->config.logo.chafaDitherMode = UINT32_MAX;
ffStrbufInit(&instance->config.colorKeys);
ffStrbufInit(&instance->config.colorTitle);
@@ -150,7 +62,6 @@ static void defaultConfig(FFinstance* instance)
instance->config.showErrors = false;
instance->config.recache = false;
instance->config.cacheSave = true;
instance->config.allowSlowOperations = false;
instance->config.disableLinewrap = true;
instance->config.hideCursor = true;
@@ -159,17 +70,20 @@ static void defaultConfig(FFinstance* instance)
instance->config.glType = FF_GL_TYPE_AUTO;
instance->config.pipe = false;
instance->config.multithreading = true;
instance->config.stat = false;
initModuleArg(&instance->config.os);
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);
@@ -191,8 +105,9 @@ static void defaultConfig(FFinstance* instance)
initModuleArg(&instance->config.localIP);
initModuleArg(&instance->config.publicIP);
initModuleArg(&instance->config.weather);
initModuleArg(&instance->config.wifi);
initModuleArg(&instance->config.player);
initModuleArg(&instance->config.song);
initModuleArg(&instance->config.media);
initModuleArg(&instance->config.dateTime);
initModuleArg(&instance->config.date);
initModuleArg(&instance->config.time);
@@ -223,15 +138,26 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInitA(&instance->config.libOpenCL, 0);
ffStrbufInitA(&instance->config.libcJSON, 0);
ffStrbufInitA(&instance->config.libfreetype, 0);
ffStrbufInit(&instance->config.libwlanapi);
ffStrbufInit(&instance->config.libnm);
instance->config.cpuTemp = false;
instance->config.gpuTemp = 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.diskRemovable = false;
instance->config.diskShowRemovable = true;
instance->config.diskShowHidden = false;
instance->config.diskShowUnknown = false;
instance->config.diskShowSubvolumes = false;
ffStrbufInitA(&instance->config.batteryDir, 0);
@@ -251,95 +177,66 @@ static void defaultConfig(FFinstance* instance)
ffStrbufInitA(&instance->config.osFile, 0);
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);
}
#if !defined(__ANDROID__) && !defined(_WIN32) && !defined(__MSYS__)
#ifdef FF_HAVE_THREADS
static void* connectDisplayServerThreadMain(void* instance)
{
ffConnectDisplayServer((FFinstance*)instance);
return NULL;
}
FF_THREAD_ENTRY_DECL_WRAPPER(ffConnectDisplayServer, FFinstance*)
#if !defined(__APPLE__)
#if !(defined(__APPLE__) || defined(_WIN32))
static void* detectPlasmaThreadMain(void* instance)
{
ffDetectQt((FFinstance*)instance);
return NULL;
}
#define FF_DETECT_QT_GTK 1
static void* detectGTK2ThreadMain(void* instance)
{
ffDetectGTK2((FFinstance*)instance);
return NULL;
}
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*)
static void* detectGTK3ThreadMain(void* instance)
{
ffDetectGTK3((FFinstance*)instance);
return NULL;
}
#endif //!(defined(__APPLE__) || defined(_WIN32))
static void* detectGTK4ThreadMain(void* instance)
{
ffDetectGTK4((FFinstance*)instance);
return NULL;
}
static void* startThreadsThreadMain(void* instance)
{
pthread_t dsThread;
pthread_create(&dsThread, NULL, connectDisplayServerThreadMain, instance);
pthread_detach(dsThread);
pthread_t gtk2Thread;
pthread_create(&gtk2Thread, NULL, detectGTK2ThreadMain, instance);
pthread_detach(gtk2Thread);
pthread_t gtk3Thread;
pthread_create(&gtk3Thread, NULL, detectGTK3ThreadMain, instance);
pthread_detach(gtk3Thread);
pthread_t gtk4Thread;
pthread_create(&gtk4Thread, NULL, detectGTK4ThreadMain, instance);
pthread_detach(gtk4Thread);
pthread_t plasmaThread;
pthread_create(&plasmaThread, NULL, detectPlasmaThreadMain, instance);
pthread_detach(plasmaThread);
return NULL;
}
#endif //FF_HAVE_THREADS
void startDetectionThreads(FFinstance* instance)
{
pthread_t startThreadsThread;
pthread_create(&startThreadsThread, NULL, startThreadsThreadMain, instance);
pthread_detach(startThreadsThread);
}
#ifdef FF_HAVE_THREADS
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, instance));
#else // !__APPLE__
void startDetectionThreads(FFinstance* instance)
{
pthread_t startThreadsThread;
pthread_create(&startThreadsThread, NULL, connectDisplayServerThreadMain, instance);
pthread_detach(startThreadsThread);
}
#endif // __APPLE__
#ifdef FF_DETECT_QT_GTK
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, instance));
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, instance));
#endif
#else // !__ANDROID__
void startDetectionThreads(FFinstance* instance)
{
#else
FF_UNUSED(instance);
#endif
}
#endif // __ANDROID__
static volatile bool ffDisableLinewrap = true;
static volatile bool ffHideCursor = true;
@@ -351,14 +248,27 @@ 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();
exit(0);
}
#else
static void exitSignalHandler(int signal)
{
FF_UNUSED(signal);
resetConsole();
exit(0);
}
#endif
void ffStart(FFinstance* instance)
{
@@ -368,16 +278,25 @@ void ffStart(FFinstance* instance)
ffDisableLinewrap = instance->config.disableLinewrap && !instance->config.pipe;
ffHideCursor = instance->config.hideCursor && !instance->config.pipe;
struct sigaction action = {};
action.sa_handler = exitSignalHandler;
#ifdef _WIN32
#ifdef FF_ENABLE_BUFFER
setvbuf(stdout, NULL, _IOFBF, 4096);
#endif
SetConsoleCtrlHandler(consoleHandler, TRUE);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode = 0;
GetConsoleMode(hStdout, &mode);
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
SetConsoleOutputCP(CP_UTF8);
#else
#ifndef FF_ENABLE_BUFFER
setvbuf(stdout, NULL, _IONBF, 0);
#endif
struct sigaction action = { .sa_handler = exitSignalHandler };
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
sigaction(SIGQUIT, &action, NULL);
//We do the cache validation here, so we can skip it if --recache is given
if(!instance->config.recache)
ffCacheValidate(instance);
#endif
//reset everything to default before we start printing
if(!instance->config.pipe)
@@ -410,6 +329,7 @@ static void destroyModuleArg(FFModuleArgs* args)
static void destroyConfig(FFinstance* instance)
{
ffStrbufDestroy(&instance->config.logo.source);
ffStrbufDestroy(&instance->config.logo.chafaSymbols);
for(uint8_t i = 0; i < (uint8_t) FASTFETCH_LOGO_MAX_COLORS; ++i)
ffStrbufDestroy(&instance->config.logo.colors[i]);
ffStrbufDestroy(&instance->config.colorKeys);
@@ -425,7 +345,7 @@ static void destroyConfig(FFinstance* instance)
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);
@@ -447,8 +367,9 @@ static void destroyConfig(FFinstance* instance)
destroyModuleArg(&instance->config.localIP);
destroyModuleArg(&instance->config.publicIP);
destroyModuleArg(&instance->config.weather);
destroyModuleArg(&instance->config.wifi);
destroyModuleArg(&instance->config.player);
destroyModuleArg(&instance->config.song);
destroyModuleArg(&instance->config.media);
destroyModuleArg(&instance->config.dateTime);
destroyModuleArg(&instance->config.date);
destroyModuleArg(&instance->config.time);
@@ -479,6 +400,8 @@ static void destroyConfig(FFinstance* instance)
ffStrbufDestroy(&instance->config.libOpenCL);
ffStrbufDestroy(&instance->config.libcJSON);
ffStrbufDestroy(&instance->config.libfreetype);
ffStrbufDestroy(&instance->config.libwlanapi);
ffStrbufDestroy(&instance->config.libnm);
ffStrbufDestroy(&instance->config.diskFolders);
ffStrbufDestroy(&instance->config.batteryDir);
@@ -488,15 +411,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);
ffStrbufDestroy(&instance->state.cacheDir);
ffPlatformDestroy(&instance->state.platform);
}
void ffDestroyInstance(FFinstance* instance)
@@ -576,7 +503,10 @@ void ffListFeatures()
"libcjson\n"
#endif
#ifdef FF_HAVE_FREETYPE
"freetype"
"freetype\n"
#endif
#ifdef FF_HAVE_LIBNM
"libnm\n"
#endif
""
, stdout);
+98 -5
View File
@@ -1,11 +1,15 @@
#include "fastfetch.h"
#include "common/io.h"
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
#ifdef _WIN32
#include <fileapi.h>
#else
#include <termios.h>
#include <poll.h>
#endif
static void createSubfolders(const char* fileName)
{
@@ -16,7 +20,13 @@ static void createSubfolders(const char* fileName)
{
ffStrbufAppendC(&path, *fileName);
if(*fileName == '/')
mkdir(path.chars, S_IRWXU | S_IRGRP | S_IROTH);
{
mkdir(path.chars
#ifndef WIN32
, S_IRWXU | S_IRGRP | S_IROTH
#endif
);
}
++fileName;
}
@@ -30,6 +40,21 @@ bool ffWriteFDBuffer(int fd, const FFstrbuf* content)
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;
@@ -45,6 +70,7 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
bool ret = write(fd, data, dataSize) != -1;
close(fd);
#endif
return ret;
}
@@ -54,11 +80,51 @@ 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;
ffStrbufEnsureFree(buffer, 31); // 32 - 1 for the null terminator
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(
@@ -84,6 +150,17 @@ bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
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;
@@ -93,10 +170,20 @@ ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
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;
@@ -104,6 +191,7 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
bool ret = ffAppendFDBuffer(fd, buffer);
close(fd);
#endif
return ret;
}
@@ -151,6 +239,7 @@ bool ffFileExists(const char* fileName, mode_t mode)
void ffGetTerminalResponse(const char* request, const char* format, ...)
{
#ifndef WIN32
struct termios oldTerm, newTerm;
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
@@ -189,4 +278,8 @@ void ffGetTerminalResponse(const char* request, const char* format, ...)
va_start(args, format);
vsscanf(buffer, format, args);
va_end(args);
#else
//Unimplemented
FF_UNUSED(request, format);
#endif
}
+5 -1
View File
@@ -5,7 +5,7 @@
#include "fastfetch.h"
#include <sys/types.h> //mode_t
#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);
@@ -16,6 +16,10 @@ 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!
+7 -5
View File
@@ -10,17 +10,19 @@
#endif
#endif
#ifdef __SANITIZE_ADDRESS__
#define FF_DLOPEN_FLAGS RTLD_LAZY | RTLD_NODELETE
#else
#define FF_DLOPEN_FLAGS RTLD_LAZY
#ifndef FF_DLOPEN_FLAGS
#ifdef __SANITIZE_ADDRESS__
#define FF_DLOPEN_FLAGS RTLD_LAZY | RTLD_NODELETE
#else
#define FF_DLOPEN_FLAGS RTLD_LAZY
#endif
#endif
static void* libraryLoad(const char* path, int maxVersion)
{
void* result = dlopen(path, FF_DLOPEN_FLAGS);
#if defined(_WIN32) || defined(__MSYS__)
#ifdef _WIN32
// libX.dll.1 never exists on Windows, while libX-1.dll may exist
FF_UNUSED(maxVersion)
+16 -2
View File
@@ -3,9 +3,20 @@
#ifndef FF_INCLUDED_common_library
#define FF_INCLUDED_common_library
#include <dlfcn.h>
#include "fastfetch.h"
#include "util/FFcheckmacros.h"
#if defined(_WIN32) || defined(__MSYS__)
#if defined(_WIN32) //We don't force MSYS using LoadLibrary because dlopen also searches $LD_LIBRARY_PATH
#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); }
FF_C_NODISCARD static inline void* dlsym(void* handle, const char* symbol) { return GetProcAddress((HMODULE)handle, symbol); }
static inline int dlclose(void* handle) { return !FreeLibrary((HMODULE)handle); }
#else
#include <dlfcn.h>
#endif
#ifdef _WIN32
#define FF_LIBRARY_EXTENSION ".dll"
#elif defined(__APPLE__)
#define FF_LIBRARY_EXTENSION ".dylib"
@@ -32,6 +43,9 @@
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
#define FF_LIBRARY_LOAD_SYMBOL_LAZY(library, symbolName) \
__typeof__(&symbolName) ff ## symbolName = dlsym(library, #symbolName);
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
-85
View File
@@ -1,85 +0,0 @@
#include "fastfetch.h"
#include "common/networking.h"
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout)
{
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo* addr;
if(getaddrinfo(host, "80", &hints, &addr) != 0)
return -1;
int sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(sockfd == -1)
{
freeaddrinfo(addr);
return -1;
}
if(timeout > 0)
{
struct timeval timev;
timev.tv_sec = 0;
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
}
if(connect(sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
{
close(sockfd);
freeaddrinfo(addr);
return -1;
}
freeaddrinfo(addr);
FFstrbuf command;
ffStrbufInitA(&command, 64);
ffStrbufAppendS(&command, "GET ");
ffStrbufAppendS(&command, path);
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&command, host);
ffStrbufAppendS(&command, "\r\n");
ffStrbufAppendS(&command, headers);
ffStrbufAppendS(&command, "\r\n");
if(send(sockfd, command.chars, command.length, 0) == -1)
{
ffStrbufDestroy(&command);
close(sockfd);
return -1;
}
ffStrbufDestroy(&command);
return sockfd;
}
bool ffNetworkingRecvHttpResponse(int sockfd, FFstrbuf* buffer)
{
ssize_t received = recv(sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
if(received > 0)
{
buffer->length += (uint32_t) received;
buffer->chars[buffer->length] = '\0';
}
close(sockfd);
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
}
bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer)
{
int sockfd = ffNetworkingSendHttpRequest(host, path, headers, timeout);
if(sockfd > 0)
return ffNetworkingRecvHttpResponse(sockfd, buffer);
return false;
}
+30 -3
View File
@@ -3,10 +3,37 @@
#ifndef FF_INCLUDED_common_networking
#define FF_INCLUDED_common_networking
#include "common/thread.h"
#include "util/FFstrbuf.h"
int ffNetworkingSendHttpRequest(const char* host, const char* path, const char* headers, uint32_t timeout);
bool ffNetworkingRecvHttpResponse(int sock, FFstrbuf* buffer);
bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer);
#ifdef _WIN32
#include <minwindef.h>
#endif
typedef struct FFNetworkingState {
#ifdef _WIN32
uintptr_t sockfd;
OVERLAPPED overlapped;
#else
int sockfd;
FFstrbuf host;
FFstrbuf command;
#ifdef FF_HAVE_THREADS
FFThreadType thread;
#endif
#endif
} FFNetworkingState;
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout);
static inline bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer)
{
FFNetworkingState state;
if(ffNetworkingSendHttpRequest(&state, host, path, headers))
return ffNetworkingRecvHttpResponse(&state, buffer, timeout);
return false;
}
#endif
+103
View File
@@ -0,0 +1,103 @@
#include "fastfetch.h"
#include "common/networking.h"
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
static void connectAndSend(FFNetworkingState* state)
{
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo* addr;
if(getaddrinfo(state->host.chars, "80", &hints, &addr) != 0)
goto error;
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(state->sockfd == -1)
{
freeaddrinfo(addr);
goto error;
}
if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
{
close(state->sockfd);
freeaddrinfo(addr);
goto error;
}
freeaddrinfo(addr);
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
{
close(state->sockfd);
goto error;
}
goto exit;
error:
state->sockfd = -1;
exit:
ffStrbufDestroy(&state->host);
ffStrbufDestroy(&state->command);
}
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
{
ffStrbufInitS(&state->host, host);
ffStrbufInitA(&state->command, 64);
ffStrbufAppendS(&state->command, "GET ");
ffStrbufAppendS(&state->command, path);
ffStrbufAppendS(&state->command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&state->command, host);
ffStrbufAppendS(&state->command, "\r\n");
ffStrbufAppendS(&state->command, headers);
ffStrbufAppendS(&state->command, "\r\n");
#ifdef FF_HAVE_THREADS
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
return !!state->thread;
#else
connectAndSend(state);
return state->sockfd != -1;
#endif
}
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
{
#ifdef FF_HAVE_THREADS
ffThreadJoin(state->thread);
#endif
if(state->sockfd == -1)
return false;
if(timeout > 0)
{
struct timeval timev;
timev.tv_sec = 0;
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
}
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
if(received > 0)
{
buffer->length += (uint32_t) received;
buffer->chars[buffer->length] = '\0';
}
close(state->sockfd);
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
}
+125
View File
@@ -0,0 +1,125 @@
#include <mswsock.h>
#include <ws2tcpip.h>
//Must be included after <mswsock.h>
#include "fastfetch.h"
#include "common/networking.h"
static LPFN_CONNECTEX ConnectEx;
static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context)
{
(void)once;
(void)param;
static WSADATA wsaData;
*context = &wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return FALSE;
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
return FALSE;
//Dummy socket needed for WSAIoctl
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == INVALID_SOCKET)
return FALSE;
DWORD dwBytes;
GUID guid = WSAID_CONNECTEX;
if(WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guid, sizeof(guid),
&ConnectEx, sizeof(ConnectEx),
&dwBytes, NULL, NULL) != 0)
return FALSE;
return closesocket(sockfd) == 0;
}
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
{
static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
WSADATA* pData;
if(!InitOnceExecuteOnce(&once, initWsaData, NULL, (LPVOID*) &pData))
return false;
memset(state, 0, sizeof(*state));
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo* addr;
if(getaddrinfo(host, "80", &hints, &addr) != 0)
return false;
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if(state->sockfd == INVALID_SOCKET)
{
freeaddrinfo(addr);
return false;
}
{
//ConnectEx requires the socket to be initially bound
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = INADDR_ANY,
.sin_port = 0,
};
if(bind(state->sockfd, (SOCKADDR *)&addr, sizeof(addr)) != 0)
{
printf("bind %d\n", WSAGetLastError());
return false;
}
}
FF_STRBUF_AUTO_DESTROY command;
ffStrbufInitA(&command, 64);
ffStrbufAppendS(&command, "GET ");
ffStrbufAppendS(&command, path);
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&command, host);
ffStrbufAppendS(&command, "\r\n");
ffStrbufAppendS(&command, headers);
ffStrbufAppendS(&command, "\r\n");
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen, command.chars, command.length, NULL, &state->overlapped);
freeaddrinfo(addr);
if(!result && WSAGetLastError() != WSA_IO_PENDING)
{
closesocket(state->sockfd);
return false;
}
return true;
}
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
{
DWORD transfer, flags;
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
{
closesocket(state->sockfd);
return false;
}
if(timeout > 0)
{
//https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
}
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int)ffStrbufGetFree(buffer), 0);
if(received > 0)
{
buffer->length += (uint32_t) received;
buffer->chars[buffer->length] = '\0';
}
closesocket(state->sockfd);
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
}
-11
View File
@@ -3,17 +3,6 @@
#include <ctype.h>
#include <inttypes.h>
bool ffStrSet(const char* str)
{
if(str == NULL)
return false;
while(isspace(*str))
str++;
return *str != '\0';
}
void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch)
{
if(major->length > 0)
-1
View File
@@ -14,7 +14,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);
+14 -3
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "util/textModifier.h"
void ffPrintLogoAndKey(FFinstance* instance, const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat)
{
@@ -93,7 +94,9 @@ static void printError(FFinstance* instance, const char* moduleName, uint8_t mod
vprintf(message, arguments);
if(!instance->config.pipe)
puts(FASTFETCH_TEXT_MODIFIER_RESET);
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
putchar('\n');
}
}
@@ -127,8 +130,16 @@ void ffPrintColor(const FFstrbuf* colorValue)
void ffPrintCharTimes(char c, uint32_t times)
{
for(uint32_t i = 0; i < times; i++)
putchar(c);
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 += (uint32_t)sizeof(str))
fwrite(str, 1, sizeof(str), stdout);
uint32_t remaining = times % sizeof(str);
if(remaining > 0)
fwrite(str, 1, remaining, stdout);
}
void ffPrintUserString(const char* value)
+2 -2
View File
@@ -31,8 +31,8 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
//Parent
close(pipes[1]);
waitpid(childPid, NULL, 0);
ffAppendFDBuffer(pipes[0], buffer);
bool ok = ffAppendFDBuffer(pipes[0], buffer);
close(pipes[0]);
return NULL;
return ok ? NULL : "ffAppendFDBuffer() failed";
}
+24 -25
View File
@@ -4,7 +4,6 @@
#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 = {
@@ -27,26 +26,30 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
.hStdOutput = hChildStdoutWrite,
};
FFstrbuf cmdline;
ffStrbufInit(&cmdline);
for(char* const* parg = argv; *parg; ++parg)
{
if(cmdline.length > 0)
ffStrbufAppendC(&cmdline, ' ');
ffStrbufAppendF(&cmdline, "\"%s\"", * parg);
}
BOOL success;
BOOL success = CreateProcessA(
NULL, // application name
cmdline.chars, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
{
FF_STRBUF_AUTO_DESTROY cmdline;
ffStrbufInitF(&cmdline, "\"%s\"", argv[0]);
for(char* const* parg = &argv[1]; *parg; ++parg)
{
ffStrbufAppendC(&cmdline, ' ');
ffStrbufAppendS(&cmdline, *parg);
}
success = CreateProcessA(
NULL, // application name
cmdline.chars, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo // receives PROCESS_INFORMATION
);
}
CloseHandle(hChildStdoutWrite);
if(!success)
@@ -55,14 +58,10 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
return "CreateProcessA() failed";
}
char str[128];
char str[1024];
DWORD nRead;
while(ReadFile(hChildStdoutRead, str, sizeof(str), &nRead, NULL) && nRead > 0)
{
ffStrbufAppendNS(buffer, nRead, str);
if(nRead < sizeof(str))
break;
}
CloseHandle(hChildStdoutRead);
return NULL;
+8 -20
View File
@@ -2,6 +2,9 @@
#include "common/properties.h"
#include <stdlib.h>
#ifdef _WIN32
#include "util/windows/getline.h"
#endif
static bool parsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer)
{
@@ -141,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);
@@ -161,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++)
for(uint32_t i = 0; i < list->length; i++)
{
//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, ffListGet(list, i));
ffStrbufAppendS(&baseDir, relativeFile);
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
@@ -200,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}});
}
+37 -5
View File
@@ -3,7 +3,7 @@
#ifndef FF_INCLUDED_common_properties
#define FF_INCLUDED_common_properties
#include "util/FFstrbuf.h"
#include "fastfetch.h"
typedef struct FFpropquery
{
@@ -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
+12 -13
View File
@@ -1,9 +1,9 @@
#include "fastfetch.h"
#include "common/settings.h"
#include "common/library.h"
#include "common/thread.h"
#include "common/io.h"
#include <pthread.h>
#include <string.h>
typedef enum FFInitState
@@ -15,18 +15,18 @@ typedef enum FFInitState
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
static dataObject data; \
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; \
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
pthread_mutex_lock(&mutex); \
ffThreadMutexLock(&mutex); \
if(initState != FF_INITSTATE_UNINITIALIZED) {\
pthread_mutex_unlock(&mutex); \
ffThreadMutexUnlock(&mutex); \
return initState == FF_INITSTATE_SUCCESSFUL ? &data : NULL; \
} \
initState = FF_INITSTATE_SUCCESSFUL; \
void* libraryHandle = ffLibraryLoad(&userLibraryName, __VA_ARGS__, NULL); \
if(libraryHandle == NULL) { \
initState = FF_INITSTATE_FAILED; \
pthread_mutex_unlock(&mutex); \
ffThreadMutexUnlock(&mutex); \
return NULL; \
} \
@@ -35,20 +35,20 @@ typedef enum FFInitState
if(data.ff ## symbolName == NULL) { \
dlclose(libraryHandle); \
initState = FF_INITSTATE_FAILED; \
pthread_mutex_unlock(&mutex); \
ffThreadMutexUnlock(&mutex); \
return NULL; \
}
#define FF_LIBRARY_DATA_LOAD_RETURN \
initState = FF_INITSTATE_SUCCESSFUL; \
pthread_mutex_unlock(&mutex); \
ffThreadMutexUnlock(&mutex); \
return &data;
#define FF_LIBRARY_DATA_LOAD_ERROR \
{ \
dlclose(libraryHandle); \
initState = FF_INITSTATE_FAILED; \
pthread_mutex_unlock(&mutex); \
ffThreadMutexUnlock(&mutex); \
return NULL; \
}
@@ -91,7 +91,7 @@ typedef struct GSettingsData
static const GSettingsData* getGSettingsData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance->config.libGIO, "libgio-2.0.so", 1);
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance->config.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_lookup)
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_has_key)
@@ -163,7 +163,7 @@ typedef struct DConfData
static const DConfData* getDConfData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance->config.libDConf, "libdconf.so", 2);
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance->config.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_read_full)
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
@@ -233,7 +233,7 @@ typedef struct XFConfData
static const XFConfData* getXFConfData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance->config.libXFConf, "libxfconf-0.so", 4);
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance->config.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get)
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_has_property)
@@ -280,7 +280,6 @@ FFvariant ffSettingsGetXFConf(const FFinstance* instance, const char* channelNam
#ifdef FF_HAVE_SQLITE3
#include <sqlite3.h>
#include <sys/stat.h>
typedef struct SQLiteData
{
@@ -295,7 +294,7 @@ typedef struct SQLiteData
static const SQLiteData* getSQLiteData(const FFinstance* instance)
{
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance->config.libSQLite3, "libsqlite3.so", 1);
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance->config.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
+4 -2
View File
@@ -2,11 +2,11 @@
#include <stdlib.h>
void ffSysctlGetString(const char* propName, FFstrbuf* result)
const char* ffSysctlGetString(const char* propName, FFstrbuf* result)
{
size_t neededLength;
if(sysctlbyname(propName, NULL, &neededLength, NULL, 0) != 0 || neededLength == 1) //neededLength is 1 for empty strings, because of the null terminator
return;
return "sysctlbyname() failed";
ffStrbufEnsureFree(result, (uint32_t) neededLength - 1);
@@ -14,6 +14,8 @@ void ffSysctlGetString(const char* propName, FFstrbuf* result)
result->length += (uint32_t) neededLength - 1;
result->chars[result->length] = '\0';
return NULL;
}
int ffSysctlGetInt(const char* propName, int defaultValue)
+6 -4
View File
@@ -4,12 +4,14 @@
#define FF_INCLUDED_common_sysctl
#include "fastfetch.h"
#include "util/FFcheckmacros.h"
#include <sys/types.h>
#include <sys/sysctl.h>
void ffSysctlGetString(const char* propName, FFstrbuf* result);
int ffSysctlGetInt(const char* propName, int defaultValue);
int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue);
void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength);
const char* ffSysctlGetString(const char* propName, FFstrbuf* result);
FF_C_NODISCARD int ffSysctlGetInt(const char* propName, int defaultValue);
FF_C_NODISCARD int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue);
FF_C_NODISCARD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength);
#endif
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#ifndef FF_INCLUDED_common_thread
#define FF_INCLUDED_common_thread
#include "fastfetch.h"
#ifdef FF_HAVE_THREADS
#if defined(_WIN32)
#include <handleapi.h>
#include <synchapi.h>
#include <process.h>
#define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT
typedef SRWLOCK FFThreadMutex;
typedef HANDLE FFThreadType;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { AcquireSRWLockExclusive(mutex); }
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { ReleaseSRWLockExclusive(mutex); }
static inline FFThreadType ffThreadCreate(unsigned (__stdcall* func)(void*), void* data) {
return (FFThreadType)_beginthreadex(NULL, 0, func, data, 0, NULL);
}
#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); }
#else
#include <pthread.h>
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t FFThreadMutex;
typedef pthread_t FFThreadType;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); }
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); }
static inline FFThreadType ffThreadCreate(void* (* func)(void*), void* data) {
FFThreadType newThread = 0;
pthread_create(&newThread, NULL, func, data);
return newThread;
}
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static void* fn ## ThreadMain (void* data) { fn((paramType)data); return NULL; }
static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); }
static inline void ffThreadJoin(FFThreadType thread) { pthread_join(thread, NULL); }
#endif
#else //FF_HAVE_THREADS
#define FF_THREAD_MUTEX_INITIALIZER 0
typedef char FFThreadMutex;
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { FF_UNUSED(mutex) }
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { FF_UNUSED(mutex) }
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType)
#endif //FF_HAVE_THREADS
#endif
+12 -9
View File
@@ -4,28 +4,31 @@
#define FF_INCLUDED_common_time
#include <stdint.h>
#if defined(_WIN32) || defined(__MSYS__)
#ifdef _WIN32
#include <synchapi.h>
#include <sysinfoapi.h>
#include <profileapi.h>
#else
#include <sys/time.h>
#include <time.h>
#endif
static inline uint64_t ffTimeGetTick() //In msec
{
#if defined(_WIN32) || defined(__MSYS__)
return GetTickCount64();
#ifdef _WIN32
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
LARGE_INTEGER start;
QueryPerformanceCounter(&start);
return (uint64_t)(start.QuadPart * 1000 / frequency.QuadPart);
#else
struct timeval timeNow;
gettimeofday(&timeNow, NULL);
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000));
struct timespec timeNow;
clock_gettime(CLOCK_MONOTONIC, &timeNow);
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000));
#endif
}
static inline void ffTimeSleep(uint32_t msec)
{
#if defined(_WIN32) || defined(__MSYS__)
#ifdef _WIN32
SleepEx(msec, TRUE);
#else
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
+71 -11
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
@@ -33,6 +33,13 @@
# Default is true.
#--multithreading true
# Print stat option:
# Sets if fastfetch should print time usage (in ms) for individual modules
# If true, it will also enable --show-errors
# Must be true or false.
# Default is false.
#--stat true
# Slow operations option:
# Sets if fastfetch is allowed to use known slow operations to detect more / better values.
# Must be true or false.
@@ -61,7 +68,7 @@
# Logo type option:
# Sets the logo type to use.
# Must be auto, builtin, file, raw, sixel, kitty or chafa.
# Must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty or chafa.
# Default is auto.
#--logo-type auto
@@ -107,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.
@@ -178,7 +191,6 @@
# OS file option
# Sets the path to the file containing the operating system information.
# Should be a valid path to an existing file.
# Note that you might need to run fastfetch with --recache once for it to take affect.
# Default is /etc/os-release.
#--os-file /etc/os-release
@@ -200,17 +212,60 @@
# 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
# 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
# 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; 6: prints bar and hide other texts
#--percent-type 1
# Key options:
# Sets the displayed key of a module
# Can be any string. Some of theme take an argument like a format string. See "fastfetch --help format" for help.
#--os-key OS
#--host-key Host
#--chassis-key Chassis
#--kernel-key Kernel
#--uptime-key Uptime
#--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
@@ -231,9 +286,10 @@
#--locale-key Locale
#--local-ip-key Local IP ({1})
#--public-ip-key Public IP
#--wifi-key Wifi
#--weather-key Weather
#--player-key Media Player
#--song-key Song
#--media-key Media
#--datetime-key Date Time
#--vulkan-key Vulkan
#--opengl-key OpenGL
@@ -247,12 +303,14 @@
# An empty format string (As they are currently below) will behave as if it was not set.
#--os-format
#--host-format
#--chassis-format
#--kernel-format
#--uptime-format
#--processes-format
#--packages-format
#--shell-format
#--resolution-format
#--display-format
#--brightness-format
#--de-format
#--wm-format
#--wm-theme-format
@@ -275,7 +333,7 @@
#--public-ip-format
#--weather-format
#--player-format
#--song-format
#--media-format
#--datetime-format
#--vulkan-format
#--opengl-format
@@ -289,12 +347,14 @@
# If one of them is set, the module will appear, even if --show-errors is not given.
#--os-error
#--host-error
#--chassis-error
#--kernel-error
#--uptime-error
#--processes-error
#--packages-error
#--shell-error
#--resolution-error
#--display-error
#--brightness-error
#--de-error
#--wm-error
#--wm-theme-error
@@ -317,7 +377,7 @@
#--public-ip-error
#--weather-error
#--player-error
#--song-error
#--media-error
#--datetime-error
#--vulkan-error
#--opengl-error
@@ -328,7 +388,7 @@
# Sets an user specific path to a library to load.
# Must be a valid path to a library.
#--lib-PCI /usr/lib/libpci.so
#--lib-vulkan /usr/lib/libvulkan.so
#--lib-vulkan /usr/lib/libvulkan.so (libMoltenVK.dylib on macOS)
#--lib-wayland /usr/lib/libwayland-client.so
#--lib-xcb-randr /usr/lib/libxcb-randr.so
#--lib-xcb /usr/lib/libxcb.so
+89 -65
View File
@@ -1,65 +1,78 @@
Usage: fastfetch <options>
Informative options:
-h,--help: shows this message and exits
-h,--help <command>: shows help for a specific command and exits
-v,--version: prints the version of fastfetch and exits
--list-logos: list available logos and exits
--list-modules: lists available modules and exits
--list-presets: list presets fastfetch knows about and exits. They can be loaded with --load-config. (+)
--list-features: list the supported features fastfetch was compiled with and exits. Mainly for development.
--print-logos: show available logos and exits
--print-config-system: prints the default system config and exits
--print-config-user: prints the default user config and exits
--print-structure: prints the default stucture and exits
-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 (+)
--list-features: List the supported features fastfetch was compiled with (mainly for development)
--print-logos: Print available logos
--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:
-r,--recache <?value>: generate new cached values
--nocache <?value>: don't use cached values, but also don't overwrite existing ones
--load-config <file>: load a config file or a preset (+)
--multithreading <?value>: use multiple threads to detect values
--allow-slow-operations <?value>: allow operations that are usually very slow for more detailed output
--escape-bedrock <?value>: on bedrock linux, sets if it should escape the bedrock jail or not
--pipe <?value>: disable logo and all escape sequences
--load-config <file>: Load a config file or preset (+)
--multithreading <?value>: Use multiple threads to detect values
--stat <?value>: Show time usage (in ms) for individual modules
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
--escape-bedrock <?value>: On Bedrock Linux, whether to escape the bedrock jail
--pipe <?value>: Disable logo and all escape sequences
Logo options:
-l,--logo <logo>: set the logo to use. The type is specified by --logo-type. If default: the name of a builtin logo or a path to a file
--logo-type <type>: set the type of the logo given. Must be auto, builtin, file, raw, sixel, kitty or chafa.
--logo-width <width>: set the width of the logo (in characters), if it is an image
--logo-height <height>: set the height of the logo (in characters), if it is an image
--logo-color-[1-9] <color>: overwrite a color in the logo
--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-print-remaining <?value>: weather to print the remaining logo, if it has more lines than modules to display
--sixel <file>: short for --logo-type sixel --logo <file>
--kitty <file>: short for --logo-type kitty --logo <file>
--chafa <file>: short for --logo-type chafa --logo <file>
--file <file>: short for --logo-type file --logo <file>
--raw <file>: short for --logo-type raw --logo <file>
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa
--logo-width <width>: Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-height <height>: Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol
--logo-preserve-aspect-radio <?value>: Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol
--logo-color-[1-9] <color>: Overwrite a color in the logo
--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>
--data <data>: Short for --logo-type data --logo <data>
--data-raw <data>: Short for --logo-type data-raw --logo <data>
--sixel <file>: Short for --logo-type sixel --logo <file>
--kitty <file>: Short for --logo-type kitty --logo <file>
--iterm <file>: Short for --logo-type iterm --logo <file>
--chafa <file>: Short for --logo-type chafa --logo <file>
--chafa-fg-only <?value>: Produce character-cell output using foreground colors only. See chafa document for detail
--chafa-symbols <str>: Specify character symbols to employ in final output. See chafa document for detail
--chafa-canvas-mode <value>: Determine how colors are used in the output. This value maps the int value of enum ChafaCanvasMode. See chafa document for detail
--chafa-color-space <value>: Set color space used for quantization. 0 for RGB; 1 for DIN99d. See chafa document for detail
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
Display options:
-s,--structure <structure>: sets the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
--color-keys <color>: sers the color of the keys
--color-title <color>: sets the color of the title
-c,--color <color>: sets the color of both the keys and the title
--separator <str>: sets the separator between key and value. Default is a colon with a space
--set <key=value>: hard set the value of a key
--set-keyless <key=value>: hard set the value of a key, but don't print the key or the separator
--show-errors <?value>: print occuring errors
--disable-linewrap <?value>: weather to disable linewrap during the run
--hide-cursor <?value>: weather to hide the cursor during the run
--binary-prefix <value>: sets the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
--color-keys <color>: Set the color of the keys
--color-title <color>: Set the color of the title
-c,--color <color>: Set the color of both the keys and title
--separator <str>: Set the separator between key and value. Default is a colon with a space
--set <key=value>: Hard set the value of a key
--set-keyless <key=value>: Hard set the value of a key, but don't print the key or the separator
--show-errors <?value>: Print occurring errors
--disable-linewrap <?value>: Whether to disable line wrap during the run
--hide-cursor <?value>: Whether to hide the cursor during the run
--binary-prefix <value>: Set the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC.
General module options:
--<module>-format <format>: Sets the format string to use for each specific module.
--<module>-format <format>: Set the format string to use for each specific module.
To see how a format string works, use fastfetch --help format.
To see help about a specific format string, use fastfetch --help <module>-format.
--<module>-key <key>: Sets the key to use for each specific module.
--<module>-key <key>: Set the key to use for each specific module.
For modules which print multiple lines, the string is parsed as a format string with the index as first character.
--<module>-error <format>: Sets the error format string to use for each specific module.
--<module>-error <format>: Set the error format string to use for each specific module.
The error is given as the first and only argument.
Setting this for a module will cause it to appear, even if --show-errors is not given.
@@ -87,25 +100,36 @@ Library options: Set the path of a library to load
--lib-cjson <path>
Module specific options:
--title-fqdn <?value>: Sets 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 informations
--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-removable <?value>: Sets if removable volume 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>: Sets the opengl context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
--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-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
--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-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-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, 6 for bar only. 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".
+8 -4
View File
@@ -1,5 +1,8 @@
Battery
Bios
Board
Break
Chassis
Colors
CPU
CPUUsage
@@ -8,6 +11,7 @@ Date
Datetime
DE
Disk
Display
Font
GPU
Host
@@ -17,15 +21,13 @@ Locale
LocalIP
Media
Memory
OS
OpenCL
OpenGL
OS
Packages
Player
PowerAdapter
Processes
PublicIP
PowerAdapter
Resolution
Separator
Shell
Swap
@@ -36,5 +38,7 @@ Time
Title
Uptime
Vulkan
Weather
Wifi
WM
WMTheme
+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
+1 -1
View File
@@ -12,7 +12,7 @@ typedef struct BatteryResult
FFstrbuf manufacturer;
FFstrbuf modelName;
FFstrbuf technology;
FFstrbuf capacity;
double capacity;
FFstrbuf status;
double temperature;
} BatteryResult;
+38
View File
@@ -0,0 +1,38 @@
#include "fastfetch.h"
#include "battery.h"
#include "common/processing.h"
#include "common/properties.h"
const char* ffDetectBatteryImpl(FF_MAYBE_UNUSED FFinstance* instance, FFlist* results)
{
FF_STRBUF_AUTO_DESTROY buffer;
ffStrbufInit(&buffer);
if(ffProcessAppendStdOut(&buffer, (char* const[]){
FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api",
"BatteryStatus"
}))
return "Starting `" FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api" " BatteryStatus` failed";
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(ffParsePropLines(buffer.chars, "\"status\": ", &battery->status))
{
ffStrbufTrimRight(&battery->status, ',');
ffStrbufTrim(&battery->status, '"');
}
return NULL;
}
+3 -4
View File
@@ -7,7 +7,7 @@
static double detectBatteryTemp()
{
FFlist temps;
FF_LIST_AUTO_DESTROY temps;
ffListInit(&temps, sizeof(FFTempValue));
ffDetectCoreTemps(FF_TEMP_BATTERY, &temps);
@@ -25,7 +25,6 @@ static double detectBatteryTemp()
ffStrbufDestroy(&tempValue->deviceClass);
}
result /= temps.length;
ffListDestroy(&temps);
return result;
}
@@ -55,7 +54,7 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
const char* error;
BatteryResult* battery = ffListAdd(results);
ffStrbufInit(&battery->capacity);
battery->capacity = 0.0/0.0;
int currentCapacity, maxCapacity;
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
@@ -68,7 +67,7 @@ const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
if(currentCapacity <= 0)
return "Querying CurrentCapacity failed";
ffStrbufAppendF(&battery->capacity, "%.0f", currentCapacity * 100.0 / maxCapacity);
battery->capacity = currentCapacity * 100.0 / maxCapacity;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
+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;
}
+9 -6
View File
@@ -33,18 +33,18 @@ static void parseBattery(FFstrbuf* dir, FFlist* results)
return;
}
ffStrbufDestroy(&testBatteryBuffer);
BatteryResult* result = ffListAdd(results);
//capacity must exist and be not empty
ffStrbufInit(&result->capacity);
ffStrbufAppendS(dir, "/capacity");
ffReadFileBuffer(dir->chars, &result->capacity);
bool available = ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(result->capacity.length == 0)
if(available)
result->capacity = ffStrbufToDouble(&testBatteryBuffer);
ffStrbufDestroy(&testBatteryBuffer);
if(!available)
{
ffStrbufDestroy(&result->capacity);
result->capacity = 0.0/0.0;
--results->length;
return;
}
@@ -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);
+158
View File
@@ -0,0 +1,158 @@
#include "battery.h"
#include "util/windows/unicode.h"
#include "util/mallocHelper.h"
#include <setupapi.h>
#include <batclass.h>
#include <devguid.h>
#include <winternl.h>
#include <powrprof.h>
static inline void wrapCloseHandle(HANDLE* handle)
{
if(*handle)
CloseHandle(*handle);
}
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
{
if(*hdev)
SetupDiDestroyDeviceInfoList(*hdev);
}
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
{
if(instance->config.allowSlowOperations)
{
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(hdev == INVALID_HANDLE_VALUE)
return "SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY) failed";
for(DWORD idev = 0;; idev++)
{
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
if(!SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did))
break;
DWORD cbRequired = 0;
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
if(!pdidd)
break; //Out of memory
pdidd->cbSize = sizeof(*pdidd);
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
continue;
HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery =
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hBattery == INVALID_HANDLE_VALUE)
continue;
BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
DWORD dwWait = 0;
DWORD dwOut;
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag)
continue;
BATTERY_INFORMATION bi = {0};
if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL))
continue;
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
continue;
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
ffStrbufInitS(&battery->technology, "Lead Acid");
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
ffStrbufInitS(&battery->technology, "Lithium Ion");
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Zinc");
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
else
ffStrbufInitS(&battery->technology, "Unknown");
{
ffStrbufInit(&battery->modelName);
bqi.InformationLevel = BatteryDeviceName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->modelName, name);
}
{
ffStrbufInit(&battery->manufacturer);
bqi.InformationLevel = BatteryManufactureName;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->manufacturer, name);
}
battery->temperature = 0.0/0.0;
if(instance->config.batteryTemp)
{
bqi.InformationLevel = BatteryTemperature;
ULONG temp;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
battery->temperature = temp;
}
{
BATTERY_STATUS bs;
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
else
battery->capacity = 0;
ffStrbufInit(&battery->status);
if(bs.PowerState & BATTERY_POWER_ON_LINE)
ffStrbufAppendS(&battery->status, "AC Connected, ");
if(bs.PowerState & BATTERY_DISCHARGING)
ffStrbufAppendS(&battery->status, "Discharging, ");
if(bs.PowerState & BATTERY_CHARGING)
ffStrbufAppendS(&battery->status, "Charging");
if(bs.PowerState & BATTERY_CRITICAL)
ffStrbufAppendS(&battery->status, "Critical, ");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
}
}
else
{
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(CallNtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
{
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
battery->temperature = 0.0/0.0;
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
if(info.AcOnLine)
{
ffStrbufAppendS(&battery->status, "AC Connected");
if(info.Charging)
ffStrbufAppendS(&battery->status, ", Charging");
}
else if(info.Discharging)
ffStrbufAppendS(&battery->status, "Discharging");
}
}
return NULL;
}
-70
View File
@@ -1,70 +0,0 @@
extern "C" {
#include "battery.h"
}
#include "util/windows/wmi.hpp"
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
{
FF_UNUSED(instance);
//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-battery
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT SystemName, Name, Chemistry, EstimatedChargeRemaining, BatteryStatus FROM Win32_Battery", nullptr);
if(!pEnumerator)
return "Query WMI service failed";
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0)
{
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->manufacturer);
ffGetWmiObjString(pclsObj, L"SystemName", &battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffGetWmiObjString(pclsObj, L"Name", &battery->modelName);
uint64_t chemistry;
ffGetWmiObjUnsigned(pclsObj, L"Chemistry", &chemistry);
switch(chemistry)
{
case 1: ffStrbufInitS(&battery->technology, "Other"); break;
case 2: ffStrbufInitS(&battery->technology, "Unknown"); break;
case 3: ffStrbufInitS(&battery->technology, "Lead Acid"); break;
case 4: ffStrbufInitS(&battery->technology, "Nickel Cadmium"); break;
case 5: ffStrbufInitS(&battery->technology, "Nickel Metal Hydride"); break;
case 6: ffStrbufInitS(&battery->technology, "Lithium-ion"); break;
case 7: ffStrbufInitS(&battery->technology, "Zinc air"); break;
case 8: ffStrbufInitS(&battery->technology, "Lithium Polymer"); break;
}
uint64_t capacity;
ffGetWmiObjUnsigned(pclsObj, L"EstimatedChargeRemaining", &capacity);
ffStrbufInitF(&battery->capacity, "%d", (int)capacity);
uint64_t batteryStatus;
ffGetWmiObjUnsigned(pclsObj, L"BatteryStatus", &batteryStatus);
switch(batteryStatus)
{
case 1: ffStrbufInitS(&battery->status, "Discharging"); break;
case 2: ffStrbufInitS(&battery->status, "AC Connected"); break;
case 3: ffStrbufInitS(&battery->status, "Fully Charged"); break;
case 4: ffStrbufInitS(&battery->status, "Low"); break;
case 5: ffStrbufInitS(&battery->status, "Critical"); break;
case 6: ffStrbufInitS(&battery->status, "Charging"); break;
case 7: ffStrbufInitS(&battery->status, "Charging and High"); break;
case 8: ffStrbufInitS(&battery->status, "Charging and Low"); break;
case 9: ffStrbufInitS(&battery->status, "Charging and Critical"); break;
case 10: ffStrbufInitS(&battery->status, "Undefined"); break;
case 11: ffStrbufInitS(&battery->status, "Partially Charged"); break;
}
battery->temperature = FF_BATTERY_TEMP_UNSET;
}
pclsObj->Release();
pEnumerator->Release();
return nullptr;
}
+70
View File
@@ -0,0 +1,70 @@
#include "bios.h"
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
io_registry_entry_t registryEntry;
#ifndef __aarch64__
//https://github.com/osquery/osquery/blob/master/osquery/tables/system/darwin/smbios_tables.cpp
//For Intel
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/rom")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
ffStrbufAppendS(&bios->error, "IORegistryEntryCreateCFProperties(registryEntry) failed");
return;
}
ffCfDictGetString(properties, CFSTR("vendor"), &bios->biosVendor);
ffCfDictGetString(properties, CFSTR("version"), &bios->biosVersion);
ffCfDictGetString(properties, CFSTR("release-date"), &bios->biosDate);
if(!ffStrbufContainC(&bios->biosDate, '-'))
ffStrbufAppendS(&bios->biosRelease, "Efi-");
ffStrbufAppend(&bios->biosRelease, &bios->biosVersion);
CFRelease(properties);
IOObjectRelease(registryEntry);
return;
}
#else
//For arm64
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
{
ffCfDictGetString(properties, CFSTR("manufacturer"), &bios->biosVendor);
CFRelease(properties);
}
IOObjectRelease(registryEntry);
}
if((registryEntry = IORegistryEntryFromPath(MACH_PORT_NULL, "IODeviceTree:/chosen")))
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) == kIOReturnSuccess)
{
ffCfDictGetString(properties, CFSTR("system-firmware-version"), &bios->biosRelease);
ffStrbufAppend(&bios->biosVersion, &bios->biosRelease);
ffStrbufSubstrAfterFirstC(&bios->biosVersion, '-');
CFRelease(properties);
}
IOObjectRelease(registryEntry);
}
#endif
}
+26
View File
@@ -0,0 +1,26 @@
#include "bios.h"
#include <kenv.h>
static void kenvLookup(const char* name, FFstrbuf* result)
{
ffStrbufEnsureFree(result, 255);
int len = kenv(KENV_GET, name, result->chars, 256);
if(len > 0)
result->length = (uint32_t) len;
}
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
//https://wiki.ghostbsd.org/index.php/Kenv
kenvLookup("smbios.bios.reldate", &bios->biosDate);
kenvLookup("smbios.system.product", &bios->biosRelease);
kenvLookup("smbios.bios.vendor", &bios->biosVendor);
kenvLookup("smbios.bios.version", &bios->biosVersion);
}
+28
View File
@@ -0,0 +1,28 @@
#include "bios.h"
#include "util/windows/registry.h"
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &bios->error))
return;
if(!ffRegReadStrbuf(hKey, L"BIOSVersion", &bios->biosRelease, &bios->error))
return;
ffRegReadStrbuf(hKey, L"BIOSVendor", &bios->biosVendor, NULL);
ffRegReadStrbuf(hKey, L"BIOSReleaseDate", &bios->biosDate, NULL);
uint32_t major, minor;
if(
ffRegReadUint(hKey, L"BiosMajorRelease", &major, NULL) &&
ffRegReadUint(hKey, L"BiosMinorRelease", &minor, NULL)
)
ffStrbufAppendF(&bios->biosVersion, "%u.%u", (unsigned)major, (unsigned)minor);
}
-38
View File
@@ -1,38 +0,0 @@
extern "C" {
#include "bios.h"
}
#include "util/windows/wmi.hpp"
extern "C" void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, ReleaseDate, Version, Manufacturer FROM Win32_BIOS", &bios->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(uReturn == 0)
{
ffStrbufInitS(&bios->error, "No Wmi result returned");
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Name", &bios->biosRelease);
ffGetWmiObjString(pclsObj, L"ReleaseDate", &bios->biosDate);
ffGetWmiObjString(pclsObj, L"Version", &bios->biosVersion);
ffGetWmiObjString(pclsObj, L"Manufacturer", &bios->biosVendor);
pclsObj->Release();
pEnumerator->Release();
}
+21
View File
@@ -0,0 +1,21 @@
#include "board.h"
#include "util/windows/registry.h"
void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInit(&board->error);
ffStrbufInit(&board->boardName);
ffStrbufInit(&board->boardVendor);
ffStrbufInit(&board->boardVersion);
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, &board->error))
return;
if(!ffRegReadStrbuf(hKey, L"BaseBoardProduct", &board->boardName, &board->error))
return;
ffRegReadStrbuf(hKey, L"BaseBoardManufacturer", &board->boardVendor, NULL);
ffRegReadStrbuf(hKey, L"BaseBoardVersion", &board->boardVersion, NULL);
}
-36
View File
@@ -1,36 +0,0 @@
extern "C" {
#include "board.h"
}
#include "util/windows/wmi.hpp"
extern "C" void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInit(&board->error);
ffStrbufInit(&board->boardName);
ffStrbufInit(&board->boardVendor);
ffStrbufInit(&board->boardVersion);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Product, Version, Manufacturer FROM Win32_BaseBoard", &board->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(uReturn == 0)
{
ffStrbufInitS(&board->error, "No Wmi result returned");
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Product", &board->boardName);
ffGetWmiObjString(pclsObj, L"Manufacturer", &board->boardVendor);
ffGetWmiObjString(pclsObj, L"Version", &board->boardVersion);
pclsObj->Release();
pEnumerator->Release();
}
+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,33 @@
#include "brightness.h"
#include <CoreGraphics/CoreGraphics.h>
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __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);
if(CGDisplayIsBuiltin(screen))
ffStrbufInitS(&display->name, "built-in");
else
ffStrbufInitF(&display->name, "external-%u", (unsigned) screen);
display->value = brightness * 100;
}
return NULL;
}
@@ -0,0 +1,55 @@
#include "brightness.h"
#include "common/io.h"
#include <dirent.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/`";
FFstrbuf backlightDir;
ffStrbufInitA(&backlightDir, 64);
ffStrbufAppendS(&backlightDir, backlightDirPath);
uint32_t backlightDirLength = backlightDir.length;
FFstrbuf 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);
ffStrbufInitS(&display->name, entry->d_name);
double maxBrightness = ffStrbufToDouble(&buffer);
display->value = (float) (actualBrightness * 100 / maxBrightness);
}
break;
}
}
closedir(dirp);
ffStrbufDestroy(&backlightDir);
ffStrbufDestroy(&buffer);
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;
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifndef FF_INCLUDED_detection_chassis_chassis
#define FF_INCLUDED_detection_chassis_chassis
#include "fastfetch.h"
typedef struct FFChassisResult
{
FFstrbuf chassisType;
FFstrbuf chassisVendor;
FFstrbuf chassisVersion;
FFstrbuf error;
} FFChassisResult;
void ffDetectChassis(FFChassisResult* result);
#endif
+55
View File
@@ -0,0 +1,55 @@
#include "chassis.h"
#include "common/io.h"
#include <stdlib.h>
static bool hostValueSet(FFstrbuf* value)
{
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(hostValueSet(buffer))
return;
ffReadFileBuffer(classPath, buffer);
if(hostValueSet(buffer))
return;
ffStrbufClear(buffer);
}
void ffDetectChassis(FFChassisResult* result)
{
ffStrbufInit(&result->error);
ffStrbufInit(&result->chassisType);
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->chassisType);
ffStrbufInit(&result->chassisVendor);
getHostValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->chassisVendor);
ffStrbufInit(&result->chassisVersion);
getHostValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->chassisVersion);
}
+10
View File
@@ -0,0 +1,10 @@
#include "chassis.h"
void ffDetectChassis(FFChassisResult* result)
{
ffStrbufInitS(&result->error, "Not supported on this platform");
ffStrbufInit(&result->chassisType);
ffStrbufInit(&result->chassisVendor);
ffStrbufInit(&result->chassisVersion);
}
+2 -26
View File
@@ -1,37 +1,15 @@
#include "cpu.h"
#include "common/caching.h"
#include "detection/internal.h"
#define FF_CPU_CACHE_NAME "cpu"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached);
static bool cacheCallback(FFCPUResult* cpu, FFCache* cache, FFCacheMethodStrbuf strbufMethod, FFCacheMethodData dataMethod)
{
return
strbufMethod(cache, &cpu->vendor) &&
strbufMethod(cache, &cpu->name) &&
dataMethod(cache, sizeof(cpu->coresPhysical), &cpu->coresPhysical) &&
dataMethod(cache, sizeof(cpu->coresLogical), &cpu->coresLogical) &&
dataMethod(cache, sizeof(cpu->coresOnline), &cpu->coresOnline) &&
dataMethod(cache, sizeof(cpu->frequencyMin), &cpu->frequencyMin) &&
dataMethod(cache, sizeof(cpu->frequencyMax), &cpu->frequencyMax);
}
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu);
static void detectCPU(const FFinstance* instance, FFCPUResult* cpu)
{
ffStrbufInit(&cpu->name);
ffStrbufInit(&cpu->vendor);
bool cached = ffCacheRead(instance, cpu, FF_CPU_CACHE_NAME, (FFCacheMethodCallback) cacheCallback);
ffDetectCPUImpl(instance, cpu, cached);
if(cached)
return;
ffDetectCPUImpl(instance, cpu);
const char* removeStrings[] = {
"(R)", "(r)", "(TM)", "(tm)",
" CPU", " FPU", " APU", " Processor",
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core",
@@ -40,8 +18,6 @@ static void detectCPU(const FFinstance* instance, FFCPUResult* cpu)
ffStrbufRemoveStringsA(&cpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
ffCacheWrite(instance, cpu, FF_CPU_CACHE_NAME, (FFCacheMethodCallback) cacheCallback);
}
const FFCPUResult* ffDetectCPU(const FFinstance* instance)
+17 -21
View File
@@ -15,7 +15,7 @@ static double getFrequency(const char* propName)
static double detectCpuTemp(const FFstrbuf* cpuName)
{
FFlist temps;
FF_LIST_AUTO_DESTROY temps;
ffListInit(&temps, sizeof(FFTempValue));
if(ffStrbufStartsWithS(cpuName, "Apple M1"))
@@ -38,36 +38,32 @@ static double detectCpuTemp(const FFstrbuf* cpuName)
ffStrbufDestroy(&tempValue->deviceClass);
}
result /= temps.length;
ffListDestroy(&temps);
return result;
}
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
FF_UNUSED(instance);
if(!cached)
{
ffSysctlGetString("machdep.cpu.brand_string", &cpu->name);
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
ffSysctlGetString("machdep.cpu.brand_string", &cpu->name);
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
if(cpu->coresPhysical == 1)
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
if(cpu->coresPhysical == 1)
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu", 1);
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
if(cpu->coresLogical == 1)
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.logicalcpu_max", 1);
if(cpu->coresLogical == 1)
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
if(cpu->coresOnline == 1)
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.logicalcpu", 1);
if(cpu->coresOnline == 1)
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
if(cpu->frequencyMax == 0.0)
cpu->frequencyMax = getFrequency("hw.cpufrequency");
}
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
if(cpu->frequencyMax == 0.0)
cpu->frequencyMax = getFrequency("hw.cpufrequency");
if (instance->config.cpuTemp)
cpu->temperature = detectCpuTemp(&cpu->name);
+12 -5
View File
@@ -1,14 +1,21 @@
#include "cpu.h"
#include "common/sysctl.h"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
FF_UNUSED(instance);
cpu->temperature = FF_CPU_TEMP_UNSET;
if(cached)
return;
if (instance->config.cpuTemp)
{
FFstrbuf cpuTemp;
ffStrbufInit(&cpuTemp);
if(ffSysctlGetString("temperature", &cpuTemp))
cpu->temperature = FF_CPU_TEMP_UNSET;
else
cpu->temperature = ffStrbufToDouble(&cpuTemp);
}
else
cpu->temperature = FF_CPU_TEMP_UNSET;
ffSysctlGetString("hw.model", &cpu->name);
+79 -27
View File
@@ -3,10 +3,11 @@
#include "common/properties.h"
#include "detection/temps/temps_linux.h"
#include <sys/sysinfo.h>
#include <stdlib.h>
#include <unistd.h>
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer)
static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz, FFstrbuf* cpuIsa, FFstrbuf* cpuUarch)
{
FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL)
@@ -18,13 +19,16 @@ static void parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer)
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)(
ffParsePropLine(line, "model name :", &cpu->name) ||
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
);
}
@@ -39,16 +43,19 @@ static double getGHz(const char* file)
{
FFstrbuf content;
ffStrbufInit(&content);
ffReadFileBuffer(file, &content);
double herz = ffStrbufToDouble(&content);
ffStrbufDestroy(&content);
if(ffAppendFileBuffer(file, &content))
{
double herz = ffStrbufToDouble(&content);
ffStrbufDestroy(&content);
//ffStrbufToDouble failed
if(herz != herz)
return 0;
//ffStrbufToDouble failed
if(herz != herz)
return 0;
herz /= 1000.0; //to MHz
return herz / 1000.0; //to GHz
herz /= 1000.0; //to MHz
return herz / 1000.0; //to GHz
}
return 0;
}
static double getFrequency(const char* info, const char* scaling)
@@ -60,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++)
{
@@ -78,34 +85,79 @@ static double detectCPUTemp(const FFinstance* instance)
return FF_CPU_TEMP_UNSET;
}
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
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;
if(cached)
return;
FFstrbuf physicalCoresBuffer;
ffStrbufInit(&physicalCoresBuffer);
parseCpuInfo(cpu, &physicalCoresBuffer);
FFstrbuf cpuMHz;
ffStrbufInit(&cpuMHz);
FFstrbuf cpuIsa;
ffStrbufInit(&cpuIsa);
FFstrbuf cpuUarch;
ffStrbufInit(&cpuUarch);
parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch);
cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1);
#ifdef FF_HAVE_SYSINFO_H
cpu->coresLogical = (uint16_t) get_nprocs_conf();
cpu->coresOnline = (uint16_t) get_nprocs();
#else
cpu->coresLogical = 1;
cpu->coresOnline = 1;
#endif
cpu->coresLogical = (uint16_t) get_nprocs_conf();
cpu->coresOnline = (uint16_t) get_nprocs();
#define BP "/sys/devices/system/cpu/cpufreq/policy0/"
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
if(ffFileExists(BP, S_IFDIR))
{
cpu->frequencyMin = getFrequency(BP"cpuinfo_min_freq", BP"scaling_min_freq");
cpu->frequencyMax = getFrequency(BP"cpuinfo_max_freq", BP"scaling_max_freq");
}
else
{
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);
}
+49
View File
@@ -0,0 +1,49 @@
#include "cpu.h"
#include "util/windows/registry.h"
#include "util/mallocHelper.h"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu)
{
FF_UNUSED(instance);
cpu->temperature = FF_CPU_TEMP_UNSET;
cpu->coresPhysical = cpu->coresLogical = cpu->coresOnline = 0;
cpu->frequencyMax = cpu->frequencyMin = 0;
ffStrbufInit(&cpu->name);
ffStrbufInit(&cpu->vendor);
{
DWORD length = 0;
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &length);
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
pLogicalInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
if(pLogicalInfo && GetLogicalProcessorInformationEx(RelationProcessorCore, pLogicalInfo, &length))
{
for(
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pLogicalInfo;
(uint8_t*)ptr < ((uint8_t*)pLogicalInfo) + length;
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
)
{
if(ptr->Relationship == RelationProcessorCore)
++cpu->coresPhysical;
}
}
}
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))
return;
{
uint32_t mhz;
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
cpu->frequencyMax = mhz / 1000.0;
}
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
}
-51
View File
@@ -1,51 +0,0 @@
extern "C" {
#include "cpu.h"
}
#include "util/windows/wmi.hpp"
extern "C"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
{
FF_UNUSED(instance);
cpu->temperature = FF_CPU_TEMP_UNSET;
if(cached)
return;
cpu->coresPhysical = cpu->coresLogical = cpu->coresOnline = 0;
ffStrbufInit(&cpu->name);
ffStrbufInit(&cpu->vendor);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, ThreadCount, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3", nullptr);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Name", &cpu->name);
ffGetWmiObjString(pclsObj, L"Manufacturer", &cpu->vendor);
uint64_t value;
ffGetWmiObjUnsigned(pclsObj, L"NumberOfCores", &value);
cpu->coresPhysical = (uint16_t)value;
ffGetWmiObjUnsigned(pclsObj, L"NumberOfLogicalProcessors", &value);
cpu->coresLogical = (uint16_t)value;
ffGetWmiObjUnsigned(pclsObj, L"ThreadCount", &value);
cpu->coresOnline = (uint16_t)value;
ffGetWmiObjUnsigned(pclsObj, L"CurrentClockSpeed", &value); //There's no MinClockSpeed in Win32_Processor
cpu->frequencyMin = (double)value / 1000.0;
ffGetWmiObjUnsigned(pclsObj, L"MaxClockSpeed", &value);
cpu->frequencyMax = (double)value / 1000.0;
pclsObj->Release();
pEnumerator->Release();
}
+17 -31
View File
@@ -1,18 +1,6 @@
#include "fastfetch.h"
#include "cpuUsage.h"
#if FF_DETECTION_CPUUSAGE_NOWAIT
const char* ffGetCpuUsageResultNoWait(double* result);
void ffPrepareCPUUsage() {}
const char* ffGetCpuUsageResult(double* result) {
return ffGetCpuUsageResultNoWait(result);
}
#else //FF_DETECTION_CPUUSAGE_NOWAIT
#include "common/time.h"
#include <stdint.h>
@@ -20,39 +8,37 @@ const char* ffGetCpuUsageResult(double* result) {
// We need to use uint64_t because sizeof(long) == 4 on Windows
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
static uint64_t inUseAll1, totalAll1, startTime;
static uint64_t inUseAll1, totalAll1;
void ffPrepareCPUUsage()
{
startTime = ffTimeGetTick();
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
}
const char* ffGetCpuUsageResult(double* result)
{
const char* error = NULL;
if(startTime == 0)
if(inUseAll1 == 0 && totalAll1 == 0)
{
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
if(error)
return error;
ffTimeSleep(1000);
ffTimeSleep(200);
}
else
while(true)
{
uint64_t duration = ffTimeGetTick() - startTime;
if(duration < 1000)
ffTimeSleep(1000 - (uint32_t) duration);
uint64_t inUseAll2, totalAll2;
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
if(error)
return error;
if(inUseAll2 != inUseAll1)
{
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
return NULL;
}
else
ffTimeSleep(200);
}
uint64_t inUseAll2, totalAll2;
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
if(error)
return error;
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
return NULL;
}
#endif //FF_DETECTION_CPUUSAGE_NOWAIT
-5
View File
@@ -3,11 +3,6 @@
#ifndef FF_INCLUDED_detection_cpu_cpuUsage
#define FF_INCLUDED_detection_cpu_cpuUsage
#if defined(_WIN32) || defined(__MSYS__)
// Disabled by default because the result does need some time to generate
#define FF_DETECTION_CPUUSAGE_NOWAIT 0
#endif
const char* ffGetCpuUsageResult(double* result);
#endif
+19
View File
@@ -0,0 +1,19 @@
#include "cpuUsage.h"
#include <sys/types.h>
#include <sys/user.h>
#include <sys/sysctl.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
// interrupt processing, user processes, system processing, lock spinning, and idling
uint64_t cpTime[5];
size_t neededLength = sizeof(cpTime);
if(sysctlbyname("kern.cp_time", cpTime, &neededLength, NULL, 0) != 0)
return "sysctlbyname(kern.cp_time) failed";
*inUseAll = cpTime[0] + cpTime[1] + cpTime[2] + cpTime[3];
*totalAll = *inUseAll + cpTime[4];
return NULL;
}
+6
View File
@@ -10,7 +10,13 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
FILE* procStat = fopen("/proc/stat", "r");
if(procStat == NULL)
{
#ifdef __ANDROID__
return "Accessing \"/proc/stat\" is restricted on Android O+";
#else
return "fopen(\"""/proc/stat\", \"r\") == NULL";
#endif
}
if (fscanf(procStat, "cpu%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
{
@@ -1,26 +0,0 @@
extern "C" {
#include "cpuUsage.h"
}
#include "util/windows/wmi.hpp"
extern "C" const char* ffGetCpuUsageResultNoWait(double* result)
{
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT LoadPercentage FROM Win32_Processor", nullptr);
if(!pEnumerator)
return "Query WMI service failed";
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
pEnumerator->Release();
return "No WMI result returned";
}
ffGetWmiObjReal(pclsObj, L"LoadPercentage", result);
pclsObj->Release();
pEnumerator->Release();
return NULL;
}
+47 -5
View File
@@ -1,8 +1,46 @@
#include "fastfetch.h"
#include "cpuUsage.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#ifdef FF_USE_WIN_NTAPI
#include "util/mallocHelper.h"
#include <ntstatus.h>
#include <winternl.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
ULONG size = 0;
if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL) failed";
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* FF_AUTO_FREE pinfo = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*)malloc(size);
if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, pinfo, size, &size)))
return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, size) failed";
*inUseAll = *totalAll = 0;
for (uint32_t i = 0; i < size / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); ++i)
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* coreInfo = pinfo + i;
// KernelTime includes idle time.
LONGLONG dpcTime = coreInfo->Reserved1[0].QuadPart;
LONGLONG interruptTime = coreInfo->Reserved1[1].QuadPart;
coreInfo->KernelTime.QuadPart -= coreInfo->IdleTime.QuadPart;
coreInfo->KernelTime.QuadPart += dpcTime + interruptTime;
LONGLONG inUse = coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart;
*inUseAll += (uint64_t)inUse;
*totalAll += (uint64_t)(inUse + coreInfo->IdleTime.QuadPart);
}
return NULL;
}
#else
#include <processthreadsapi.h>
static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime);
@@ -11,10 +49,14 @@ static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
FILETIME idleTime, kernelTime, userTime;
if(GetSystemTimes(&idleTime, &kernelTime, &userTime) == 0)
if(!GetSystemTimes(&idleTime, &kernelTime, &userTime))
return "GetSystemTimes() failed";
*inUseAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime);
*totalAll = *inUseAll + fileTimeToUint64(&idleTime);
// 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
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#ifndef FF_INCLUDED_detection_cursor_cursor
#define FF_INCLUDED_detection_cursor_cursor
#include "fastfetch.h"
typedef struct FFCursorResult
{
FFstrbuf theme;
FFstrbuf size;
FFstrbuf error;
} FFCursorResult;
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result);
#endif
+90
View File
@@ -0,0 +1,90 @@
#include "cursor.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "common/settings.h"
#include "detection/gtk.h"
#include "detection/displayserver/displayserver.h"
#include <stdlib.h>
static bool detectCursorGTK(const FFinstance* instance, FFCursorResult* result)
{
const FFGTKResult* gtk = ffDetectGTK4(instance);
if(gtk->cursor.length == 0)
gtk = ffDetectGTK3(instance);
if(gtk->cursor.length == 0)
gtk = ffDetectGTK2(instance);
if(gtk->cursor.length == 0)
return false;
ffStrbufAppend(&result->theme, &gtk->cursor);
ffStrbufAppend(&result->size, &gtk->cursorSize);
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)
{
if(ffParsePropFileConfigValues(instance, relativeFilePath, 2, (FFpropquery[]) {
{themeStart, &result->theme},
{sizeStart, &result->size}
})) {
if(result->theme.length == 0)
ffStrbufAppendS(&result->theme, themeDefault);
if(result->size.length == 0)
ffStrbufAppendS(&result->size, sizeDefault);
}
if(result->theme.length == 0)
ffStrbufAppendF(&result->error, "Couldn't find cursor in %s", relativeFilePath);
}
static bool detectCursorFromXResources(const FFinstance* instance, FFCursorResult* result)
{
ffParsePropFileHomeValues(instance, ".Xresources", 2, (FFpropquery[]) {
{"Xcursor.theme :", &result->theme},
{"Xcursor.size :", &result->size}
});
return result->theme.length > 0;
}
static bool detectCursorFromEnv(const FFinstance* instance, FFCursorResult* result)
{
FF_UNUSED(instance);
const char* xcursor_theme = getenv("XCURSOR_THEME");
if(!ffStrSet(xcursor_theme))
return false;
ffStrbufAppendS(&result->theme, xcursor_theme);
ffStrbufAppendS(&result->size, getenv("XCURSOR_SIZE"));
return true;
}
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
{
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0)
ffStrbufAppendS(&result->error, "WSLg uses native windows cursor");
else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY");
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0)
detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "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");
}
+7
View File
@@ -0,0 +1,7 @@
#include "cursor.h"
void ffDetectCursor(const FFinstance* instance, FFCursorResult* result)
{
FF_UNUSED(instance, result);
ffStrbufInitS(&result->error, "Not supported on this platform");
}
+12
View File
@@ -0,0 +1,12 @@
#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);
}
+5 -5
View File
@@ -1,21 +1,21 @@
#include "fastfetch.h"
#include "detection/datetime.h"
#include "common/thread.h"
#include <time.h>
#include <pthread.h>
const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance)
{
FF_UNUSED(instance); //We may need it later for additional configuration
static FFDateTimeResult result;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
static bool init = false;
pthread_mutex_lock(&mutex);
ffThreadMutexLock(&mutex);
if (init)
{
pthread_mutex_unlock(&mutex);
ffThreadMutexUnlock(&mutex);
return &result;
}
init = true;
@@ -68,6 +68,6 @@ const FFDateTimeResult* ffDetectDateTime(const FFinstance* instance)
ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm);
pthread_mutex_unlock(&mutex);
ffThreadMutexUnlock(&mutex);
return &result;
}
+17 -45
View File
@@ -1,56 +1,28 @@
#include "fastfetch.h"
#include "disk.h"
#include "detection/internal.h"
#include <sys/statvfs.h>
void ffDetectDisksImpl(FFDiskResult* disks);
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result)
static int compareDisks(const void* disk1, const void* disk2)
{
ffStrbufInitS(&result->path, folderPath);
result->used = result->total = 0;
ffStrbufInit(&result->error);
struct statvfs newFs;
if(fs == NULL)
{
fs = &newFs;
int ret = statvfs(folderPath, fs);
if(ret != 0)
{
ffStrbufAppendF(&result->error, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
return;
}
}
result->total = fs->f_blocks * fs->f_frsize;
if(result->total == 0)
{
ffStrbufAppendF(&result->error, "statvfs for %s returned size 0", folderPath);
return;
}
result->used = result->total - (fs->f_bavail * fs->f_frsize);
result->files = (uint32_t) (fs->f_files - fs->f_ffree);
result->removable = false; //To be set at other place
return ffStrbufCompAlphabetically(&((const FFDisk*) disk1)->mountpoint, &((const FFDisk*) disk2)->mountpoint);
}
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
const FFDiskResult* ffDetectDisks()
{
ffStrbufTrim(&instance->config.diskFolders, ':');
if(instance->config.diskFolders.length == 0)
return false;
FF_DETECTION_INTERNAL_GUARD(FFDiskResult,
ffStrbufInit(&result.error);
ffListInitA(&result.disks, sizeof(FFDisk), 4);
uint32_t startIndex = 0;
while(startIndex < instance->config.diskFolders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
instance->config.diskFolders.chars[colonIndex] = '\0';
ffDetectDisksImpl(&result);
ffDetectDiskWithStatvfs(instance->config.diskFolders.chars + startIndex, NULL, (FFDiskResult*)ffListAdd(folders));
if(result.disks.length == 0 && result.error.length == 0)
ffStrbufAppendS(&result.error, "No disks found");
startIndex = colonIndex + 1;
}
return true;
//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);
);
}
+30 -7
View File
@@ -5,17 +5,40 @@
#include "fastfetch.h"
typedef enum FFDiskType
{
FF_DISK_TYPE_REGULAR,
FF_DISK_TYPE_HIDDEN,
FF_DISK_TYPE_EXTERNAL,
FF_DISK_TYPE_SUBVOLUME
} FFDiskType;
typedef struct FFDisk
{
FFstrbuf mountpoint;
FFstrbuf filesystem;
FFstrbuf name;
FFDiskType type;
uint64_t bytesUsed;
uint64_t bytesTotal;
uint32_t filesUsed;
uint32_t filesTotal;
} FFDisk;
typedef struct FFDiskResult
{
FFstrbuf path;
uint64_t used;
uint64_t total;
uint32_t files;
bool removable;
FFstrbuf error;
FFlist disks; //List of FFDisk
} FFDiskResult;
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders);
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders);
/**
* Returns a List of FFDisk, sorted alphabetically by mountpoint.
* If error is not set, disks contains at least one disk.
*
* @return const FFDiskResult*
*/
const FFDiskResult* ffDetectDisks();
#endif
+10 -22
View File
@@ -1,29 +1,17 @@
#include "disk.h"
#include <sys/mount.h>
#import <Foundation/Foundation.h>
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
void detectFsInfo(struct statfs* fs, FFDisk* disk)
{
NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeNameKey, nil];
NSArray *urls = [NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys:keys
options:NSVolumeEnumerationSkipHiddenVolumes];
if(urls == nil)
return "[NSFileManager.defaultManager mountedVolumeURLsIncludingResourceValuesForKeys] failed";
// FreeBSD doesn't support these flags
if(fs->f_flags & MNT_DONTBROWSE)
disk->type = FF_DISK_TYPE_HIDDEN;
else if(fs->f_flags & MNT_REMOVABLE)
disk->type = FF_DISK_TYPE_EXTERNAL;
else
disk->type = FF_DISK_TYPE_REGULAR;
for (NSURL *url in urls) {
NSError *error;
NSNumber* removable;
if([url getResourceValue:&removable forKey:NSURLVolumeIsRemovableKey error:&error] == NO)
continue;
if(removable.boolValue && !instance->config.diskRemovable)
continue;
FFDiskResult* folder = (FFDiskResult*)ffListAdd(folders);
ffDetectDiskWithStatvfs([url.relativePath cStringUsingEncoding:NSUTF8StringEncoding], NULL, folder);
folder->removable = removable.boolValue;
}
return NULL;
ffStrbufInitS(&disk->name, [NSFileManager.defaultManager displayNameAtPath:@(fs->f_mntonname)].UTF8String);
}
+56
View File
@@ -0,0 +1,56 @@
#include "disk.h"
#include <sys/mount.h>
#ifdef __FreeBSD__
static void detectFsInfo(struct statfs* fs, FFDisk* disk)
{
if(
ffStrbufStartsWithS(&disk->mountpoint, "/boot") ||
ffStrbufStartsWithS(&disk->mountpoint, "/dev") ||
ffStrbufStartsWithS(&disk->mountpoint, "/var") ||
ffStrbufStartsWithS(&disk->mountpoint, "/tmp") ||
ffStrbufStartsWithS(&disk->mountpoint, "/proc") ||
ffStrbufStartsWithS(&disk->mountpoint, "/zroot")
)
disk->type = FF_DISK_TYPE_HIDDEN;
else if((fs->f_flags & MNT_NOSUID) || !(fs->f_flags & MNT_LOCAL))
disk->type = FF_DISK_TYPE_EXTERNAL;
else
disk->type = FF_DISK_TYPE_REGULAR;
ffStrbufInit(&disk->name);
}
#else
void detectFsInfo(struct statfs* fs, FFDisk* disk);
#endif
void ffDetectDisksImpl(FFDiskResult* disks)
{
struct statfs* buf;
int size = getmntinfo(&buf, MNT_WAIT);
if(size <= 0)
ffStrbufAppendS(&disks->error, "getmntinfo() failed");
for(struct statfs* fs = buf; fs < buf + size; ++fs)
{
FFDisk* disk = ffListAdd(&disks->disks);
#ifdef __FreeBSD__
// f_bavail and f_ffree are signed on FreeBSD...
if(fs->f_bavail < 0) fs->f_bavail = 0;
if(fs->f_ffree < 0) fs->f_ffree = 0;
#endif
disk->bytesTotal = fs->f_blocks * fs->f_bsize;
disk->bytesUsed = disk->bytesTotal - ((uint64_t)fs->f_bavail * fs->f_bsize);
disk->filesTotal = (uint32_t) fs->f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs->f_ffree);
ffStrbufInitS(&disk->mountpoint, fs->f_mntonname);
ffStrbufInitS(&disk->filesystem, fs->f_fstypename);
detectFsInfo(fs, disk);
}
}
+229 -13
View File
@@ -1,24 +1,240 @@
#include "disk.h"
#include <limits.h>
#include <ctype.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
#ifdef __USE_LARGEFILE64
#define stat stat64
#define statvfs statvfs64
#define dirent dirent64
#define readdir readdir64
#endif
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
static bool isPhysicalDevice(const char* device)
{
FF_UNUSED(instance);
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
if(strcmp(device, "drvfs") == 0)
return true;
struct statvfs fsRoot;
int rootRet = statvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot);
if(rootRet != 0)
return "statvfs(\"/\") failed";
//Pseudo filesystems don't have a device in /dev
const char* devPrefix = "/dev/";
if(strncmp(device, devPrefix, strlen(devPrefix)) != 0)
return false;
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot, (FFDiskResult*)ffListAdd(folders));
//Skip /dev/ prefix
device += strlen(devPrefix);
struct statvfs fsHome;
int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome);
if(homeRet == 0 && (fsRoot.f_fsid != fsHome.f_fsid))
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome, (FFDiskResult*)ffListAdd(folders));
if(
strncmp(device, "loop", 4) == 0 || //Ignore loop devices
strncmp(device, "ram", 3) == 0 || //Ignore ram devices
strncmp(device, "fd", 2) == 0 //Ignore fd devices
) return false;
return NULL;
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)
{
char octal[4] = {0};
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(buffer, (char) value);
*source += 4;
continue;
}
}
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;
FFstrbuf 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);
ffStrbufDestroy(&basePath);
}
#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;
else if(ffStrbufStartsWithS(&currentDisk->mountpoint, "/mnt/media_rw/"))
currentDisk->type = FF_DISK_TYPE_EXTERNAL;
else
currentDisk->type = FF_DISK_TYPE_HIDDEN;
}
#else
static bool isSubvolume(const FFlist* devices)
{
const FFstrbuf* currentDevie = ffListGet(devices, devices->length - 1);
for(uint32_t i = 0; i < devices->length - 1; i++)
{
const FFstrbuf* otherDevice = ffListGet(devices, i);
if(ffStrbufEqual(currentDevie, otherDevice))
return true;
}
return false;
}
static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options)
{
if(isSubvolume(devices))
currentDisk->type = FF_DISK_TYPE_SUBVOLUME;
else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL)
currentDisk->type = FF_DISK_TYPE_EXTERNAL;
else if(ffStrbufStartsWithS(&currentDisk->mountpoint, "/boot") || ffStrbufStartsWithS(&currentDisk->mountpoint, "/efi"))
currentDisk->type = FF_DISK_TYPE_HIDDEN;
else
currentDisk->type = FF_DISK_TYPE_REGULAR;
}
#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)
{
FILE* mountsFile = fopen("/proc/mounts", "r");
if(mountsFile == NULL)
{
ffStrbufAppendS(&disks->error, "fopen(\"/proc/mounts\", \"r\") == NULL");
return;
}
FFlist devices;
ffListInit(&devices, sizeof(FFstrbuf));
char* line = NULL;
size_t len = 0;
while(getline(&line, &len, mountsFile) != EOF)
{
if(!isPhysicalDevice(line))
continue;
//We have a valid device, add it to the list
FFDisk* disk = ffListAdd(&disks->disks);
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
char* currentPos = line;
//detect device
FFstrbuf* device = ffListAdd(&devices);
ffStrbufInit(device);
appendNextEntry(device, &currentPos);
//detect mountpoint
ffStrbufInit(&disk->mountpoint);
appendNextEntry(&disk->mountpoint, &currentPos);
//detect filesystem
ffStrbufInit(&disk->filesystem);
appendNextEntry(&disk->filesystem, &currentPos);
//detect name
ffStrbufInit(&disk->name);
detectName(disk, device);
//detect type
detectType(&devices, disk, currentPos);
//Detects stats
detectStats(disk);
}
if(line != NULL)
free(line);
FF_LIST_FOR_EACH(FFstrbuf, device, devices)
ffStrbufDestroy(device);
ffListDestroy(&devices);
fclose(mountsFile);
}
+58 -54
View File
@@ -1,66 +1,70 @@
#include "disk.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#include <windows.h>
static void detectDrive(const char* folderPath, uint32_t pathLen, FFDiskResult* result)
void ffDetectDisksImpl(FFDiskResult* disks)
{
ffStrbufInitNS(&result->path, pathLen, folderPath);
result->removable = false; //To be set at other place
result->files = 0; //Unsupported
//According to https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexa
//GetDiskFreeSpaceExA does not have to specify the root directory on a disk. The function accepts any directory on a disk.
uint64_t freeBytes;
if(GetDiskFreeSpaceExA(folderPath, NULL, (PULARGE_INTEGER)&result->total, (PULARGE_INTEGER)&freeBytes)) {
result->used = result->total - freeBytes;
ffStrbufInit(&result->error);
}
else
ffStrbufInitS(&result->error, "GetDiskFreeSpaceExA() failed");
}
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
{
FF_UNUSED(instance);
char buf[128]; // "C:\\\0D:\\\0"
uint32_t length = GetLogicalDriveStringsA(sizeof(buf) / sizeof(*buf), buf);
for(size_t i = 0; i < length;)
uint32_t length = GetLogicalDriveStringsA(0, NULL);
if(length == 0)
{
const char* drive = buf + i;
uint32_t driveLen = (uint32_t) strlen(drive);
i += driveLen + 1;
ffStrbufAppendS(&disks->error, "GetLogicalDriveStringsA failed");
return;
}
bool removable = GetDriveTypeA(drive) == DRIVE_REMOVABLE;
if(removable && !instance->config.diskRemovable)
char* buf = malloc(length + 1);
GetLogicalDriveStringsA(length, buf);
for(uint32_t i = 0; i < length; i++)
{
const char* mountpoint = buf + i;
UINT driveType = GetDriveTypeA(mountpoint);
if(driveType == DRIVE_NO_ROOT_DIR)
{
i += (uint32_t)strlen(mountpoint);
continue;
}
FFDiskResult* folder = (FFDiskResult*)ffListAdd(folders);
detectDrive(drive, driveLen, folder);
folder->removable = removable;
FFDisk* disk = ffListAdd(&disks->disks);
ffStrbufInitS(&disk->mountpoint, mountpoint);
uint64_t bytesFree;
if(!GetDiskFreeSpaceExA(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
{
disk->bytesTotal = 0;
bytesFree = 0;
}
disk->bytesUsed = disk->bytesTotal - bytesFree;
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
disk->type = FF_DISK_TYPE_EXTERNAL;
else if(driveType == DRIVE_FIXED)
disk->type = FF_DISK_TYPE_REGULAR;
else
disk->type = FF_DISK_TYPE_HIDDEN;
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
NULL, //Serial number
NULL, //Max component length
NULL, //File system flags
disk->filesystem.chars, disk->filesystem.allocated
);
SetErrorMode(errorMode);
ffStrbufRecalculateLength(&disk->name);
ffStrbufRecalculateLength(&disk->filesystem);
//TODO: implement
disk->filesUsed = 0;
disk->filesTotal = 0;
i += disk->mountpoint.length;
}
return NULL;
}
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
{
ffStrbufTrim(&instance->config.diskFolders, ';');
if(instance->config.diskFolders.length == 0)
return false;
uint32_t startIndex = 0;
while(startIndex < instance->config.diskFolders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ';');
instance->config.diskFolders.chars[colonIndex] = '\0';
detectDrive(instance->config.diskFolders.chars + startIndex, colonIndex - startIndex, (FFDiskResult*)ffListAdd(folders));
startIndex = colonIndex + 1;
}
return true;
free(buf);
}
+7 -5
View File
@@ -19,15 +19,17 @@ uint32_t ffdsParseRefreshRate(int32_t refreshRate)
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, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight)
{
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;
return true;
}
+6 -4
View File
@@ -5,12 +5,14 @@
#include "fastfetch.h"
typedef struct FFResolutionResult
typedef struct FFDisplayResult
{
uint32_t width;
uint32_t height;
uint32_t refreshRate;
} FFResolutionResult;
uint32_t scaledWidth;
uint32_t scaledHeight;
} FFDisplayResult;
typedef struct FFDisplayServerResult
{
@@ -20,13 +22,13 @@ 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, uint32_t refreshRate, uint32_t scaledWidth, uint32_t scaledHeight);
#endif
@@ -4,56 +4,52 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <ApplicationServices/ApplicationServices.h>
#include <assert.h>
#include <CoreGraphics/CGDirectDisplay.h>
#include <CoreVideo/CVDisplayLink.h>
//Resolution code heavily inspired by displayplacer <3
typedef union
static void detectDisplays(FFDisplayServerResult* ds)
{
uint8_t rawData[0xDC];
struct
{
uint32_t mode;
uint32_t flags; // 0x4
uint32_t width; // 0x8
uint32_t height; // 0xC
uint32_t depth; // 0x10
uint32_t dc2[42];
uint16_t dc3;
uint16_t freq; // 0xBC
uint32_t dc4[4];
float density; // 0xD0
} derived;
} modes_D4;
void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
void CGSGetDisplayModeDescriptionOfLength(CGDirectDisplayID display, int idx, modes_D4* mode, int length);
static void detectResolution(FFDisplayServerResult* ds)
{
CGDisplayCount screenCount;
CGGetOnlineDisplayList(INT_MAX, NULL, &screenCount);
if(screenCount == 0)
CGDirectDisplayID screens[128];
uint32_t screenCount;
if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess)
return;
CGDirectDisplayID* screens = malloc(screenCount * sizeof(CGDirectDisplayID));
CGGetOnlineDisplayList(INT_MAX, screens, &screenCount);
for(uint32_t i = 0; i < screenCount; i++)
{
int modeID;
CGSGetCurrentDisplayMode(screens[i], &modeID);
modes_D4 mode;
CGSGetDisplayModeDescriptionOfLength(screens[i], modeID, &mode, 0xD4);
CGDirectDisplayID screen = screens[i];
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(screen);
if(mode)
{
//https://github.com/glfw/glfw/commit/aab08712dd8142b642e2042e7b7ba563acd07a45
double refreshRate = CGDisplayModeGetRefreshRate(mode);
uint32_t refreshRate = ffdsParseRefreshRate(mode.derived.freq);
ffdsAppendResolution(ds, mode.derived.width, mode.derived.height, refreshRate);
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);
}
}
ffdsAppendDisplay(ds,
(uint32_t)CGDisplayModeGetPixelWidth(mode),
(uint32_t)CGDisplayModeGetPixelHeight(mode),
(uint32_t)refreshRate,
(uint32_t)CGDisplayModeGetWidth(mode),
(uint32_t)CGDisplayModeGetHeight(mode)
);
CGDisplayModeRelease(mode);
}
CGDisplayRelease(screen);
}
free(screens);
}
static void detectWM(FFDisplayServerResult* ds)
static void detectWMPlugin(FFstrbuf* name)
{
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
u_int requestLength = sizeof(request) / sizeof(*request);
@@ -76,9 +72,8 @@ static void detectWM(FFDisplayServerResult* ds)
strcasecmp(comm, "rectangle") != 0
) continue;
ffStrbufAppendS(&ds->wmProcessName, comm);
ffStrbufAppendS(&ds->wmPrettyName, comm);
ds->wmPrettyName.chars[0] = (char) toupper(ds->wmPrettyName.chars[0]);
ffStrbufAppendS(name, comm);
name->chars[0] = (char) toupper(name->chars[0]);
break;
}
@@ -89,22 +84,24 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
{
FF_UNUSED(instance);
ffStrbufInit(&ds->wmProcessName);
ffStrbufInit(&ds->wmPrettyName);
ffStrbufInitA(&ds->wmProtocolName, 0);
detectWM(ds);
if(ds->wmProcessName.length == 0)
ffStrbufInitS(&ds->wmProcessName, "quartz");
ffStrbufInitS(&ds->wmPrettyName, "Quartz Compositor");
ffStrbufInit(&ds->wmProtocolName);
if(instance->config.allowSlowOperations)
{
ffStrbufAppendS(&ds->wmProcessName, "quartz");
ffStrbufAppendS(&ds->wmPrettyName, "Quartz Compositor");
FF_STRBUF_AUTO_DESTROY name;
detectWMPlugin(&name);
if(name.length)
ffStrbufAppendF(&ds->wmPrettyName, " (with %s)", name.chars);
}
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInitA(&ds->deVersion, 0);
ffStrbufInit(&ds->deVersion);
ffStrbufAppendS(&ds->deProcessName, "aqua");
ffStrbufAppendS(&ds->dePrettyName, "Aqua");
ffListInitA(&ds->resolutions, sizeof(FFResolutionResult), 4);
detectResolution(ds);
ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4);
detectDisplays(ds);
}
@@ -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);
}
@@ -4,6 +4,26 @@
#include <dwmapi.h>
#include <WinUser.h>
typedef struct
{
WCHAR* deviceName;
uint32_t width;
uint32_t height;
} DataBundle;
static CALLBACK WINBOOL enumMonitorProc(HMONITOR hMonitor, FF_MAYBE_UNUSED HDC hDC, FF_MAYBE_UNUSED LPRECT rc, LPARAM lparam)
{
MONITORINFOEXW mi = { .cbSize = sizeof(mi) };
DataBundle* data = (DataBundle*) lparam;
if(GetMonitorInfoW(hMonitor, (MONITORINFO *)&mi) && wcscmp(mi.szDevice, data->deviceName) == 0)
{
data->width = (uint32_t) mi.rcMonitor.right;
data->height = (uint32_t) mi.rcMonitor.bottom;
return FALSE;
}
return TRUE;
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
{
FF_UNUSED(instance);
@@ -23,7 +43,7 @@ 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)
@@ -34,15 +54,30 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* ins
if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0)
continue;
ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency);
DataBundle data = {
.deviceName = displayDevice.DeviceName,
.width = 0,
.height = 0,
};
EnumDisplayMonitors(NULL, NULL, enumMonitorProc, (LPARAM)&data);
ffdsAppendDisplay(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency, data.width, data.height);
}
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
const FFOSResult* os = ffDetectOS(instance);
if(ffStrbufCompS(&os->version, "11") == 0 || ffStrbufCompS(&os->version, "10") == 0)
ffStrbufSetS(&ds->dePrettyName, "Fluent");
else if(ffStrbufCompS(&os->version, "8") == 0 || ffStrbufStartsWithS(&os->version, "8."))
ffStrbufSetS(&ds->dePrettyName, "Metro");
if(
ffStrbufEqualS(&os->version, "11") ||
ffStrbufEqualS(&os->version, "10") ||
ffStrbufEqualS(&os->version, "2022") ||
ffStrbufEqualS(&os->version, "2019") ||
ffStrbufEqualS(&os->version, "2016")
) ffStrbufSetS(&ds->dePrettyName, "Fluent");
else if(
ffStrbufEqualS(&os->version, "8") ||
ffStrbufEqualS(&os->version, "81.") ||
ffStrbufEqualS(&os->version, "2012 R2") ||
ffStrbufEqualS(&os->version, "2012")
) ffStrbufSetS(&ds->dePrettyName, "Metro");
else
ffStrbufSetS(&ds->dePrettyName, "Aero");
}
@@ -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
+10 -8
View File
@@ -6,7 +6,7 @@
#ifdef FF_HAVE_WAYLAND
#include "common/library.h"
#include "common/io.h"
#include <pthread.h>
#include "common/thread.h"
#include <wayland-client.h>
#include <sys/socket.h>
@@ -56,16 +56,18 @@ static void waylandOutputModeListener(void* data, struct wl_output* output, uint
if(!(flags & WL_OUTPUT_MODE_CURRENT) || width <= 0 || height <= 0)
return;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
ffThreadMutexLock(&mutex);
FFResolutionResult* result = ffListAdd(wldata->results);
FFDisplayResult* result = ffListAdd(wldata->results);
pthread_mutex_unlock(&mutex);
ffThreadMutexUnlock(&mutex);
result->width = (uint32_t) width;
result->height = (uint32_t) height;
result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000);
result->scaledWidth = 0;
result->scaledHeight = 0;
}
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
@@ -102,7 +104,7 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(wayland, &instance->config.libWayland, false, "libwayland-client.so", 1)
FF_LIBRARY_LOAD(wayland, &instance->config.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
@@ -136,7 +138,7 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
return false;
}
data.results = &result->resolutions;
data.results = &result->displays;
struct wl_registry_listener registry_listener = {
.global = waylandGlobalAddListener,
@@ -151,7 +153,7 @@ bool detectWayland(const FFinstance* instance, FFDisplayServerResult* result)
ffwl_display_disconnect(display);
dlclose(wayland);
//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);
+31 -22
View File
@@ -9,7 +9,6 @@
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
static const char* parseEnv()
{
@@ -117,38 +116,34 @@ 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");
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);
ffParsePropFileData(instance, "gnome-shell/org.gnome.Extensions", "version :", &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);
ffParsePropFileData(instance, "applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
}
static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
@@ -165,7 +160,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}
@@ -194,7 +189,7 @@ 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);
ffParsePropFileData(instance, "gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
{
@@ -215,12 +210,12 @@ 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);
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)
{
@@ -244,6 +239,13 @@ static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
ffStrbufDestroy(&wmProcessNameBuffer);
}
static void getBudgie(const FFinstance* instance, FFDisplayServerResult* result)
{
ffStrbufSetS(&result->dePrettyName, "Budgie");
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
ffParsePropFileData(instance, "budgie/budgie-version.xml", "<str>", &result->deVersion);
}
static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResult* result, const char* name)
{
if(!ffStrSet(name))
@@ -254,19 +256,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 ||
@@ -287,6 +289,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)
+22 -12
View File
@@ -91,7 +91,7 @@ static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connect
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcb, &instance->config.libXcb, , "libxcb.so", 2)
FF_LIBRARY_LOAD(xcb, &instance->config.libXcb, , "libxcb" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_connect,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_get_setup,)
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_setup_roots_iterator,)
@@ -115,10 +115,12 @@ void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
while(iterator.rem > 0)
{
ffdsAppendResolution(
ffdsAppendDisplay(
result,
(uint32_t) iterator.data->width_in_pixels,
(uint32_t) iterator.data->height_in_pixels,
0,
0,
0
);
ffxcb_screen_next(&iterator);
@@ -180,17 +182,19 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo
modeInfo->dot_clock / (uint32_t) (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,
0,
0
);
}
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 +219,13 @@ 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,
0,
0
);
free(crtcInfoReply);
@@ -258,11 +264,13 @@ 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,
0,
0
);
}
@@ -316,17 +324,19 @@ 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,
0,
0
);
}
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcbRandr, &instance->config.libXcbRandr, , "libxcb-randr.so", 1)
FF_LIBRARY_LOAD(xcbRandr, &instance->config.libXcbRandr, , "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_connect,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_get_setup,)
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_setup_roots_iterator,)

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