mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2025-02-20 11:43:27 +08:00
commit
5060c265a9
38
.github/workflows/ci.yml
vendored
38
.github/workflows/ci.yml
vendored
@ -438,43 +438,6 @@ jobs:
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
freebsd-aarch64:
|
||||
name: FreeBSD-aarch64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: freebsd
|
||||
architecture: arm64
|
||||
cpu_count: 3
|
||||
shell: bash
|
||||
version: '13.2'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd v4l_compat
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch
|
||||
time ./fastfetch --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-freebsd-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
@ -623,7 +586,6 @@ jobs:
|
||||
- musl-aarch64
|
||||
- macos-universal
|
||||
- freebsd-amd64
|
||||
- freebsd-aarch64
|
||||
- sunos-amd64
|
||||
- windows-amd64
|
||||
- windows-i686
|
||||
|
29
CHANGELOG.md
29
CHANGELOG.md
@ -1,3 +1,32 @@
|
||||
# 2.18.0
|
||||
|
||||
Changes:
|
||||
* `yyjson 0.10.0` is required
|
||||
* Fastfetch no longer prints `*` (which means it's the default route) if `defaultRouteOnly` is set (LocalIP)
|
||||
|
||||
Bugfixes:
|
||||
* Fix some memory leaks
|
||||
* Fix compatibility with old Python versions
|
||||
* Don't detect frequency for AMD cards (GPU, Linux)
|
||||
* Fix possible hang with discrete AMD cards (#1077)
|
||||
* Don't print colors in `--pipe` mode (Separator)
|
||||
* Don't print `(null)` in property `locator` (PhysicalMemory)
|
||||
* Ignore disabled PCI devices (GPU)
|
||||
* Fix flag `--opengl-library` doesn't work (OpenGL)
|
||||
|
||||
Features:
|
||||
* Detect revision of USB drives (#1048, Disk)
|
||||
* Support fractional scale factor detection (Display, Linux)
|
||||
* Support primary display detection for KDE and GNOME (Display, Linux)
|
||||
* Support percent bar in custom formatting
|
||||
* Print signal quality by default (Wifi)
|
||||
* Detect used OpenGL library version (OpenGL)
|
||||
* Support detecting OpenGL version by `EGL` (ANGLE) on Windows (OpenGL)
|
||||
|
||||
Logos:
|
||||
* Add Arkane Linux
|
||||
* Add Opak
|
||||
|
||||
# 2.17.2
|
||||
|
||||
Changes:
|
||||
|
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.17.2
|
||||
VERSION 2.18.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@ -61,7 +61,7 @@ cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR B
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE OR SunOS" 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 OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD OR WIN32 OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32 OR ANDROID OR SunOS" OFF)
|
||||
@ -307,6 +307,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/media/media.c
|
||||
src/detection/netio/netio.c
|
||||
src/detection/opencl/opencl.c
|
||||
src/detection/opengl/opengl_shared.c
|
||||
src/detection/os/os.c
|
||||
src/detection/packages/packages.c
|
||||
src/detection/physicalmemory/physicalmemory.c
|
||||
@ -395,6 +396,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/options/general.c
|
||||
src/options/library.c
|
||||
src/util/edidHelper.c
|
||||
src/util/base64.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
src/util/platform/FFPlatform.c
|
||||
@ -429,7 +431,11 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
@ -562,7 +568,11 @@ elseif(BSD)
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
@ -763,7 +773,11 @@ elseif(SunOS)
|
||||
src/detection/displayserver/linux/wayland/wayland.c
|
||||
src/detection/displayserver/linux/wayland/global-output.c
|
||||
src/detection/displayserver/linux/wayland/zwlr-output.c
|
||||
src/detection/displayserver/linux/wayland/kde-output.c
|
||||
src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c
|
||||
src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c
|
||||
src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
|
@ -356,7 +356,6 @@ __fastfetch_completion()
|
||||
local FF_OPTIONS_PATH=(
|
||||
"-c"
|
||||
"--config"
|
||||
"--lib-pci"
|
||||
"--lib-vulkan"
|
||||
"--lib-wayland"
|
||||
"--lib-xcb-randr"
|
||||
|
@ -54,51 +54,48 @@ function __fastfetch_complete_structure
|
||||
end
|
||||
end
|
||||
|
||||
string match -r -a -g "^###> ?(.*)" < (status -f) | string collect | python3 | source
|
||||
echo '
|
||||
import json, subprocess, sys
|
||||
|
||||
###> #!/usr/bin/env python3
|
||||
###>
|
||||
###> import json, subprocess, sys
|
||||
###>
|
||||
###> def main():
|
||||
###> data: dict[str, list[dict]] = json.loads(subprocess.check_output(['fastfetch', '--help-raw']))
|
||||
###>
|
||||
###> for key in data:
|
||||
###> for flag in data[key]:
|
||||
###> if flag.get('pseudo', False):
|
||||
###> continue
|
||||
###>
|
||||
###> command_prefix: str = f'complete -c fastfetch -d "{flag["desc"]}" -l "{flag["long"]}"';
|
||||
###> if 'short' in flag:
|
||||
###> command_prefix += f' -o "{flag["short"]}"'
|
||||
###>
|
||||
###> if 'arg' in flag:
|
||||
###> type: str = flag['arg']['type'];
|
||||
###> if type == 'bool':
|
||||
###> print(f'{command_prefix} -x -a "(__fastfetch_complete_bool)"')
|
||||
###> elif type == 'color':
|
||||
###> print(f'{command_prefix} -x -a "(__fastfetch_complete_color)"')
|
||||
###> elif type == 'command':
|
||||
###> print(f'{command_prefix} -x -a "(__fastfetch_complete_command)"')
|
||||
###> elif type == 'config':
|
||||
###> print(f'{command_prefix} -x -a "(__fastfetch_complete_config)"')
|
||||
###> elif type == 'enum':
|
||||
###> temp: str = ' '.join(flag["arg"]["enum"])
|
||||
###> print(f'{command_prefix} -x -a "{temp}"')
|
||||
###> elif type == 'logo':
|
||||
###> print(f'{command_prefix} -x -a "(__fastfetch_complete_logo)"')
|
||||
###> elif type == 'structure':
|
||||
###> print(f'{command_prefix} -x -a "(__fish_complete_list : __fastfetch_complete_structure)"')
|
||||
###> elif type == 'path':
|
||||
###> print(f'{command_prefix} -r -F')
|
||||
###> else:
|
||||
###> print(f'{command_prefix} -x')
|
||||
###> else:
|
||||
###> print(f'{command_prefix} -f')
|
||||
###>
|
||||
###> if __name__ == "__main__":
|
||||
###> try:
|
||||
###> main()
|
||||
###> except:
|
||||
###> sys.exit(1)
|
||||
###>
|
||||
def main():
|
||||
data: dict[str, list[dict]] = json.loads(subprocess.check_output(["fastfetch", "--help-raw"]))
|
||||
|
||||
for key in data:
|
||||
for flag in data[key]:
|
||||
if flag.get("pseudo", False):
|
||||
continue
|
||||
|
||||
command_prefix = f"""complete -c fastfetch -d "{flag["desc"]}" -l "{flag["long"]}\""""
|
||||
if "short" in flag:
|
||||
command_prefix += f""" -o {flag["short"]}"""
|
||||
|
||||
if "arg" in flag:
|
||||
type: str = flag["arg"]["type"];
|
||||
if type == "bool":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"")
|
||||
elif type == "color":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"")
|
||||
elif type == "command":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"")
|
||||
elif type == "config":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"")
|
||||
elif type == "enum":
|
||||
temp: str = " ".join(flag["arg"]["enum"])
|
||||
print(f"{command_prefix} -x -a \"{temp}\"")
|
||||
elif type == "logo":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"")
|
||||
elif type == "structure":
|
||||
print(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"")
|
||||
elif type == "path":
|
||||
print(f"{command_prefix} -r -F")
|
||||
else:
|
||||
print(f"{command_prefix} -x")
|
||||
else:
|
||||
print(f"{command_prefix} -f")
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except:
|
||||
sys.exit(1)
|
||||
' | python3 | source
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
||||
fastfetch (2.17.2) jammy; urgency=medium
|
||||
|
||||
* Update to 2.17.2
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 04 Jul 2024 10:22:44 +0800
|
||||
|
||||
fastfetch (2.17.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.17.1
|
||||
|
2
debian/files
vendored
2
debian/files
vendored
@ -1 +1 @@
|
||||
fastfetch_2.17.1_source.buildinfo universe/utils optional
|
||||
fastfetch_2.17.2_source.buildinfo universe/utils optional
|
||||
|
@ -586,10 +586,6 @@
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"pci": {
|
||||
"type": "string",
|
||||
"description": "GPU output (Linux and FreeBSD)"
|
||||
},
|
||||
"vulkan": {
|
||||
"type": "string",
|
||||
"description": "Vulkan module & fallback for GPU output"
|
||||
@ -604,39 +600,39 @@
|
||||
},
|
||||
"xcbRandr": {
|
||||
"type": "string",
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD)"
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"xcb": {
|
||||
"type": "string",
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD)"
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"xrandr": {
|
||||
"type": "string",
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD)"
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"x11": {
|
||||
"type": "string",
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD)"
|
||||
"description": "X11 sessions for better display detection and faster WM detection.\nThe *randr ones provide multi monitor support The libxcb* ones usually have better performance.\n (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"drm": {
|
||||
"type": "string",
|
||||
"description": "Used for fast resolution and refresh rate detection (Linux)"
|
||||
"description": "Used for fast resolution and refresh rate detection (Linux, FreeBSD)"
|
||||
},
|
||||
"gio": {
|
||||
"type": "string",
|
||||
"description": "Needed for values that are only stored GSettings (Linux, FreeBSD)"
|
||||
"description": "Needed for values that are only stored GSettings (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"dconf": {
|
||||
"type": "string",
|
||||
"description": "Needed for values that are only stored in DConf + Fallback for GSettings (Linux, FreeBSD)"
|
||||
"description": "Needed for values that are only stored in DConf + Fallback for GSettings (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"dbus": {
|
||||
"type": "string",
|
||||
"description": "Bluetooth, Player & Media detection (Linux, FreeBSD)"
|
||||
"description": "Bluetooth, Player & Media detection (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"xfconf": {
|
||||
"type": "string",
|
||||
"description": "Needed for XFWM theme and XFCE Terminal font (Linux, FreeBSD)"
|
||||
"description": "Needed for XFWM theme and XFCE Terminal font (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"sqlite3": {
|
||||
"type": "string",
|
||||
@ -648,34 +644,34 @@
|
||||
},
|
||||
"imagemagick": {
|
||||
"type": "string",
|
||||
"description": "Images in terminal using sixel or kitty graphics protocol (Linux, FreeBSD, macOS)"
|
||||
"description": "Images in terminal using sixel or kitty graphics protocol (Linux, FreeBSD, SunOS, macOS)"
|
||||
},
|
||||
"z": {
|
||||
"description": "Libz. Faster image output when using kitty graphics protocol (Linux, FreeBSD, macOS)",
|
||||
"description": "Libz. Faster image output when using kitty graphics protocol (Linux, FreeBSD, SunOS, macOS)",
|
||||
"type": "string"
|
||||
},
|
||||
"chafa": {
|
||||
"type": "string",
|
||||
"description": "Image output as ascii art (Linux, FreeBSD, macOS)"
|
||||
"description": "Image output as ascii art (Linux, FreeBSD, SunOS, macOS)"
|
||||
},
|
||||
"egl": {
|
||||
"type": "string",
|
||||
"description": "Needed by the OpenGL module for gl context creation (Linux, FreeBSD)"
|
||||
"description": "Library used by the OpenGL module for gl context creation (Linux, FreeBSD, SunOS, Windows)"
|
||||
},
|
||||
"glx": {
|
||||
"type": "string",
|
||||
"description": "Needed by the OpenGL module for gl context creation (Linux, FreeBSD)"
|
||||
"description": "Library used by the OpenGL module for gl context creation (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"osmesa": {
|
||||
"type": "string",
|
||||
"description": "Needed by the OpenGL module for gl context creation (Linux, FreeBSD)"
|
||||
"description": "Library used by the OpenGL module for gl context creation (Linux, FreeBSD, SunOS)"
|
||||
},
|
||||
"opencl": {
|
||||
"type": "string",
|
||||
"description": "OpenCL module (Linux, FreeBSD, Windows)"
|
||||
"description": "OpenCL module (Linux, FreeBSD, SunOS, Windows)"
|
||||
},
|
||||
"pulse": {
|
||||
"description": "Pulseaudio. Used for Sound detection (Linux, FreeBSD)",
|
||||
"description": "Pulseaudio. Used for Sound detection (Linux, FreeBSD, SunOS)",
|
||||
"type": "string"
|
||||
},
|
||||
"nm": {
|
||||
@ -1771,7 +1767,7 @@
|
||||
"const": "opengl"
|
||||
},
|
||||
"library": {
|
||||
"description": "Set the OpenGL context creation library to use. Linux only",
|
||||
"description": "Set the OpenGL context creation library to use",
|
||||
"enum": [
|
||||
"auto",
|
||||
"egl",
|
||||
@ -1820,6 +1816,9 @@
|
||||
"emerge",
|
||||
"eopkg",
|
||||
"flatpak",
|
||||
"guix",
|
||||
"lpkg",
|
||||
"lpkgbuild",
|
||||
"macports",
|
||||
"nix",
|
||||
"opkg",
|
||||
@ -1830,6 +1829,7 @@
|
||||
"rpm",
|
||||
"scoop",
|
||||
"snap",
|
||||
"sorcery",
|
||||
"winget",
|
||||
"xbps"
|
||||
],
|
||||
|
@ -47,6 +47,7 @@
|
||||
"cpuusage",
|
||||
{
|
||||
"type": "gpu",
|
||||
"driverSpecific": true,
|
||||
"temp": true
|
||||
},
|
||||
"memory",
|
||||
@ -63,6 +64,7 @@
|
||||
"showIpv6": true,
|
||||
"showMac": true
|
||||
},
|
||||
"dns",
|
||||
"wifi",
|
||||
"datetime",
|
||||
"locale",
|
||||
|
@ -49,6 +49,7 @@
|
||||
"cpuusage",
|
||||
{
|
||||
"type": "gpu",
|
||||
"driverSpecific": true,
|
||||
"temp": true
|
||||
},
|
||||
"memory",
|
||||
@ -65,6 +66,7 @@
|
||||
"showIpv6": true,
|
||||
"showMac": true
|
||||
},
|
||||
"dns",
|
||||
"wifi",
|
||||
"datetime",
|
||||
"locale",
|
||||
|
2
src/3rdparty/yyjson/repo.json
vendored
2
src/3rdparty/yyjson/repo.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/ibireme/yyjson",
|
||||
"license": "MIT ( embed in source )",
|
||||
"version": "0.9.0",
|
||||
"version": "0.10.0",
|
||||
"author": "ibireme"
|
||||
}
|
||||
|
209
src/3rdparty/yyjson/yyjson.c
vendored
209
src/3rdparty/yyjson/yyjson.c
vendored
@ -1831,6 +1831,42 @@ bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) {
|
||||
}
|
||||
}
|
||||
|
||||
bool yyjson_locate_pos(const char *str, size_t len, size_t pos,
|
||||
size_t *line, size_t *col, size_t *chr) {
|
||||
usize line_sum = 0, line_pos = 0, chr_sum = 0;
|
||||
const u8 *cur = (const u8 *)str;
|
||||
const u8 *end = cur + pos;
|
||||
|
||||
if (!str || pos > len) {
|
||||
if (line) *line = 0;
|
||||
if (col) *col = 0;
|
||||
if (chr) *chr = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
while (cur < end) {
|
||||
u8 c = *cur;
|
||||
chr_sum += 1;
|
||||
if (likely(c < 0x80)) { /* 0xxxxxxx (0x00-0x7F) ASCII */
|
||||
if (c == '\n') {
|
||||
line_sum += 1;
|
||||
line_pos = chr_sum;
|
||||
}
|
||||
cur += 1;
|
||||
}
|
||||
else if (c < 0xC0) cur += 1; /* 10xxxxxx (0x80-0xBF) Invalid */
|
||||
else if (c < 0xE0) cur += 2; /* 110xxxxx (0xC0-0xDF) 2-byte UTF-8 */
|
||||
else if (c < 0xF0) cur += 3; /* 1110xxxx (0xE0-0xEF) 3-byte UTF-8 */
|
||||
else if (c < 0xF8) cur += 4; /* 11110xxx (0xF0-0xF7) 4-byte UTF-8 */
|
||||
else cur += 1; /* 11111xxx (0xF8-0xFF) Invalid */
|
||||
}
|
||||
|
||||
if (line) *line = line_sum + 1;
|
||||
if (col) *col = chr_sum - line_pos + 1;
|
||||
if (chr) *chr = chr_sum;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if !YYJSON_DISABLE_UTILS
|
||||
@ -4434,7 +4470,7 @@ static_inline bool read_number(u8 **ptr,
|
||||
bool sign;
|
||||
|
||||
/* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */
|
||||
if (unlikely(pre && !has_read_flag(BIGNUM_AS_RAW))) {
|
||||
if (has_read_flag(NUMBER_AS_RAW)) {
|
||||
return read_number_raw(ptr, pre, flg, val, msg);
|
||||
}
|
||||
|
||||
@ -5036,7 +5072,7 @@ static_inline bool read_number(u8 **ptr,
|
||||
bool sign;
|
||||
|
||||
/* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */
|
||||
if (unlikely(pre && !has_read_flag(BIGNUM_AS_RAW))) {
|
||||
if (has_read_flag(NUMBER_AS_RAW)) {
|
||||
return read_number_raw(ptr, pre, flg, val, msg);
|
||||
}
|
||||
|
||||
@ -5744,18 +5780,18 @@ static_noinline yyjson_doc *read_root_single(u8 *hdr,
|
||||
}
|
||||
if (*cur == 't') {
|
||||
if (likely(read_true(&cur, val))) goto doc_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_true;
|
||||
}
|
||||
if (*cur == 'f') {
|
||||
if (likely(read_false(&cur, val))) goto doc_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_false;
|
||||
}
|
||||
if (*cur == 'n') {
|
||||
if (likely(read_null(&cur, val))) goto doc_end;
|
||||
if (has_read_flag(ALLOW_INF_AND_NAN)) {
|
||||
if (read_nan(false, &cur, pre, val)) goto doc_end;
|
||||
}
|
||||
goto fail_literal;
|
||||
goto fail_literal_null;
|
||||
}
|
||||
if (has_read_flag(ALLOW_INF_AND_NAN)) {
|
||||
if (read_inf_or_nan(false, &cur, pre, val)) goto doc_end;
|
||||
@ -5789,15 +5825,26 @@ fail_string:
|
||||
fail_number:
|
||||
return_err(cur, INVALID_NUMBER, msg);
|
||||
fail_alloc:
|
||||
return_err(cur, MEMORY_ALLOCATION, "memory allocation failed");
|
||||
fail_literal:
|
||||
return_err(cur, LITERAL, "invalid literal");
|
||||
fail_comment:
|
||||
return_err(cur, INVALID_COMMENT, "unclosed multiline comment");
|
||||
return_err(cur, MEMORY_ALLOCATION,
|
||||
"memory allocation failed");
|
||||
fail_literal_true:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'true'");
|
||||
fail_literal_false:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'false'");
|
||||
fail_literal_null:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'null'");
|
||||
fail_character:
|
||||
return_err(cur, UNEXPECTED_CHARACTER, "unexpected character");
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a valid root value");
|
||||
fail_comment:
|
||||
return_err(cur, INVALID_COMMENT,
|
||||
"unclosed multiline comment");
|
||||
fail_garbage:
|
||||
return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document");
|
||||
return_err(cur, UNEXPECTED_CONTENT,
|
||||
"unexpected content after document");
|
||||
|
||||
#undef return_err
|
||||
}
|
||||
@ -5927,13 +5974,13 @@ arr_val_begin:
|
||||
val_incr();
|
||||
ctn_len++;
|
||||
if (likely(read_true(&cur, val))) goto arr_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_true;
|
||||
}
|
||||
if (*cur == 'f') {
|
||||
val_incr();
|
||||
ctn_len++;
|
||||
if (likely(read_false(&cur, val))) goto arr_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_false;
|
||||
}
|
||||
if (*cur == 'n') {
|
||||
val_incr();
|
||||
@ -5942,7 +5989,7 @@ arr_val_begin:
|
||||
if (has_read_flag(ALLOW_INF_AND_NAN)) {
|
||||
if (read_nan(false, &cur, pre, val)) goto arr_val_end;
|
||||
}
|
||||
goto fail_literal;
|
||||
goto fail_literal_null;
|
||||
}
|
||||
if (*cur == ']') {
|
||||
cur++;
|
||||
@ -5960,13 +6007,13 @@ arr_val_begin:
|
||||
val_incr();
|
||||
ctn_len++;
|
||||
if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end;
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
}
|
||||
if (has_read_flag(ALLOW_COMMENTS)) {
|
||||
if (skip_spaces_and_comments(&cur)) goto arr_val_begin;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
|
||||
arr_val_end:
|
||||
if (*cur == ',') {
|
||||
@ -5985,7 +6032,7 @@ arr_val_end:
|
||||
if (skip_spaces_and_comments(&cur)) goto arr_val_end;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_arr_end;
|
||||
|
||||
arr_end:
|
||||
/* get parent container */
|
||||
@ -6038,7 +6085,7 @@ obj_key_begin:
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_key_begin;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_obj_key;
|
||||
|
||||
obj_key_end:
|
||||
if (*cur == ':') {
|
||||
@ -6053,7 +6100,7 @@ obj_key_end:
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_key_end;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_obj_sep;
|
||||
|
||||
obj_val_begin:
|
||||
if (*cur == '"') {
|
||||
@ -6080,13 +6127,13 @@ obj_val_begin:
|
||||
val++;
|
||||
ctn_len++;
|
||||
if (likely(read_true(&cur, val))) goto obj_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_true;
|
||||
}
|
||||
if (*cur == 'f') {
|
||||
val++;
|
||||
ctn_len++;
|
||||
if (likely(read_false(&cur, val))) goto obj_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_false;
|
||||
}
|
||||
if (*cur == 'n') {
|
||||
val++;
|
||||
@ -6095,7 +6142,7 @@ obj_val_begin:
|
||||
if (has_read_flag(ALLOW_INF_AND_NAN)) {
|
||||
if (read_nan(false, &cur, pre, val)) goto obj_val_end;
|
||||
}
|
||||
goto fail_literal;
|
||||
goto fail_literal_null;
|
||||
}
|
||||
if (char_is_space(*cur)) {
|
||||
while (char_is_space(*++cur));
|
||||
@ -6106,13 +6153,13 @@ obj_val_begin:
|
||||
val++;
|
||||
ctn_len++;
|
||||
if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end;
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
}
|
||||
if (has_read_flag(ALLOW_COMMENTS)) {
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_val_begin;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
|
||||
obj_val_end:
|
||||
if (likely(*cur == ',')) {
|
||||
@ -6131,7 +6178,7 @@ obj_val_end:
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_val_end;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_obj_end;
|
||||
|
||||
obj_end:
|
||||
/* pop container */
|
||||
@ -6174,17 +6221,41 @@ fail_string:
|
||||
fail_number:
|
||||
return_err(cur, INVALID_NUMBER, msg);
|
||||
fail_alloc:
|
||||
return_err(cur, MEMORY_ALLOCATION, "memory allocation failed");
|
||||
return_err(cur, MEMORY_ALLOCATION,
|
||||
"memory allocation failed");
|
||||
fail_trailing_comma:
|
||||
return_err(cur, JSON_STRUCTURE, "trailing comma is not allowed");
|
||||
fail_literal:
|
||||
return_err(cur, LITERAL, "invalid literal");
|
||||
return_err(cur, JSON_STRUCTURE,
|
||||
"trailing comma is not allowed");
|
||||
fail_literal_true:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'true'");
|
||||
fail_literal_false:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'false'");
|
||||
fail_literal_null:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'null'");
|
||||
fail_character_val:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a valid JSON value");
|
||||
fail_character_arr_end:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a comma or a closing bracket");
|
||||
fail_character_obj_key:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a string for object key");
|
||||
fail_character_obj_sep:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a colon after object key");
|
||||
fail_character_obj_end:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a comma or a closing brace");
|
||||
fail_comment:
|
||||
return_err(cur, INVALID_COMMENT, "unclosed multiline comment");
|
||||
fail_character:
|
||||
return_err(cur, UNEXPECTED_CHARACTER, "unexpected character");
|
||||
return_err(cur, INVALID_COMMENT,
|
||||
"unclosed multiline comment");
|
||||
fail_garbage:
|
||||
return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document");
|
||||
return_err(cur, UNEXPECTED_CONTENT,
|
||||
"unexpected content after document");
|
||||
|
||||
#undef val_incr
|
||||
#undef return_err
|
||||
@ -6330,13 +6401,13 @@ arr_val_begin:
|
||||
val_incr();
|
||||
ctn_len++;
|
||||
if (likely(read_true(&cur, val))) goto arr_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_true;
|
||||
}
|
||||
if (*cur == 'f') {
|
||||
val_incr();
|
||||
ctn_len++;
|
||||
if (likely(read_false(&cur, val))) goto arr_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_false;
|
||||
}
|
||||
if (*cur == 'n') {
|
||||
val_incr();
|
||||
@ -6345,7 +6416,7 @@ arr_val_begin:
|
||||
if (has_read_flag(ALLOW_INF_AND_NAN)) {
|
||||
if (read_nan(false, &cur, pre, val)) goto arr_val_end;
|
||||
}
|
||||
goto fail_literal;
|
||||
goto fail_literal_null;
|
||||
}
|
||||
if (*cur == ']') {
|
||||
cur++;
|
||||
@ -6363,13 +6434,13 @@ arr_val_begin:
|
||||
val_incr();
|
||||
ctn_len++;
|
||||
if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end;
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
}
|
||||
if (has_read_flag(ALLOW_COMMENTS)) {
|
||||
if (skip_spaces_and_comments(&cur)) goto arr_val_begin;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
|
||||
arr_val_end:
|
||||
if (byte_match_2(cur, ",\n")) {
|
||||
@ -6392,7 +6463,7 @@ arr_val_end:
|
||||
if (skip_spaces_and_comments(&cur)) goto arr_val_end;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_arr_end;
|
||||
|
||||
arr_end:
|
||||
/* get parent container */
|
||||
@ -6458,7 +6529,7 @@ obj_key_begin:
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_key_begin;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_obj_key;
|
||||
|
||||
obj_key_end:
|
||||
if (byte_match_2(cur, ": ")) {
|
||||
@ -6477,7 +6548,7 @@ obj_key_end:
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_key_end;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_obj_sep;
|
||||
|
||||
obj_val_begin:
|
||||
if (*cur == '"') {
|
||||
@ -6504,13 +6575,13 @@ obj_val_begin:
|
||||
val++;
|
||||
ctn_len++;
|
||||
if (likely(read_true(&cur, val))) goto obj_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_true;
|
||||
}
|
||||
if (*cur == 'f') {
|
||||
val++;
|
||||
ctn_len++;
|
||||
if (likely(read_false(&cur, val))) goto obj_val_end;
|
||||
goto fail_literal;
|
||||
goto fail_literal_false;
|
||||
}
|
||||
if (*cur == 'n') {
|
||||
val++;
|
||||
@ -6519,7 +6590,7 @@ obj_val_begin:
|
||||
if (has_read_flag(ALLOW_INF_AND_NAN)) {
|
||||
if (read_nan(false, &cur, pre, val)) goto obj_val_end;
|
||||
}
|
||||
goto fail_literal;
|
||||
goto fail_literal_null;
|
||||
}
|
||||
if (char_is_space(*cur)) {
|
||||
while (char_is_space(*++cur));
|
||||
@ -6530,13 +6601,13 @@ obj_val_begin:
|
||||
val++;
|
||||
ctn_len++;
|
||||
if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end;
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
}
|
||||
if (has_read_flag(ALLOW_COMMENTS)) {
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_val_begin;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_val;
|
||||
|
||||
obj_val_end:
|
||||
if (byte_match_2(cur, ",\n")) {
|
||||
@ -6559,7 +6630,7 @@ obj_val_end:
|
||||
if (skip_spaces_and_comments(&cur)) goto obj_val_end;
|
||||
if (byte_match_2(cur, "/*")) goto fail_comment;
|
||||
}
|
||||
goto fail_character;
|
||||
goto fail_character_obj_end;
|
||||
|
||||
obj_end:
|
||||
/* pop container */
|
||||
@ -6603,17 +6674,41 @@ fail_string:
|
||||
fail_number:
|
||||
return_err(cur, INVALID_NUMBER, msg);
|
||||
fail_alloc:
|
||||
return_err(cur, MEMORY_ALLOCATION, "memory allocation failed");
|
||||
return_err(cur, MEMORY_ALLOCATION,
|
||||
"memory allocation failed");
|
||||
fail_trailing_comma:
|
||||
return_err(cur, JSON_STRUCTURE, "trailing comma is not allowed");
|
||||
fail_literal:
|
||||
return_err(cur, LITERAL, "invalid literal");
|
||||
return_err(cur, JSON_STRUCTURE,
|
||||
"trailing comma is not allowed");
|
||||
fail_literal_true:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'true'");
|
||||
fail_literal_false:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'false'");
|
||||
fail_literal_null:
|
||||
return_err(cur, LITERAL,
|
||||
"invalid literal, expected a valid literal such as 'null'");
|
||||
fail_character_val:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a valid JSON value");
|
||||
fail_character_arr_end:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a comma or a closing bracket");
|
||||
fail_character_obj_key:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a string for object key");
|
||||
fail_character_obj_sep:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a colon after object key");
|
||||
fail_character_obj_end:
|
||||
return_err(cur, UNEXPECTED_CHARACTER,
|
||||
"unexpected character, expected a comma or a closing brace");
|
||||
fail_comment:
|
||||
return_err(cur, INVALID_COMMENT, "unclosed multiline comment");
|
||||
fail_character:
|
||||
return_err(cur, UNEXPECTED_CHARACTER, "unexpected character");
|
||||
return_err(cur, INVALID_COMMENT,
|
||||
"unclosed multiline comment");
|
||||
fail_garbage:
|
||||
return_err(cur, UNEXPECTED_CONTENT, "unexpected content after document");
|
||||
return_err(cur, UNEXPECTED_CONTENT,
|
||||
"unexpected content after document");
|
||||
|
||||
#undef val_incr
|
||||
#undef return_err
|
||||
@ -7835,7 +7930,7 @@ static const u8 esc_single_char_table[512] = {
|
||||
|
||||
/** Returns the encode table with options. */
|
||||
static_inline const char_enc_type *get_enc_table_with_flag(
|
||||
yyjson_read_flag flg) {
|
||||
yyjson_write_flag flg) {
|
||||
if (has_write_flag(ESCAPE_UNICODE)) {
|
||||
if (has_write_flag(ESCAPE_SLASHES)) {
|
||||
return enc_table_esc_slash;
|
||||
|
24
src/3rdparty/yyjson/yyjson.h
vendored
24
src/3rdparty/yyjson/yyjson.h
vendored
@ -527,16 +527,16 @@ extern "C" {
|
||||
#define YYJSON_VERSION_MAJOR 0
|
||||
|
||||
/** The minor version of yyjson. */
|
||||
#define YYJSON_VERSION_MINOR 9
|
||||
#define YYJSON_VERSION_MINOR 10
|
||||
|
||||
/** The patch version of yyjson. */
|
||||
#define YYJSON_VERSION_PATCH 0
|
||||
|
||||
/** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
|
||||
#define YYJSON_VERSION_HEX 0x000900
|
||||
#define YYJSON_VERSION_HEX 0x000A00
|
||||
|
||||
/** The version string of yyjson. */
|
||||
#define YYJSON_VERSION_STRING "0.9.0"
|
||||
#define YYJSON_VERSION_STRING "0.10.0"
|
||||
|
||||
/** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
|
||||
yyjson_api uint32_t yyjson_version(void);
|
||||
@ -841,6 +841,24 @@ typedef struct yyjson_read_err {
|
||||
size_t pos;
|
||||
} yyjson_read_err;
|
||||
|
||||
/**
|
||||
Locate the line and column number for a byte position in a string.
|
||||
This can be used to get better description for error position.
|
||||
|
||||
@param str The input string.
|
||||
@param len The byte length of the input string.
|
||||
@param pos The byte position within the input string.
|
||||
@param line A pointer to receive the line number, starting from 1.
|
||||
@param col A pointer to receive the column number, starting from 1.
|
||||
@param chr A pointer to receive the character index, starting from 0.
|
||||
@return true on success, false if `str` is NULL or `pos` is out of bounds.
|
||||
@note Line/column/character are calculated based on Unicode characters for
|
||||
compatibility with text editors. For multi-byte UTF-8 characters,
|
||||
the returned value may not directly correspond to the byte position.
|
||||
*/
|
||||
yyjson_api bool yyjson_locate_pos(const char *str, size_t len, size_t pos,
|
||||
size_t *line, size_t *col, size_t *chr);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -130,10 +130,7 @@ void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
|
||||
if(instance.config.display.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,17 +101,25 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
|
||||
|
||||
#else
|
||||
|
||||
struct stat fileStat;
|
||||
if(stat(path, &fileStat) != 0)
|
||||
return false;
|
||||
if (pathType == FF_PATHTYPE_ANY)
|
||||
{
|
||||
// Zero overhead
|
||||
return access(path, F_OK) == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stat fileStat;
|
||||
if(stat(path, &fileStat) != 0)
|
||||
return false;
|
||||
|
||||
unsigned int mode = fileStat.st_mode & S_IFMT;
|
||||
unsigned int mode = fileStat.st_mode & S_IFMT;
|
||||
|
||||
if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR)
|
||||
return true;
|
||||
if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR)
|
||||
return true;
|
||||
|
||||
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
|
||||
return true;
|
||||
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -213,10 +213,7 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
|
||||
if(instance.config.display.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -738,13 +738,6 @@
|
||||
}
|
||||
],
|
||||
"Library path": [
|
||||
{
|
||||
"long": "lib-pci",
|
||||
"desc": "Pciutils. Used for GPU output",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-vulkan",
|
||||
"desc": "Vulkan module & fallback for GPU output",
|
||||
|
@ -33,7 +33,7 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
|
||||
|
||||
//capacity must exist and be not empty
|
||||
ffStrbufAppendS(dir, "/capacity");
|
||||
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer); // This is expensive in my laptop
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if (!available)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "wayland.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
|
||||
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
{
|
||||
@ -35,6 +36,39 @@ static void waylandOutputGeometryListener(void *data,
|
||||
display->transform = (enum wl_output_transform) transform;
|
||||
}
|
||||
|
||||
static void handleXdgLogicalSize(void *data, FF_MAYBE_UNUSED struct zxdg_output_v1 *_, int32_t width, FF_MAYBE_UNUSED int32_t height)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
// Seems the values are only useful when ractional scale is enabled
|
||||
if (width < display->width)
|
||||
{
|
||||
display->scale = (double) display->width / width;
|
||||
}
|
||||
}
|
||||
|
||||
// Dirty hack for #477
|
||||
// The order of these callbacks MUST follow `struct wl_output_listener`
|
||||
static void* outputListener[] = {
|
||||
waylandOutputGeometryListener, // geometry
|
||||
waylandOutputModeListener, // mode
|
||||
stubListener, // done
|
||||
waylandOutputScaleListener, // scale
|
||||
ffWaylandOutputNameListener, // name
|
||||
ffWaylandOutputDescriptionListener, // description
|
||||
};
|
||||
static_assert(
|
||||
sizeof(outputListener) >= sizeof(struct wl_output_listener),
|
||||
"sizeof(outputListener) is too small. Please report it to fastfetch github issue"
|
||||
);
|
||||
|
||||
static struct zxdg_output_v1_listener zxdgOutputListener = {
|
||||
.logical_position = (void*) stubListener,
|
||||
.logical_size = handleXdgLogicalSize,
|
||||
.done = (void*) stubListener,
|
||||
.name = (void*) ffWaylandOutputNameListener,
|
||||
.description = (void*) ffWaylandOutputDescriptionListener,
|
||||
};
|
||||
|
||||
void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
|
||||
@ -54,23 +88,21 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
|
||||
.edidName = ffStrbufCreate(),
|
||||
};
|
||||
|
||||
// Dirty hack for #477
|
||||
// The order of these callbacks MUST follow `struct wl_output_listener`
|
||||
void* outputListener[] = {
|
||||
waylandOutputGeometryListener, // geometry
|
||||
waylandOutputModeListener, // mode
|
||||
stubListener, // done
|
||||
waylandOutputScaleListener, // scale
|
||||
ffWaylandOutputNameListener, // name
|
||||
ffWaylandOutputDescriptionListener, // description
|
||||
};
|
||||
static_assert(
|
||||
sizeof(outputListener) >= sizeof(struct wl_output_listener),
|
||||
"sizeof(outputListener) is too small. Please report it to fastfetch github issue"
|
||||
);
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
|
||||
if (wldata->zxdgOutputManager)
|
||||
{
|
||||
struct wl_proxy* zxdgOutput = wldata->ffwl_proxy_marshal_constructor_versioned(wldata->zxdgOutputManager, ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT, &zxdg_output_v1_interface, version, NULL, output);
|
||||
|
||||
if (zxdgOutput)
|
||||
{
|
||||
wldata->ffwl_proxy_add_listener(zxdgOutput, (void(**)(void)) &zxdgOutputListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
wldata->ffwl_proxy_destroy(zxdgOutput);
|
||||
}
|
||||
}
|
||||
|
||||
wldata->ffwl_proxy_destroy(output);
|
||||
|
||||
if(display.width <= 0 || display.height <= 0)
|
||||
@ -124,7 +156,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
|
||||
: &display.name,
|
||||
display.type,
|
||||
false,
|
||||
0
|
||||
display.id
|
||||
);
|
||||
|
||||
ffStrbufDestroy(&display.description);
|
||||
@ -132,4 +164,13 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
|
||||
ffStrbufDestroy(&display.edidName);
|
||||
}
|
||||
|
||||
void ffWaylandHandleZxdgOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* manager = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &zxdg_output_manager_v1_interface, version, name, zxdg_output_manager_v1_interface.name, version, NULL);
|
||||
if(manager == NULL)
|
||||
return;
|
||||
|
||||
wldata->zxdgOutputManager = manager;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,845 @@
|
||||
/* Generated by wayland-scanner 1.22.0 */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_CLIENT_PROTOCOL_H
|
||||
#define KDE_OUTPUT_DEVICE_V2_CLIENT_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <wayland-util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page page_kde_output_device_v2 The kde_output_device_v2 protocol
|
||||
* @section page_ifaces_kde_output_device_v2 Interfaces
|
||||
* - @subpage page_iface_kde_output_device_v2 - output configuration representation
|
||||
* - @subpage page_iface_kde_output_device_mode_v2 - output mode
|
||||
* @section page_copyright_kde_output_device_v2 Copyright
|
||||
* <pre>
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2008-2011 Kristian Høgsberg
|
||||
* SPDX-FileCopyrightText: 2010-2011 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2012-2013 Collabora, Ltd.
|
||||
* SPDX-FileCopyrightText: 2015 Sebastian Kügler <sebas@kde.org>
|
||||
* SPDX-FileCopyrightText: 2021 Méven Car <meven.car@enioka.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT-CMU
|
||||
* </pre>
|
||||
*/
|
||||
struct kde_output_device_mode_v2;
|
||||
struct kde_output_device_v2;
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_INTERFACE
|
||||
#define KDE_OUTPUT_DEVICE_V2_INTERFACE
|
||||
/**
|
||||
* @page page_iface_kde_output_device_v2 kde_output_device_v2
|
||||
* @section page_iface_kde_output_device_v2_desc Description
|
||||
*
|
||||
* An output device describes a display device available to the compositor.
|
||||
* output_device is similar to wl_output, but focuses on output
|
||||
* configuration management.
|
||||
*
|
||||
* A client can query all global output_device objects to enlist all
|
||||
* available display devices, even those that may currently not be
|
||||
* represented by the compositor as a wl_output.
|
||||
*
|
||||
* The client sends configuration changes to the server through the
|
||||
* outputconfiguration interface, and the server applies the configuration
|
||||
* changes to the hardware and signals changes to the output devices
|
||||
* accordingly.
|
||||
*
|
||||
* This object is published as global during start up for every available
|
||||
* display devices, or when one later becomes available, for example by
|
||||
* being hotplugged via a physical connector.
|
||||
* @section page_iface_kde_output_device_v2_api API
|
||||
* See @ref iface_kde_output_device_v2.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_kde_output_device_v2 The kde_output_device_v2 interface
|
||||
*
|
||||
* An output device describes a display device available to the compositor.
|
||||
* output_device is similar to wl_output, but focuses on output
|
||||
* configuration management.
|
||||
*
|
||||
* A client can query all global output_device objects to enlist all
|
||||
* available display devices, even those that may currently not be
|
||||
* represented by the compositor as a wl_output.
|
||||
*
|
||||
* The client sends configuration changes to the server through the
|
||||
* outputconfiguration interface, and the server applies the configuration
|
||||
* changes to the hardware and signals changes to the output devices
|
||||
* accordingly.
|
||||
*
|
||||
* This object is published as global during start up for every available
|
||||
* display devices, or when one later becomes available, for example by
|
||||
* being hotplugged via a physical connector.
|
||||
*/
|
||||
extern const struct wl_interface kde_output_device_v2_interface;
|
||||
#endif
|
||||
#ifndef KDE_OUTPUT_DEVICE_MODE_V2_INTERFACE
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_INTERFACE
|
||||
/**
|
||||
* @page page_iface_kde_output_device_mode_v2 kde_output_device_mode_v2
|
||||
* @section page_iface_kde_output_device_mode_v2_desc Description
|
||||
*
|
||||
* This object describes an output mode.
|
||||
*
|
||||
* Some heads don't support output modes, in which case modes won't be
|
||||
* advertised.
|
||||
*
|
||||
* Properties sent via this interface are applied atomically via the
|
||||
* kde_output_device.done event. No guarantees are made regarding the order
|
||||
* in which properties are sent.
|
||||
* @section page_iface_kde_output_device_mode_v2_api API
|
||||
* See @ref iface_kde_output_device_mode_v2.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_kde_output_device_mode_v2 The kde_output_device_mode_v2 interface
|
||||
*
|
||||
* This object describes an output mode.
|
||||
*
|
||||
* Some heads don't support output modes, in which case modes won't be
|
||||
* advertised.
|
||||
*
|
||||
* Properties sent via this interface are applied atomically via the
|
||||
* kde_output_device.done event. No guarantees are made regarding the order
|
||||
* in which properties are sent.
|
||||
*/
|
||||
extern const struct wl_interface kde_output_device_mode_v2_interface;
|
||||
#endif
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_SUBPIXEL_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_V2_SUBPIXEL_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* subpixel geometry information
|
||||
*
|
||||
* This enumeration describes how the physical pixels on an output are
|
||||
* laid out.
|
||||
*/
|
||||
enum kde_output_device_v2_subpixel {
|
||||
KDE_OUTPUT_DEVICE_V2_SUBPIXEL_UNKNOWN = 0,
|
||||
KDE_OUTPUT_DEVICE_V2_SUBPIXEL_NONE = 1,
|
||||
KDE_OUTPUT_DEVICE_V2_SUBPIXEL_HORIZONTAL_RGB = 2,
|
||||
KDE_OUTPUT_DEVICE_V2_SUBPIXEL_HORIZONTAL_BGR = 3,
|
||||
KDE_OUTPUT_DEVICE_V2_SUBPIXEL_VERTICAL_RGB = 4,
|
||||
KDE_OUTPUT_DEVICE_V2_SUBPIXEL_VERTICAL_BGR = 5,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_SUBPIXEL_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_TRANSFORM_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_V2_TRANSFORM_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* transform from framebuffer to output
|
||||
*
|
||||
* This describes the transform, that a compositor will apply to a
|
||||
* surface to compensate for the rotation or mirroring of an
|
||||
* output device.
|
||||
*
|
||||
* The flipped values correspond to an initial flip around a
|
||||
* vertical axis followed by rotation.
|
||||
*
|
||||
* The purpose is mainly to allow clients to render accordingly and
|
||||
* tell the compositor, so that for fullscreen surfaces, the
|
||||
* compositor is still able to scan out directly client surfaces.
|
||||
*/
|
||||
enum kde_output_device_v2_transform {
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_NORMAL = 0,
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_90 = 1,
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_180 = 2,
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_270 = 3,
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_FLIPPED = 4,
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_FLIPPED_90 = 5,
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_FLIPPED_180 = 6,
|
||||
KDE_OUTPUT_DEVICE_V2_TRANSFORM_FLIPPED_270 = 7,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_TRANSFORM_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_CAPABILITY_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* describes capabilities of the outputdevice
|
||||
*
|
||||
* Describes what capabilities this device has.
|
||||
*/
|
||||
enum kde_output_device_v2_capability {
|
||||
/**
|
||||
* if this output_device can use overscan
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_OVERSCAN = 0x1,
|
||||
/**
|
||||
* if this outputdevice supports variable refresh rate
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_VRR = 0x2,
|
||||
/**
|
||||
* if setting the rgb range is possible
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_RGB_RANGE = 0x4,
|
||||
/**
|
||||
* if this outputdevice supports high dynamic range
|
||||
* @since 3
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_HIGH_DYNAMIC_RANGE = 0x8,
|
||||
/**
|
||||
* if this outputdevice supports a wide color gamut
|
||||
* @since 3
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_WIDE_COLOR_GAMUT = 0x10,
|
||||
/**
|
||||
* if this outputdevice supports autorotation
|
||||
* @since 4
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_AUTO_ROTATE = 0x20,
|
||||
/**
|
||||
* if this outputdevice supports icc profiles
|
||||
* @since 5
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_ICC_PROFILE = 0x40,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_HIGH_DYNAMIC_RANGE_SINCE_VERSION 3
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_WIDE_COLOR_GAMUT_SINCE_VERSION 3
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_AUTO_ROTATE_SINCE_VERSION 4
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_ICC_PROFILE_SINCE_VERSION 5
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_CAPABILITY_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_VRR_POLICY_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_V2_VRR_POLICY_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* describes vrr policy
|
||||
*
|
||||
* Describes when the compositor may employ variable refresh rate
|
||||
*/
|
||||
enum kde_output_device_v2_vrr_policy {
|
||||
KDE_OUTPUT_DEVICE_V2_VRR_POLICY_NEVER = 0,
|
||||
KDE_OUTPUT_DEVICE_V2_VRR_POLICY_ALWAYS = 1,
|
||||
KDE_OUTPUT_DEVICE_V2_VRR_POLICY_AUTOMATIC = 2,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_VRR_POLICY_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_RGB_RANGE_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_V2_RGB_RANGE_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* describes RGB range policy
|
||||
*
|
||||
* Whether full or limited color range should be used
|
||||
*/
|
||||
enum kde_output_device_v2_rgb_range {
|
||||
KDE_OUTPUT_DEVICE_V2_RGB_RANGE_AUTOMATIC = 0,
|
||||
KDE_OUTPUT_DEVICE_V2_RGB_RANGE_FULL = 1,
|
||||
KDE_OUTPUT_DEVICE_V2_RGB_RANGE_LIMITED = 2,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_RGB_RANGE_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* describes when auto rotate should be used
|
||||
*/
|
||||
enum kde_output_device_v2_auto_rotate_policy {
|
||||
KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_NEVER = 0,
|
||||
KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_IN_TABLET_MODE = 1,
|
||||
KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_ALWAYS = 2,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_COLOR_PROFILE_SOURCE_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_V2_COLOR_PROFILE_SOURCE_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* which source the compositor should use for the color profile on an output
|
||||
*/
|
||||
enum kde_output_device_v2_color_profile_source {
|
||||
KDE_OUTPUT_DEVICE_V2_COLOR_PROFILE_SOURCE_SRGB = 0,
|
||||
KDE_OUTPUT_DEVICE_V2_COLOR_PROFILE_SOURCE_ICC = 1,
|
||||
KDE_OUTPUT_DEVICE_V2_COLOR_PROFILE_SOURCE_EDID = 2,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_COLOR_PROFILE_SOURCE_ENUM */
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
* @struct kde_output_device_v2_listener
|
||||
*/
|
||||
struct kde_output_device_v2_listener {
|
||||
/**
|
||||
* geometric properties of the output
|
||||
*
|
||||
* The geometry event describes geometric properties of the
|
||||
* output. The event is sent when binding to the output object and
|
||||
* whenever any of the properties change.
|
||||
* @param x x position within the global compositor space
|
||||
* @param y y position within the global compositor space
|
||||
* @param physical_width width in millimeters of the output
|
||||
* @param physical_height height in millimeters of the output
|
||||
* @param subpixel subpixel orientation of the output
|
||||
* @param make textual description of the manufacturer
|
||||
* @param model textual description of the model
|
||||
* @param transform transform that maps framebuffer to output
|
||||
*/
|
||||
void (*geometry)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t physical_width,
|
||||
int32_t physical_height,
|
||||
int32_t subpixel,
|
||||
const char *make,
|
||||
const char *model,
|
||||
int32_t transform);
|
||||
/**
|
||||
* current mode
|
||||
*
|
||||
* This event describes the mode currently in use for this head.
|
||||
* It is only sent if the output is enabled.
|
||||
*/
|
||||
void (*current_mode)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
struct kde_output_device_mode_v2 *mode);
|
||||
/**
|
||||
* advertise available output modes and current one
|
||||
*
|
||||
* The mode event describes an available mode for the output.
|
||||
*
|
||||
* When the client binds to the output_device object, the server
|
||||
* sends this event once for every available mode the output_device
|
||||
* can be operated by.
|
||||
*
|
||||
* There will always be at least one event sent out on initial
|
||||
* binding, which represents the current mode.
|
||||
*
|
||||
* Later if an output changes, its mode event is sent again for the
|
||||
* eventual added modes and lastly the current mode. In other
|
||||
* words, the current mode is always represented by the latest
|
||||
* event sent with the current flag set.
|
||||
*
|
||||
* The size of a mode is given in physical hardware units of the
|
||||
* output device. This is not necessarily the same as the output
|
||||
* size in the global compositor space. For instance, the output
|
||||
* may be scaled, as described in kde_output_device_v2.scale, or
|
||||
* transformed, as described in kde_output_device_v2.transform.
|
||||
*/
|
||||
void (*mode)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
struct kde_output_device_mode_v2 *mode);
|
||||
/**
|
||||
* sent all information about output
|
||||
*
|
||||
* This event is sent after all other properties have been sent
|
||||
* on binding to the output object as well as after any other
|
||||
* output property change have been applied later on. This allows
|
||||
* to see changes to the output properties as atomic, even if
|
||||
* multiple events successively announce them.
|
||||
*/
|
||||
void (*done)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2);
|
||||
/**
|
||||
* output scaling properties
|
||||
*
|
||||
* This event contains scaling geometry information that is not
|
||||
* in the geometry event. It may be sent after binding the output
|
||||
* object or if the output scale changes later. If it is not sent,
|
||||
* the client should assume a scale of 1.
|
||||
*
|
||||
* A scale larger than 1 means that the compositor will
|
||||
* automatically scale surface buffers by this amount when
|
||||
* rendering. This is used for high resolution displays where
|
||||
* applications rendering at the native resolution would be too
|
||||
* small to be legible.
|
||||
*
|
||||
* It is intended that scaling aware clients track the current
|
||||
* output of a surface, and if it is on a scaled output it should
|
||||
* use wl_surface.set_buffer_scale with the scale of the output.
|
||||
* That way the compositor can avoid scaling the surface, and the
|
||||
* client can supply a higher detail image.
|
||||
* @param factor scaling factor of output
|
||||
*/
|
||||
void (*scale)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
wl_fixed_t factor);
|
||||
/**
|
||||
* advertise EDID data for the output
|
||||
*
|
||||
* The edid event encapsulates the EDID data for the
|
||||
* outputdevice.
|
||||
*
|
||||
* The event is sent when binding to the output object. The EDID
|
||||
* data may be empty, in which case this event is sent anyway. If
|
||||
* the EDID information is empty, you can fall back to the name et
|
||||
* al. properties of the outputdevice.
|
||||
* @param raw base64-encoded EDID string
|
||||
*/
|
||||
void (*edid)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
const char *raw);
|
||||
/**
|
||||
* output is enabled or disabled
|
||||
*
|
||||
* The enabled event notifies whether this output is currently
|
||||
* enabled and used for displaying content by the server. The event
|
||||
* is sent when binding to the output object and whenever later on
|
||||
* an output changes its state by becoming enabled or disabled.
|
||||
* @param enabled output enabled state
|
||||
*/
|
||||
void (*enabled)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
int32_t enabled);
|
||||
/**
|
||||
* A unique id for this outputdevice
|
||||
*
|
||||
* The uuid can be used to identify the output. It's controlled
|
||||
* by the server entirely. The server should make sure the uuid is
|
||||
* persistent across restarts. An empty uuid is considered invalid.
|
||||
* @param uuid output devices ID
|
||||
*/
|
||||
void (*uuid)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
const char *uuid);
|
||||
/**
|
||||
* Serial Number
|
||||
*
|
||||
* Serial ID of the monitor, sent on startup before the first
|
||||
* done event.
|
||||
* @param serialNumber textual representation of serial number
|
||||
*/
|
||||
void (*serial_number)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
const char *serialNumber);
|
||||
/**
|
||||
* EISA ID
|
||||
*
|
||||
* EISA ID of the monitor, sent on startup before the first done
|
||||
* event.
|
||||
* @param eisaId textual representation of EISA identifier
|
||||
*/
|
||||
void (*eisa_id)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
const char *eisaId);
|
||||
/**
|
||||
* capability flags
|
||||
*
|
||||
* What capabilities this device has, sent on startup before the
|
||||
* first done event.
|
||||
*/
|
||||
void (*capabilities)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t flags);
|
||||
/**
|
||||
* overscan
|
||||
*
|
||||
* Overscan value of the monitor in percent, sent on startup
|
||||
* before the first done event.
|
||||
* @param overscan amount of overscan of the monitor
|
||||
*/
|
||||
void (*overscan)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t overscan);
|
||||
/**
|
||||
* Variable Refresh Rate Policy
|
||||
*
|
||||
* What policy the compositor will employ regarding its use of
|
||||
* variable refresh rate.
|
||||
*/
|
||||
void (*vrr_policy)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t vrr_policy);
|
||||
/**
|
||||
* RGB range
|
||||
*
|
||||
* What rgb range the compositor is using for this output
|
||||
*/
|
||||
void (*rgb_range)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t rgb_range);
|
||||
/**
|
||||
* Output's name
|
||||
*
|
||||
* Name of the output, it's useful to cross-reference to an
|
||||
* zxdg_output_v1 and ultimately QScreen
|
||||
* @since 2
|
||||
*/
|
||||
void (*name)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
const char *name);
|
||||
/**
|
||||
* if HDR is enabled
|
||||
*
|
||||
* Whether or not high dynamic range is enabled for this output
|
||||
* @param hdr_enabled 1 if enabled, 0 if disabled
|
||||
* @since 3
|
||||
*/
|
||||
void (*high_dynamic_range)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t hdr_enabled);
|
||||
/**
|
||||
* the brightness of sdr if hdr is enabled
|
||||
*
|
||||
* If high dynamic range is used, this value defines the
|
||||
* brightness in nits for content that's in standard dynamic range
|
||||
* format. Note that while the value is in nits, that doesn't
|
||||
* necessarily translate to the same brightness on the screen.
|
||||
* @since 3
|
||||
*/
|
||||
void (*sdr_brightness)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t sdr_brightness);
|
||||
/**
|
||||
* if WCG is enabled
|
||||
*
|
||||
* Whether or not the use of a wide color gamut is enabled for
|
||||
* this output
|
||||
* @param wcg_enabled 1 if enabled, 0 if disabled
|
||||
* @since 3
|
||||
*/
|
||||
void (*wide_color_gamut)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t wcg_enabled);
|
||||
/**
|
||||
* describes when auto rotate is used
|
||||
*
|
||||
*
|
||||
* @since 4
|
||||
*/
|
||||
void (*auto_rotate_policy)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t policy);
|
||||
/**
|
||||
* describes when auto rotate is used
|
||||
*
|
||||
*
|
||||
* @since 5
|
||||
*/
|
||||
void (*icc_profile_path)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
const char *profile_path);
|
||||
/**
|
||||
* metadata about the screen's brightness limits
|
||||
*
|
||||
*
|
||||
* @param max_peak_brightness in nits
|
||||
* @param max_frame_average_brightness in nits
|
||||
* @param min_brightness in 0.0001 nits
|
||||
* @since 6
|
||||
*/
|
||||
void (*brightness_metadata)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t max_peak_brightness,
|
||||
uint32_t max_frame_average_brightness,
|
||||
uint32_t min_brightness);
|
||||
/**
|
||||
* overrides for the screen's brightness limits
|
||||
*
|
||||
*
|
||||
* @param max_peak_brightness -1 for no override, positive values are the brightness in nits
|
||||
* @param max_average_brightness -1 for no override, positive values are the brightness in nits
|
||||
* @param min_brightness -1 for no override, positive values are the brightness in 0.0001 nits
|
||||
* @since 6
|
||||
*/
|
||||
void (*brightness_overrides)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
int32_t max_peak_brightness,
|
||||
int32_t max_average_brightness,
|
||||
int32_t min_brightness);
|
||||
/**
|
||||
* describes which gamut is assumed for sRGB applications
|
||||
*
|
||||
* This can be used to provide the colors users assume sRGB
|
||||
* applications should have based on the default experience on many
|
||||
* modern sRGB screens.
|
||||
* @param gamut_wideness 0 means rec.709 primaries, 10000 means native primaries
|
||||
* @since 6
|
||||
*/
|
||||
void (*sdr_gamut_wideness)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t gamut_wideness);
|
||||
/**
|
||||
* describes which source the compositor uses for the color profile on an output
|
||||
*
|
||||
*
|
||||
* @since 7
|
||||
*/
|
||||
void (*color_profile_source)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t source);
|
||||
/**
|
||||
* brightness multiplier
|
||||
*
|
||||
* This is the brightness modifier of the output. It doesn't
|
||||
* specify any absolute values, but is merely a multiplier on top
|
||||
* of other brightness values, like sdr_brightness and
|
||||
* brightness_metadata. 0 is the minimum brightness (not completely
|
||||
* dark) and 10000 is the maximum brightness. This is currently
|
||||
* only supported / meaningful while HDR is active.
|
||||
* @param brightness brightness in 0-10000
|
||||
* @since 8
|
||||
*/
|
||||
void (*brightness)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t brightness);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
static inline int
|
||||
kde_output_device_v2_add_listener(struct kde_output_device_v2 *kde_output_device_v2,
|
||||
const struct kde_output_device_v2_listener *listener, void *data)
|
||||
{
|
||||
return wl_proxy_add_listener((struct wl_proxy *) kde_output_device_v2,
|
||||
(void (**)(void)) listener, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_GEOMETRY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CURRENT_MODE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_MODE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_DONE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_SCALE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_EDID_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_ENABLED_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_UUID_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_SERIAL_NUMBER_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_EISA_ID_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITIES_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_OVERSCAN_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_VRR_POLICY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_RGB_RANGE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_NAME_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_HIGH_DYNAMIC_RANGE_SINCE_VERSION 3
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_SDR_BRIGHTNESS_SINCE_VERSION 3
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_WIDE_COLOR_GAMUT_SINCE_VERSION 3
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_AUTO_ROTATE_POLICY_SINCE_VERSION 4
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_ICC_PROFILE_PATH_SINCE_VERSION 5
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_BRIGHTNESS_METADATA_SINCE_VERSION 6
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_BRIGHTNESS_OVERRIDES_SINCE_VERSION 6
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_SDR_GAMUT_WIDENESS_SINCE_VERSION 6
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_COLOR_PROFILE_SOURCE_SINCE_VERSION 7
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_BRIGHTNESS_SINCE_VERSION 8
|
||||
|
||||
|
||||
// /** @ingroup iface_kde_output_device_v2 */
|
||||
// static inline void
|
||||
// kde_output_device_v2_set_user_data(struct kde_output_device_v2 *kde_output_device_v2, void *user_data)
|
||||
// {
|
||||
// wl_proxy_set_user_data((struct wl_proxy *) kde_output_device_v2, user_data);
|
||||
// }
|
||||
|
||||
// /** @ingroup iface_kde_output_device_v2 */
|
||||
// static inline void *
|
||||
// kde_output_device_v2_get_user_data(struct kde_output_device_v2 *kde_output_device_v2)
|
||||
// {
|
||||
// return wl_proxy_get_user_data((struct wl_proxy *) kde_output_device_v2);
|
||||
// }
|
||||
|
||||
// static inline uint32_t
|
||||
// kde_output_device_v2_get_version(struct kde_output_device_v2 *kde_output_device_v2)
|
||||
// {
|
||||
// return wl_proxy_get_version((struct wl_proxy *) kde_output_device_v2);
|
||||
// }
|
||||
|
||||
// /** @ingroup iface_kde_output_device_v2 */
|
||||
// static inline void
|
||||
// kde_output_device_v2_destroy(struct kde_output_device_v2 *kde_output_device_v2)
|
||||
// {
|
||||
// wl_proxy_destroy((struct wl_proxy *) kde_output_device_v2);
|
||||
// }
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
* @struct kde_output_device_mode_v2_listener
|
||||
*/
|
||||
struct kde_output_device_mode_v2_listener {
|
||||
/**
|
||||
* mode size
|
||||
*
|
||||
* This event describes the mode size. The size is given in
|
||||
* physical hardware units of the output device. This is not
|
||||
* necessarily the same as the output size in the global compositor
|
||||
* space. For instance, the output may be scaled or transformed.
|
||||
* @param width width of the mode in hardware units
|
||||
* @param height height of the mode in hardware units
|
||||
*/
|
||||
void (*size)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2,
|
||||
int32_t width,
|
||||
int32_t height);
|
||||
/**
|
||||
* mode refresh rate
|
||||
*
|
||||
* This event describes the mode's fixed vertical refresh rate.
|
||||
* It is only sent if the mode has a fixed refresh rate.
|
||||
* @param refresh vertical refresh rate in mHz
|
||||
*/
|
||||
void (*refresh)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2,
|
||||
int32_t refresh);
|
||||
/**
|
||||
* mode is preferred
|
||||
*
|
||||
* This event advertises this mode as preferred.
|
||||
*/
|
||||
void (*preferred)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2);
|
||||
/**
|
||||
* the mode has been destroyed
|
||||
*
|
||||
* The compositor will destroy the object immediately after
|
||||
* sending this event, so it will become invalid and the client
|
||||
* should release any resources associated with it.
|
||||
*/
|
||||
void (*removed)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
static inline int
|
||||
kde_output_device_mode_v2_add_listener(struct kde_output_device_mode_v2 *kde_output_device_mode_v2,
|
||||
const struct kde_output_device_mode_v2_listener *listener, void *data)
|
||||
{
|
||||
return wl_proxy_add_listener((struct wl_proxy *) kde_output_device_mode_v2,
|
||||
(void (**)(void)) listener, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_SIZE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_REFRESH_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_PREFERRED_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_REMOVED_SINCE_VERSION 1
|
||||
|
||||
|
||||
// /** @ingroup iface_kde_output_device_mode_v2 */
|
||||
// static inline void
|
||||
// kde_output_device_mode_v2_set_user_data(struct kde_output_device_mode_v2 *kde_output_device_mode_v2, void *user_data)
|
||||
// {
|
||||
// wl_proxy_set_user_data((struct wl_proxy *) kde_output_device_mode_v2, user_data);
|
||||
// }
|
||||
|
||||
// /** @ingroup iface_kde_output_device_mode_v2 */
|
||||
// static inline void *
|
||||
// kde_output_device_mode_v2_get_user_data(struct kde_output_device_mode_v2 *kde_output_device_mode_v2)
|
||||
// {
|
||||
// return wl_proxy_get_user_data((struct wl_proxy *) kde_output_device_mode_v2);
|
||||
// }
|
||||
|
||||
// static inline uint32_t
|
||||
// kde_output_device_mode_v2_get_version(struct kde_output_device_mode_v2 *kde_output_device_mode_v2)
|
||||
// {
|
||||
// return wl_proxy_get_version((struct wl_proxy *) kde_output_device_mode_v2);
|
||||
// }
|
||||
|
||||
// /** @ingroup iface_kde_output_device_mode_v2 */
|
||||
// static inline void
|
||||
// kde_output_device_mode_v2_destroy(struct kde_output_device_mode_v2 *kde_output_device_mode_v2)
|
||||
// {
|
||||
// wl_proxy_destroy((struct wl_proxy *) kde_output_device_mode_v2);
|
||||
// }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,81 @@
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
/* Generated by wayland-scanner 1.22.0 */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2008-2011 Kristian Høgsberg
|
||||
* SPDX-FileCopyrightText: 2010-2011 Intel Corporation
|
||||
* SPDX-FileCopyrightText: 2012-2013 Collabora, Ltd.
|
||||
* SPDX-FileCopyrightText: 2015 Sebastian Kügler <sebas@kde.org>
|
||||
* SPDX-FileCopyrightText: 2021 Méven Car <meven.car@enioka.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT-CMU
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <wayland-util.h>
|
||||
|
||||
extern const struct wl_interface kde_output_device_mode_v2_interface;
|
||||
|
||||
static const struct wl_interface *kde_output_device_v2_types[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&kde_output_device_mode_v2_interface,
|
||||
&kde_output_device_mode_v2_interface,
|
||||
};
|
||||
|
||||
static const struct wl_message kde_output_device_v2_events[] = {
|
||||
{ "geometry", "iiiiissi", kde_output_device_v2_types + 0 },
|
||||
{ "current_mode", "o", kde_output_device_v2_types + 8 },
|
||||
{ "mode", "n", kde_output_device_v2_types + 9 },
|
||||
{ "done", "", kde_output_device_v2_types + 0 },
|
||||
{ "scale", "f", kde_output_device_v2_types + 0 },
|
||||
{ "edid", "s", kde_output_device_v2_types + 0 },
|
||||
{ "enabled", "i", kde_output_device_v2_types + 0 },
|
||||
{ "uuid", "s", kde_output_device_v2_types + 0 },
|
||||
{ "serial_number", "s", kde_output_device_v2_types + 0 },
|
||||
{ "eisa_id", "s", kde_output_device_v2_types + 0 },
|
||||
{ "capabilities", "u", kde_output_device_v2_types + 0 },
|
||||
{ "overscan", "u", kde_output_device_v2_types + 0 },
|
||||
{ "vrr_policy", "u", kde_output_device_v2_types + 0 },
|
||||
{ "rgb_range", "u", kde_output_device_v2_types + 0 },
|
||||
{ "name", "2s", kde_output_device_v2_types + 0 },
|
||||
{ "high_dynamic_range", "3u", kde_output_device_v2_types + 0 },
|
||||
{ "sdr_brightness", "3u", kde_output_device_v2_types + 0 },
|
||||
{ "wide_color_gamut", "3u", kde_output_device_v2_types + 0 },
|
||||
{ "auto_rotate_policy", "4u", kde_output_device_v2_types + 0 },
|
||||
{ "icc_profile_path", "5s", kde_output_device_v2_types + 0 },
|
||||
{ "brightness_metadata", "6uuu", kde_output_device_v2_types + 0 },
|
||||
{ "brightness_overrides", "6iii", kde_output_device_v2_types + 0 },
|
||||
{ "sdr_gamut_wideness", "6u", kde_output_device_v2_types + 0 },
|
||||
{ "color_profile_source", "7u", kde_output_device_v2_types + 0 },
|
||||
{ "brightness", "8u", kde_output_device_v2_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface kde_output_device_v2_interface = {
|
||||
"kde_output_device_v2", 8,
|
||||
0, NULL,
|
||||
25, kde_output_device_v2_events,
|
||||
};
|
||||
|
||||
static const struct wl_message kde_output_device_mode_v2_events[] = {
|
||||
{ "size", "ii", kde_output_device_v2_types + 0 },
|
||||
{ "refresh", "i", kde_output_device_v2_types + 0 },
|
||||
{ "preferred", "", kde_output_device_v2_types + 0 },
|
||||
{ "removed", "", kde_output_device_v2_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface kde_output_device_mode_v2_interface = {
|
||||
"kde_output_device_mode_v2", 1,
|
||||
0, NULL,
|
||||
4, kde_output_device_mode_v2_events,
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,133 @@
|
||||
/* Generated by wayland-scanner 1.22.0 */
|
||||
|
||||
#ifndef KDE_OUTPUT_ORDER_V1_CLIENT_PROTOCOL_H
|
||||
#define KDE_OUTPUT_ORDER_V1_CLIENT_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "wayland-client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page page_kde_output_order_v1 The kde_output_order_v1 protocol
|
||||
* @section page_ifaces_kde_output_order_v1 Interfaces
|
||||
* - @subpage page_iface_kde_output_order_v1 - announce order of outputs
|
||||
* @section page_copyright_kde_output_order_v1 Copyright
|
||||
* <pre>
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT-CMU
|
||||
* </pre>
|
||||
*/
|
||||
struct kde_output_order_v1;
|
||||
|
||||
#ifndef KDE_OUTPUT_ORDER_V1_INTERFACE
|
||||
#define KDE_OUTPUT_ORDER_V1_INTERFACE
|
||||
/**
|
||||
* @page page_iface_kde_output_order_v1 kde_output_order_v1
|
||||
* @section page_iface_kde_output_order_v1_desc Description
|
||||
*
|
||||
* Announce the order in which desktop environment components should be placed on outputs.
|
||||
* The compositor will send the list of outputs when the global is bound and whenever there is a change.
|
||||
* @section page_iface_kde_output_order_v1_api API
|
||||
* See @ref iface_kde_output_order_v1.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_kde_output_order_v1 The kde_output_order_v1 interface
|
||||
*
|
||||
* Announce the order in which desktop environment components should be placed on outputs.
|
||||
* The compositor will send the list of outputs when the global is bound and whenever there is a change.
|
||||
*/
|
||||
extern const struct wl_interface kde_output_order_v1_interface;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_order_v1
|
||||
* @struct kde_output_order_v1_listener
|
||||
*/
|
||||
struct kde_output_order_v1_listener {
|
||||
/**
|
||||
* output name
|
||||
*
|
||||
* Specifies the output identified by their wl_output.name.
|
||||
* @param output_name the name of the output
|
||||
*/
|
||||
void (*output)(void *data,
|
||||
struct kde_output_order_v1 *kde_output_order_v1,
|
||||
const char *output_name);
|
||||
/**
|
||||
* done
|
||||
*
|
||||
* Specifies that the output list is complete. On the next output
|
||||
* event, a new list begins.
|
||||
*/
|
||||
void (*done)(void *data,
|
||||
struct kde_output_order_v1 *kde_output_order_v1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_order_v1
|
||||
*/
|
||||
static inline int
|
||||
kde_output_order_v1_add_listener(struct kde_output_order_v1 *kde_output_order_v1,
|
||||
const struct kde_output_order_v1_listener *listener, void *data)
|
||||
{
|
||||
return wl_proxy_add_listener((struct wl_proxy *) kde_output_order_v1,
|
||||
(void (**)(void)) listener, data);
|
||||
}
|
||||
|
||||
#define KDE_OUTPUT_ORDER_V1_DESTROY 0
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_order_v1
|
||||
*/
|
||||
#define KDE_OUTPUT_ORDER_V1_OUTPUT_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_order_v1
|
||||
*/
|
||||
#define KDE_OUTPUT_ORDER_V1_DONE_SINCE_VERSION 1
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_order_v1
|
||||
*/
|
||||
#define KDE_OUTPUT_ORDER_V1_DESTROY_SINCE_VERSION 1
|
||||
|
||||
// /** @ingroup iface_kde_output_order_v1 */
|
||||
// static inline void
|
||||
// kde_output_order_v1_set_user_data(struct kde_output_order_v1 *kde_output_order_v1, void *user_data)
|
||||
// {
|
||||
// wl_proxy_set_user_data((struct wl_proxy *) kde_output_order_v1, user_data);
|
||||
// }
|
||||
|
||||
// /** @ingroup iface_kde_output_order_v1 */
|
||||
// static inline void *
|
||||
// kde_output_order_v1_get_user_data(struct kde_output_order_v1 *kde_output_order_v1)
|
||||
// {
|
||||
// return wl_proxy_get_user_data((struct wl_proxy *) kde_output_order_v1);
|
||||
// }
|
||||
|
||||
// static inline uint32_t
|
||||
// kde_output_order_v1_get_version(struct kde_output_order_v1 *kde_output_order_v1)
|
||||
// {
|
||||
// return wl_proxy_get_version((struct wl_proxy *) kde_output_order_v1);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @ingroup iface_kde_output_order_v1
|
||||
// */
|
||||
// static inline void
|
||||
// kde_output_order_v1_destroy(struct kde_output_order_v1 *kde_output_order_v1)
|
||||
// {
|
||||
// wl_proxy_marshal_flags((struct wl_proxy *) kde_output_order_v1,
|
||||
// KDE_OUTPUT_ORDER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) kde_output_order_v1), WL_MARSHAL_FLAG_DESTROY);
|
||||
// }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,35 @@
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
/* Generated by wayland-scanner 1.22.0 */
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT-CMU
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
||||
|
||||
static const struct wl_interface *kde_output_order_v1_types[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct wl_message kde_output_order_v1_requests[] = {
|
||||
{ "destroy", "", kde_output_order_v1_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message kde_output_order_v1_events[] = {
|
||||
{ "output", "s", kde_output_order_v1_types + 0 },
|
||||
{ "done", "", kde_output_order_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface kde_output_order_v1_interface = {
|
||||
"kde_output_order_v1", 1,
|
||||
1, kde_output_order_v1_requests,
|
||||
2, kde_output_order_v1_events,
|
||||
};
|
||||
|
||||
#endif
|
250
src/detection/displayserver/linux/wayland/kde-output.c
Normal file
250
src/detection/displayserver/linux/wayland/kde-output.c
Normal file
@ -0,0 +1,250 @@
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
|
||||
#include "wayland.h"
|
||||
#include "kde-output-device-v2-client-protocol.h"
|
||||
#include "kde-output-order-v1-client-protocol.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "util/base64.h"
|
||||
|
||||
typedef struct WaylandKdeMode
|
||||
{
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t refreshRate;
|
||||
struct kde_output_device_mode_v2* pMode;
|
||||
} WaylandKdeMode;
|
||||
|
||||
static void waylandKdeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height)
|
||||
{
|
||||
WaylandKdeMode* mode = (WaylandKdeMode*) data;
|
||||
mode->width = width;
|
||||
mode->height = height;
|
||||
}
|
||||
|
||||
static void waylandKdeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate)
|
||||
{
|
||||
WaylandKdeMode* mode = (WaylandKdeMode*) data;
|
||||
mode->refreshRate = rate;
|
||||
}
|
||||
|
||||
static const struct kde_output_device_mode_v2_listener modeListener = {
|
||||
.size = waylandKdeSizeListener,
|
||||
.refresh = waylandKdeRefreshListener,
|
||||
.preferred = (void*) stubListener,
|
||||
.removed = (void*) stubListener,
|
||||
};
|
||||
|
||||
static void waylandKdeModeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, struct kde_output_device_mode_v2 *mode)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
if (!wldata->internal) return;
|
||||
|
||||
WaylandKdeMode* newMode = ffListAdd((FFlist*) wldata->internal);
|
||||
newMode->pMode = mode;
|
||||
|
||||
// Strangely, the listener is called only in this function, but not in `waylandKdeCurrentModeListener`
|
||||
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode);
|
||||
}
|
||||
|
||||
static void waylandKdeCurrentModeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2 *_, struct kde_output_device_mode_v2 *mode)
|
||||
{
|
||||
// waylandKdeModeListener is always run before this
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
if (!wldata->internal) return;
|
||||
|
||||
WaylandKdeMode* current = NULL;
|
||||
FF_LIST_FOR_EACH(WaylandKdeMode, m, *(FFlist*) wldata->internal)
|
||||
{
|
||||
if (m->pMode == mode)
|
||||
{
|
||||
current = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
wldata->width = current->width;
|
||||
wldata->height = current->height;
|
||||
wldata->refreshRate = current->refreshRate;
|
||||
}
|
||||
|
||||
static void waylandKdeScaleListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, wl_fixed_t scale)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
wldata->scale = wl_fixed_to_double(scale);
|
||||
}
|
||||
|
||||
static void waylandKdeEdidListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, const char* raw)
|
||||
{
|
||||
if (!*raw) return;
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
FF_STRBUF_AUTO_DESTROY b64 = ffStrbufCreateStatic(raw);
|
||||
FF_STRBUF_AUTO_DESTROY edid = ffBase64DecodeStrbuf(&b64);
|
||||
if (edid.length < 128) return;
|
||||
ffEdidGetName((const uint8_t*) edid.chars, &wldata->edidName);
|
||||
}
|
||||
|
||||
static void waylandKdeEnabledListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, int32_t enabled)
|
||||
{
|
||||
WaylandDisplay* wldata = (WaylandDisplay*) data;
|
||||
if (!enabled) wldata->internal = NULL;
|
||||
}
|
||||
|
||||
static void waylandKdeGeometryListener(void *data,
|
||||
FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2,
|
||||
FF_MAYBE_UNUSED int32_t x,
|
||||
FF_MAYBE_UNUSED int32_t y,
|
||||
FF_MAYBE_UNUSED int32_t physical_width,
|
||||
FF_MAYBE_UNUSED int32_t physical_height,
|
||||
FF_MAYBE_UNUSED int32_t subpixel,
|
||||
FF_MAYBE_UNUSED const char *make,
|
||||
FF_MAYBE_UNUSED const char *model,
|
||||
int32_t transform)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
display->transform = (enum wl_output_transform) transform;
|
||||
}
|
||||
|
||||
void waylandOutputNameListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* output, const char *name)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
if(ffStrStartsWith(name, "eDP-"))
|
||||
display->type = FF_DISPLAY_TYPE_BUILTIN;
|
||||
else if(ffStrStartsWith(name, "HDMI-"))
|
||||
display->type = FF_DISPLAY_TYPE_EXTERNAL;
|
||||
strncpy((char*) &display->id, name, sizeof(display->id));
|
||||
ffStrbufAppendS(&display->name, name);
|
||||
}
|
||||
|
||||
static struct kde_output_device_v2_listener outputListener = {
|
||||
.geometry = waylandKdeGeometryListener,
|
||||
.current_mode = waylandKdeCurrentModeListener,
|
||||
.mode = waylandKdeModeListener,
|
||||
.done = (void*) stubListener,
|
||||
.scale = waylandKdeScaleListener,
|
||||
.edid = waylandKdeEdidListener,
|
||||
.enabled = waylandKdeEnabledListener,
|
||||
.uuid = (void*) stubListener,
|
||||
.serial_number = (void*) stubListener,
|
||||
.eisa_id = (void*) stubListener,
|
||||
.capabilities = (void*) stubListener,
|
||||
.overscan = (void*) stubListener,
|
||||
.vrr_policy = (void*) stubListener,
|
||||
.rgb_range = (void*) stubListener,
|
||||
.name = waylandOutputNameListener,
|
||||
.high_dynamic_range = (void*) stubListener,
|
||||
.sdr_brightness = (void*) stubListener,
|
||||
.wide_color_gamut = (void*) stubListener,
|
||||
.auto_rotate_policy = (void*) stubListener,
|
||||
.icc_profile_path = (void*) stubListener,
|
||||
.brightness_metadata = (void*) stubListener,
|
||||
.brightness_overrides = (void*) stubListener,
|
||||
.sdr_gamut_wideness = (void*) stubListener,
|
||||
.color_profile_source = (void*) stubListener,
|
||||
.brightness = (void*) stubListener,
|
||||
};
|
||||
|
||||
void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_v2_interface, version, name, kde_output_device_v2_interface.name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandKdeMode));
|
||||
WaylandDisplay display = {
|
||||
.parent = wldata,
|
||||
.width = 0,
|
||||
.height = 0,
|
||||
.refreshRate = 0,
|
||||
.scale = 1,
|
||||
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
.type = FF_DISPLAY_TYPE_UNKNOWN,
|
||||
.name = ffStrbufCreate(),
|
||||
.description = ffStrbufCreate(),
|
||||
.edidName = ffStrbufCreate(),
|
||||
.internal = &modes,
|
||||
};
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
wldata->ffwl_proxy_destroy(output);
|
||||
|
||||
if(display.width <= 0 || display.height <= 0 || !display.internal)
|
||||
return;
|
||||
|
||||
uint32_t rotation;
|
||||
switch(display.transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
rotation = 90;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
rotation = 180;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
rotation = 270;
|
||||
break;
|
||||
default:
|
||||
rotation = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(rotation)
|
||||
{
|
||||
case 90:
|
||||
case 270: {
|
||||
int32_t temp = display.width;
|
||||
display.width = display.height;
|
||||
display.height = temp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ffdsAppendDisplay(wldata->result,
|
||||
(uint32_t) display.width,
|
||||
(uint32_t) display.height,
|
||||
display.refreshRate / 1000.0,
|
||||
(uint32_t) (display.width / display.scale),
|
||||
(uint32_t) (display.height / display.scale),
|
||||
rotation,
|
||||
display.edidName.length
|
||||
? &display.edidName
|
||||
: &display.name,
|
||||
display.type,
|
||||
false,
|
||||
display.id
|
||||
);
|
||||
|
||||
ffStrbufDestroy(&display.description);
|
||||
ffStrbufDestroy(&display.name);
|
||||
ffStrbufDestroy(&display.edidName);
|
||||
}
|
||||
|
||||
|
||||
static void waylandKdeOutputOrderListener(void *data, FF_MAYBE_UNUSED struct kde_output_order_v1 *_, const char *output_name)
|
||||
{
|
||||
uint64_t* id = (uint64_t*) data;
|
||||
if (*id == 0)
|
||||
*id = ffWaylandGenerateIdFromName(output_name);
|
||||
}
|
||||
|
||||
void ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
{
|
||||
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_order_v1_interface, version, name, kde_output_order_v1_interface.name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
struct kde_output_order_v1_listener orderListener = {
|
||||
.output = waylandKdeOutputOrderListener,
|
||||
.done = (void*) stubListener,
|
||||
};
|
||||
|
||||
wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &orderListener, &wldata->primaryDisplayId);
|
||||
wldata->ffwl_display_roundtrip(wldata->display);
|
||||
wldata->ffwl_proxy_destroy(output);
|
||||
}
|
||||
|
||||
#endif
|
@ -9,27 +9,34 @@
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "common/properties.h"
|
||||
|
||||
#include "wayland.h"
|
||||
#include "wlr-output-management-unstable-v1-client-protocol.h"
|
||||
#include "kde-output-device-v2-client-protocol.h"
|
||||
#include "kde-output-order-v1-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
#ifdef __linux__
|
||||
static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
struct ucred ucred;
|
||||
socklen_t len = sizeof(struct ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
|
||||
return;
|
||||
return false;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate();
|
||||
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
|
||||
ffReadFileBuffer(procPath.chars, &result->wmProcessName);
|
||||
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
|
||||
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_UNUSED(fd, result);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -47,6 +54,19 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
|
||||
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_ZWLR;
|
||||
ffWaylandHandleZwlrOutput(wldata, registry, name, version);
|
||||
}
|
||||
else if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_KDE) && ffStrEquals(interface, kde_output_device_v2_interface.name))
|
||||
{
|
||||
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE;
|
||||
ffWaylandHandleKdeOutput(wldata, registry, name, version);
|
||||
}
|
||||
else if(ffStrEquals(interface, kde_output_order_v1_interface.name))
|
||||
{
|
||||
ffWaylandHandleKdeOutputOrder(wldata, registry, name, version);
|
||||
}
|
||||
else if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, zxdg_output_manager_v1_interface.name))
|
||||
{
|
||||
ffWaylandHandleZxdgOutput(wldata, registry, name, version);
|
||||
}
|
||||
}
|
||||
|
||||
bool detectWayland(FFDisplayServerResult* result)
|
||||
@ -90,9 +110,85 @@ bool detectWayland(FFDisplayServerResult* result)
|
||||
data.ffwl_proxy_add_listener(registry, (void(**)(void)) ®istry_listener, &data);
|
||||
data.ffwl_display_roundtrip(data.display);
|
||||
|
||||
if (data.zxdgOutputManager)
|
||||
data.ffwl_proxy_destroy(data.zxdgOutputManager);
|
||||
|
||||
data.ffwl_proxy_destroy(registry);
|
||||
ffwl_display_disconnect(data.display);
|
||||
|
||||
if(data.primaryDisplayId == 0 && result->wmProcessName.length > 0)
|
||||
{
|
||||
const char* fileName = ffStrbufEqualS(&result->wmProcessName, "gnome-shell")
|
||||
? "monitors.xml"
|
||||
: ffStrbufEqualS(&result->wmProcessName, "cinnamon")
|
||||
? "cinnamon-monitors.xml"
|
||||
: NULL;
|
||||
if (fileName)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY monitorsXml = ffStrbufCreate();
|
||||
FF_LIST_FOR_EACH(FFstrbuf, basePath, instance.state.platform.configDirs)
|
||||
{
|
||||
char path[1024];
|
||||
snprintf(path, sizeof(path) - 1, "%s%s", basePath->chars, fileName);
|
||||
if (ffReadFileBuffer(path, &monitorsXml))
|
||||
break;
|
||||
}
|
||||
if (monitorsXml.length)
|
||||
{
|
||||
// <monitors version="2">
|
||||
// <configuration>
|
||||
// <logicalmonitor>
|
||||
// <x>0</x>
|
||||
// <y>0</y>
|
||||
// <scale>1.7489879131317139</scale>
|
||||
// <primary>yes</primary>
|
||||
// <monitor>
|
||||
// <monitorspec>
|
||||
// <connector>Virtual-1</connector>
|
||||
// <vendor>unknown</vendor>
|
||||
// <product>unknown</product>
|
||||
// <serial>unknown</serial>
|
||||
// </monitorspec>
|
||||
// <mode>
|
||||
// <width>3456</width>
|
||||
// <height>2160</height>
|
||||
// <rate>60.000068664550781</rate>
|
||||
// </mode>
|
||||
// </monitor>
|
||||
// </logicalmonitor>
|
||||
// </configuration>
|
||||
// </monitors>
|
||||
uint32_t start = ffStrbufFirstIndexS(&monitorsXml, "<primary>yes</primary>");
|
||||
if (start < monitorsXml.length)
|
||||
{
|
||||
start = ffStrbufNextIndexS(&monitorsXml, start, "<connector>");
|
||||
if (start < monitorsXml.length)
|
||||
{
|
||||
uint32_t end = ffStrbufNextIndexS(&monitorsXml, start, "</connector>");
|
||||
if (end < monitorsXml.length)
|
||||
{
|
||||
ffStrbufSubstrBefore(&monitorsXml, end);
|
||||
const char* name = monitorsXml.chars + start + strlen("<connector>");
|
||||
data.primaryDisplayId = ffWaylandGenerateIdFromName(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(data.primaryDisplayId)
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFDisplayResult, d, data.result->displays)
|
||||
{
|
||||
if(d->id == data.primaryDisplayId)
|
||||
{
|
||||
d->primary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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.
|
||||
@ -103,17 +199,23 @@ bool detectWayland(FFDisplayServerResult* result)
|
||||
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
if (display->id) return;
|
||||
|
||||
if(ffStrStartsWith(name, "eDP-"))
|
||||
display->type = FF_DISPLAY_TYPE_BUILTIN;
|
||||
else if(ffStrStartsWith(name, "HDMI-"))
|
||||
display->type = FF_DISPLAY_TYPE_EXTERNAL;
|
||||
ffdsMatchDrmConnector(name, &display->edidName);
|
||||
if (!display->edidName.length)
|
||||
ffdsMatchDrmConnector(name, &display->edidName);
|
||||
display->id = ffWaylandGenerateIdFromName(name);
|
||||
ffStrbufAppendS(&display->name, name);
|
||||
}
|
||||
|
||||
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description)
|
||||
{
|
||||
WaylandDisplay* display = data;
|
||||
if (display->description.length) return;
|
||||
|
||||
while (*description == ' ') ++description;
|
||||
if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)"))
|
||||
ffStrbufAppendS(&display->description, description);
|
||||
|
@ -14,6 +14,7 @@ typedef enum WaylandProtocolType
|
||||
FF_WAYLAND_PROTOCOL_TYPE_NONE,
|
||||
FF_WAYLAND_PROTOCOL_TYPE_GLOBAL,
|
||||
FF_WAYLAND_PROTOCOL_TYPE_ZWLR,
|
||||
FF_WAYLAND_PROTOCOL_TYPE_KDE,
|
||||
} WaylandProtocolType;
|
||||
|
||||
typedef struct WaylandData
|
||||
@ -26,6 +27,8 @@ typedef struct WaylandData
|
||||
struct wl_display* display;
|
||||
const struct wl_interface* ffwl_output_interface;
|
||||
WaylandProtocolType protocolType;
|
||||
uint64_t primaryDisplayId;
|
||||
struct wl_proxy* zxdgOutputManager;
|
||||
} WaylandData;
|
||||
|
||||
typedef struct WaylandDisplay
|
||||
@ -40,6 +43,7 @@ typedef struct WaylandDisplay
|
||||
FFstrbuf name;
|
||||
FFstrbuf description;
|
||||
FFstrbuf edidName;
|
||||
uint64_t id;
|
||||
void* internal;
|
||||
} WaylandDisplay;
|
||||
|
||||
@ -48,10 +52,24 @@ inline static void stubListener(void* data, ...)
|
||||
(void) data;
|
||||
}
|
||||
|
||||
inline static uint64_t ffWaylandGenerateIdFromName(const char* name)
|
||||
{
|
||||
uint64_t id = 0;
|
||||
size_t len = strlen(name);
|
||||
if (len > sizeof(id))
|
||||
memcpy(&id, name + (len - sizeof(id)), sizeof(id)); // copy the last 8 bytes
|
||||
else if (len > 0)
|
||||
memcpy(&id, name, len);
|
||||
return id;
|
||||
}
|
||||
|
||||
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name);
|
||||
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description);
|
||||
|
||||
void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
|
||||
void ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
|
||||
void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
|
||||
void ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
|
||||
void ffWaylandHandleZxdgOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,414 @@
|
||||
/* Generated by wayland-scanner 1.22.0 */
|
||||
|
||||
#ifndef XDG_OUTPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H
|
||||
#define XDG_OUTPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <wayland-client.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page page_xdg_output_unstable_v1 The xdg_output_unstable_v1 protocol
|
||||
* Protocol to describe output regions
|
||||
*
|
||||
* @section page_desc_xdg_output_unstable_v1 Description
|
||||
*
|
||||
* This protocol aims at describing outputs in a way which is more in line
|
||||
* with the concept of an output on desktop oriented systems.
|
||||
*
|
||||
* Some information are more specific to the concept of an output for
|
||||
* a desktop oriented system and may not make sense in other applications,
|
||||
* such as IVI systems for example.
|
||||
*
|
||||
* Typically, the global compositor space on a desktop system is made of
|
||||
* a contiguous or overlapping set of rectangular regions.
|
||||
*
|
||||
* The logical_position and logical_size events defined in this protocol
|
||||
* might provide information identical to their counterparts already
|
||||
* available from wl_output, in which case the information provided by this
|
||||
* protocol should be preferred to their equivalent in wl_output. The goal is
|
||||
* to move the desktop specific concepts (such as output location within the
|
||||
* global compositor space, etc.) out of the core wl_output protocol.
|
||||
*
|
||||
* Warning! The protocol described in this file is experimental and
|
||||
* backward incompatible changes may be made. Backward compatible
|
||||
* changes may be added together with the corresponding interface
|
||||
* version bump.
|
||||
* Backward incompatible changes are done by bumping the version
|
||||
* number in the protocol and interface names and resetting the
|
||||
* interface version. Once the protocol is to be declared stable,
|
||||
* the 'z' prefix and the version number in the protocol and
|
||||
* interface names are removed and the interface version number is
|
||||
* reset.
|
||||
*
|
||||
* @section page_ifaces_xdg_output_unstable_v1 Interfaces
|
||||
* - @subpage page_iface_zxdg_output_manager_v1 - manage xdg_output objects
|
||||
* - @subpage page_iface_zxdg_output_v1 - compositor logical output region
|
||||
* @section page_copyright_xdg_output_unstable_v1 Copyright
|
||||
* <pre>
|
||||
*
|
||||
* Copyright © 2017 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
* </pre>
|
||||
*/
|
||||
struct wl_output;
|
||||
struct zxdg_output_manager_v1;
|
||||
struct zxdg_output_v1;
|
||||
|
||||
#ifndef ZXDG_OUTPUT_MANAGER_V1_INTERFACE
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_INTERFACE
|
||||
/**
|
||||
* @page page_iface_zxdg_output_manager_v1 zxdg_output_manager_v1
|
||||
* @section page_iface_zxdg_output_manager_v1_desc Description
|
||||
*
|
||||
* A global factory interface for xdg_output objects.
|
||||
* @section page_iface_zxdg_output_manager_v1_api API
|
||||
* See @ref iface_zxdg_output_manager_v1.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_zxdg_output_manager_v1 The zxdg_output_manager_v1 interface
|
||||
*
|
||||
* A global factory interface for xdg_output objects.
|
||||
*/
|
||||
extern const struct wl_interface zxdg_output_manager_v1_interface;
|
||||
#endif
|
||||
#ifndef ZXDG_OUTPUT_V1_INTERFACE
|
||||
#define ZXDG_OUTPUT_V1_INTERFACE
|
||||
/**
|
||||
* @page page_iface_zxdg_output_v1 zxdg_output_v1
|
||||
* @section page_iface_zxdg_output_v1_desc Description
|
||||
*
|
||||
* An xdg_output describes part of the compositor geometry.
|
||||
*
|
||||
* This typically corresponds to a monitor that displays part of the
|
||||
* compositor space.
|
||||
*
|
||||
* For objects version 3 onwards, after all xdg_output properties have been
|
||||
* sent (when the object is created and when properties are updated), a
|
||||
* wl_output.done event is sent. This allows changes to the output
|
||||
* properties to be seen as atomic, even if they happen via multiple events.
|
||||
* @section page_iface_zxdg_output_v1_api API
|
||||
* See @ref iface_zxdg_output_v1.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_zxdg_output_v1 The zxdg_output_v1 interface
|
||||
*
|
||||
* An xdg_output describes part of the compositor geometry.
|
||||
*
|
||||
* This typically corresponds to a monitor that displays part of the
|
||||
* compositor space.
|
||||
*
|
||||
* For objects version 3 onwards, after all xdg_output properties have been
|
||||
* sent (when the object is created and when properties are updated), a
|
||||
* wl_output.done event is sent. This allows changes to the output
|
||||
* properties to be seen as atomic, even if they happen via multiple events.
|
||||
*/
|
||||
extern const struct wl_interface zxdg_output_v1_interface;
|
||||
#endif
|
||||
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_DESTROY 0
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT 1
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_manager_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_DESTROY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_manager_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT_SINCE_VERSION 1
|
||||
|
||||
// /** @ingroup iface_zxdg_output_manager_v1 */
|
||||
// static inline void
|
||||
// zxdg_output_manager_v1_set_user_data(struct zxdg_output_manager_v1 *zxdg_output_manager_v1, void *user_data)
|
||||
// {
|
||||
// wl_proxy_set_user_data((struct wl_proxy *) zxdg_output_manager_v1, user_data);
|
||||
// }
|
||||
|
||||
// /** @ingroup iface_zxdg_output_manager_v1 */
|
||||
// static inline void *
|
||||
// zxdg_output_manager_v1_get_user_data(struct zxdg_output_manager_v1 *zxdg_output_manager_v1)
|
||||
// {
|
||||
// return wl_proxy_get_user_data((struct wl_proxy *) zxdg_output_manager_v1);
|
||||
// }
|
||||
|
||||
// static inline uint32_t
|
||||
// zxdg_output_manager_v1_get_version(struct zxdg_output_manager_v1 *zxdg_output_manager_v1)
|
||||
// {
|
||||
// return wl_proxy_get_version((struct wl_proxy *) zxdg_output_manager_v1);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @ingroup iface_zxdg_output_manager_v1
|
||||
// *
|
||||
// * Using this request a client can tell the server that it is not
|
||||
// * going to use the xdg_output_manager object anymore.
|
||||
// *
|
||||
// * Any objects already created through this instance are not affected.
|
||||
// */
|
||||
// static inline void
|
||||
// zxdg_output_manager_v1_destroy(struct zxdg_output_manager_v1 *zxdg_output_manager_v1)
|
||||
// {
|
||||
// wl_proxy_marshal_flags((struct wl_proxy *) zxdg_output_manager_v1,
|
||||
// ZXDG_OUTPUT_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_output_manager_v1), WL_MARSHAL_FLAG_DESTROY);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @ingroup iface_zxdg_output_manager_v1
|
||||
// *
|
||||
// * This creates a new xdg_output object for the given wl_output.
|
||||
// */
|
||||
// static inline struct zxdg_output_v1 *
|
||||
// zxdg_output_manager_v1_get_xdg_output(struct zxdg_output_manager_v1 *zxdg_output_manager_v1, struct wl_output *output)
|
||||
// {
|
||||
// struct wl_proxy *id;
|
||||
|
||||
// id = wl_proxy_marshal_flags((struct wl_proxy *) zxdg_output_manager_v1,
|
||||
// ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT, &zxdg_output_v1_interface, wl_proxy_get_version((struct wl_proxy *) zxdg_output_manager_v1), 0, NULL, output);
|
||||
|
||||
// return (struct zxdg_output_v1 *) id;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
* @struct zxdg_output_v1_listener
|
||||
*/
|
||||
struct zxdg_output_v1_listener {
|
||||
/**
|
||||
* position of the output within the global compositor space
|
||||
*
|
||||
* The position event describes the location of the wl_output
|
||||
* within the global compositor space.
|
||||
*
|
||||
* The logical_position event is sent after creating an xdg_output
|
||||
* (see xdg_output_manager.get_xdg_output) and whenever the
|
||||
* location of the output changes within the global compositor
|
||||
* space.
|
||||
* @param x x position within the global compositor space
|
||||
* @param y y position within the global compositor space
|
||||
*/
|
||||
void (*logical_position)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
int32_t x,
|
||||
int32_t y);
|
||||
/**
|
||||
* size of the output in the global compositor space
|
||||
*
|
||||
* The logical_size event describes the size of the output in the
|
||||
* global compositor space.
|
||||
*
|
||||
* Most regular Wayland clients should not pay attention to the
|
||||
* logical size and would rather rely on xdg_shell interfaces.
|
||||
*
|
||||
* Some clients such as Xwayland, however, need this to configure
|
||||
* their surfaces in the global compositor space as the compositor
|
||||
* may apply a different scale from what is advertised by the
|
||||
* output scaling property (to achieve fractional scaling, for
|
||||
* example).
|
||||
*
|
||||
* For example, for a wl_output mode 3840×2160 and a scale factor
|
||||
* 2:
|
||||
*
|
||||
* - A compositor not scaling the monitor viewport in its
|
||||
* compositing space will advertise a logical size of 3840×2160,
|
||||
*
|
||||
* - A compositor scaling the monitor viewport with scale factor 2
|
||||
* will advertise a logical size of 1920×1080,
|
||||
*
|
||||
* - A compositor scaling the monitor viewport using a fractional
|
||||
* scale of 1.5 will advertise a logical size of 2560×1440.
|
||||
*
|
||||
* For example, for a wl_output mode 1920×1080 and a 90 degree
|
||||
* rotation, the compositor will advertise a logical size of
|
||||
* 1080x1920.
|
||||
*
|
||||
* The logical_size event is sent after creating an xdg_output (see
|
||||
* xdg_output_manager.get_xdg_output) and whenever the logical size
|
||||
* of the output changes, either as a result of a change in the
|
||||
* applied scale or because of a change in the corresponding output
|
||||
* mode(see wl_output.mode) or transform (see wl_output.transform).
|
||||
* @param width width in global compositor space
|
||||
* @param height height in global compositor space
|
||||
*/
|
||||
void (*logical_size)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
int32_t width,
|
||||
int32_t height);
|
||||
/**
|
||||
* all information about the output have been sent
|
||||
*
|
||||
* This event is sent after all other properties of an xdg_output
|
||||
* have been sent.
|
||||
*
|
||||
* This allows changes to the xdg_output properties to be seen as
|
||||
* atomic, even if they happen via multiple events.
|
||||
*
|
||||
* For objects version 3 onwards, this event is deprecated.
|
||||
* Compositors are not required to send it anymore and must send
|
||||
* wl_output.done instead.
|
||||
*/
|
||||
void (*done)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1);
|
||||
/**
|
||||
* name of this output
|
||||
*
|
||||
* Many compositors will assign names to their outputs, show them
|
||||
* to the user, allow them to be configured by name, etc. The
|
||||
* client may wish to know this name as well to offer the user
|
||||
* similar behaviors.
|
||||
*
|
||||
* The naming convention is compositor defined, but limited to
|
||||
* alphanumeric characters and dashes (-). Each name is unique
|
||||
* among all wl_output globals, but if a wl_output global is
|
||||
* destroyed the same name may be reused later. The names will also
|
||||
* remain consistent across sessions with the same hardware and
|
||||
* software configuration.
|
||||
*
|
||||
* Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc.
|
||||
* However, do not assume that the name is a reflection of an
|
||||
* underlying DRM connector, X11 connection, etc.
|
||||
*
|
||||
* The name event is sent after creating an xdg_output (see
|
||||
* xdg_output_manager.get_xdg_output). This event is only sent once
|
||||
* per xdg_output, and the name does not change over the lifetime
|
||||
* of the wl_output global.
|
||||
*
|
||||
* This event is deprecated, instead clients should use
|
||||
* wl_output.name. Compositors must still support this event.
|
||||
* @param name output name
|
||||
* @since 2
|
||||
*/
|
||||
void (*name)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
const char *name);
|
||||
/**
|
||||
* human-readable description of this output
|
||||
*
|
||||
* Many compositors can produce human-readable descriptions of
|
||||
* their outputs. The client may wish to know this description as
|
||||
* well, to communicate the user for various purposes.
|
||||
*
|
||||
* The description is a UTF-8 string with no convention defined for
|
||||
* its contents. Examples might include 'Foocorp 11" Display' or
|
||||
* 'Virtual X11 output via :1'.
|
||||
*
|
||||
* The description event is sent after creating an xdg_output (see
|
||||
* xdg_output_manager.get_xdg_output) and whenever the description
|
||||
* changes. The description is optional, and may not be sent at
|
||||
* all.
|
||||
*
|
||||
* For objects of version 2 and lower, this event is only sent once
|
||||
* per xdg_output, and the description does not change over the
|
||||
* lifetime of the wl_output global.
|
||||
*
|
||||
* This event is deprecated, instead clients should use
|
||||
* wl_output.description. Compositors must still support this
|
||||
* event.
|
||||
* @param description output description
|
||||
* @since 2
|
||||
*/
|
||||
void (*description)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
const char *description);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
static inline int
|
||||
zxdg_output_v1_add_listener(struct zxdg_output_v1 *zxdg_output_v1,
|
||||
const struct zxdg_output_v1_listener *listener, void *data)
|
||||
{
|
||||
return wl_proxy_add_listener((struct wl_proxy *) zxdg_output_v1,
|
||||
(void (**)(void)) listener, data);
|
||||
}
|
||||
|
||||
#define ZXDG_OUTPUT_V1_DESTROY 0
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_LOGICAL_POSITION_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_LOGICAL_SIZE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_DONE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_NAME_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION 2
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_DESTROY_SINCE_VERSION 1
|
||||
|
||||
// /** @ingroup iface_zxdg_output_v1 */
|
||||
// static inline void
|
||||
// zxdg_output_v1_set_user_data(struct zxdg_output_v1 *zxdg_output_v1, void *user_data)
|
||||
// {
|
||||
// wl_proxy_set_user_data((struct wl_proxy *) zxdg_output_v1, user_data);
|
||||
// }
|
||||
|
||||
// /** @ingroup iface_zxdg_output_v1 */
|
||||
// static inline void *
|
||||
// zxdg_output_v1_get_user_data(struct zxdg_output_v1 *zxdg_output_v1)
|
||||
// {
|
||||
// return wl_proxy_get_user_data((struct wl_proxy *) zxdg_output_v1);
|
||||
// }
|
||||
|
||||
// static inline uint32_t
|
||||
// zxdg_output_v1_get_version(struct zxdg_output_v1 *zxdg_output_v1)
|
||||
// {
|
||||
// return wl_proxy_get_version((struct wl_proxy *) zxdg_output_v1);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @ingroup iface_zxdg_output_v1
|
||||
// *
|
||||
// * Using this request a client can tell the server that it is not
|
||||
// * going to use the xdg_output object anymore.
|
||||
// */
|
||||
// static inline void
|
||||
// zxdg_output_v1_destroy(struct zxdg_output_v1 *zxdg_output_v1)
|
||||
// {
|
||||
// wl_proxy_marshal_flags((struct wl_proxy *) zxdg_output_v1,
|
||||
// ZXDG_OUTPUT_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_output_v1), WL_MARSHAL_FLAG_DESTROY);
|
||||
// }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,70 @@
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
/* Generated by wayland-scanner 1.22.0 */
|
||||
|
||||
/*
|
||||
* Copyright © 2017 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <wayland-util.h>
|
||||
|
||||
extern const struct wl_interface wl_output_interface;
|
||||
extern const struct wl_interface zxdg_output_v1_interface;
|
||||
|
||||
static const struct wl_interface *xdg_output_unstable_v1_types[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
&zxdg_output_v1_interface,
|
||||
NULL, // &wl_output_interface,
|
||||
};
|
||||
|
||||
static const struct wl_message zxdg_output_manager_v1_requests[] = {
|
||||
{ "destroy", "", xdg_output_unstable_v1_types + 0 },
|
||||
{ "get_xdg_output", "no", xdg_output_unstable_v1_types + 2 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface zxdg_output_manager_v1_interface = {
|
||||
"zxdg_output_manager_v1", 3,
|
||||
2, zxdg_output_manager_v1_requests,
|
||||
0, NULL,
|
||||
};
|
||||
|
||||
static const struct wl_message zxdg_output_v1_requests[] = {
|
||||
{ "destroy", "", xdg_output_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message zxdg_output_v1_events[] = {
|
||||
{ "logical_position", "ii", xdg_output_unstable_v1_types + 0 },
|
||||
{ "logical_size", "ii", xdg_output_unstable_v1_types + 0 },
|
||||
{ "done", "", xdg_output_unstable_v1_types + 0 },
|
||||
{ "name", "2s", xdg_output_unstable_v1_types + 0 },
|
||||
{ "description", "2s", xdg_output_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface zxdg_output_v1_interface = {
|
||||
"zxdg_output_v1", 3,
|
||||
1, zxdg_output_v1_requests,
|
||||
5, zxdg_output_v1_events,
|
||||
};
|
||||
|
||||
#endif
|
@ -71,27 +71,27 @@ static void waylandZwlrCurrentModeListener(void* data, FF_MAYBE_UNUSED struct zw
|
||||
wldata->refreshRate = current->refreshRate;
|
||||
}
|
||||
|
||||
static const struct zwlr_output_head_v1_listener headListener = {
|
||||
.name = (void*) ffWaylandOutputNameListener,
|
||||
.description = (void*) ffWaylandOutputDescriptionListener,
|
||||
.physical_size = (void*) stubListener,
|
||||
.mode = waylandZwlrModeListener,
|
||||
.enabled = (void*) stubListener,
|
||||
.current_mode = waylandZwlrCurrentModeListener,
|
||||
.position = (void*) stubListener,
|
||||
.transform = waylandZwlrTransformListener,
|
||||
.scale = waylandZwlrScaleListener,
|
||||
.finished = (void*) stubListener,
|
||||
.make = (void*) stubListener,
|
||||
.model = (void*) stubListener,
|
||||
.serial_number = (void*) stubListener,
|
||||
.adaptive_sync = (void*) stubListener,
|
||||
};
|
||||
|
||||
static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output_manager_v1 *zwlr_output_manager_v1, struct zwlr_output_head_v1 *head)
|
||||
{
|
||||
WaylandData* wldata = data;
|
||||
|
||||
const struct zwlr_output_head_v1_listener headListener = {
|
||||
.name = (void*) ffWaylandOutputNameListener,
|
||||
.description = (void*) ffWaylandOutputDescriptionListener,
|
||||
.physical_size = (void*) stubListener,
|
||||
.mode = waylandZwlrModeListener,
|
||||
.enabled = (void*) stubListener,
|
||||
.current_mode = waylandZwlrCurrentModeListener,
|
||||
.position = (void*) stubListener,
|
||||
.transform = waylandZwlrTransformListener,
|
||||
.scale = waylandZwlrScaleListener,
|
||||
.finished = (void*) stubListener,
|
||||
.make = (void*) stubListener,
|
||||
.model = (void*) stubListener,
|
||||
.serial_number = (void*) stubListener,
|
||||
.adaptive_sync = (void*) stubListener,
|
||||
};
|
||||
|
||||
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandZwlrMode));
|
||||
WaylandDisplay display = {
|
||||
.parent = wldata,
|
||||
@ -160,7 +160,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
|
||||
: &display.name,
|
||||
display.type,
|
||||
false,
|
||||
0
|
||||
display.id
|
||||
);
|
||||
|
||||
ffStrbufDestroy(&display.description);
|
||||
|
@ -42,6 +42,8 @@ const char* detectByOpenGL(FFlist* gpus)
|
||||
ffStrbufInit(&result.renderer);
|
||||
ffStrbufInit(&result.vendor);
|
||||
ffStrbufInit(&result.slv);
|
||||
ffStrbufInit(&result.library);
|
||||
|
||||
const char* error = ffDetectOpenGL(&instance.config.modules.openGL, &result);
|
||||
if (!error)
|
||||
{
|
||||
@ -75,6 +77,7 @@ const char* detectByOpenGL(FFlist* gpus)
|
||||
ffStrbufDestroy(&result.renderer);
|
||||
ffStrbufDestroy(&result.vendor);
|
||||
ffStrbufDestroy(&result.slv);
|
||||
ffStrbufDestroy(&result.library);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ typedef struct FFGPUResult
|
||||
FFstrbuf platformApi;
|
||||
double temperature;
|
||||
int32_t coreCount;
|
||||
double frequency; // Real time clock frequency in GHz
|
||||
double frequency; // Maximum time clock frequency in GHz
|
||||
FFGPUMemory dedicated;
|
||||
FFGPUMemory shared;
|
||||
uint64_t deviceId; // Used internally, may be uninitialized
|
||||
|
@ -78,7 +78,7 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
|
||||
|
||||
const uint32_t hwmonLen = pciDir->length;
|
||||
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
|
||||
if (ffPathExists(pciDir->chars, FF_PATHTYPE_FILE))
|
||||
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY))
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
else
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
@ -92,11 +92,6 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
|
||||
gpu->temperature = (double) value / 1000;
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(pciDir, hwmonLen);
|
||||
ffStrbufAppendS(pciDir, "freq1_input"); // The gfx/compute clock in hertz
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
gpu->frequency = (double) value / (1000 * 1000 * 1000);
|
||||
|
||||
if (options->driverSpecific)
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
@ -197,6 +192,13 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
||||
return "Invalid PCI device path";
|
||||
|
||||
ffStrbufAppendS(deviceDir, "/enable");
|
||||
if (ffReadFileBuffer(deviceDir->chars, buffer))
|
||||
{
|
||||
if (!ffStrbufStartsWithC(buffer, '1'))
|
||||
return "GPU disabled";
|
||||
}
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
|
||||
ffStrbufInit(&gpu->name);
|
||||
|
@ -8,7 +8,10 @@ typedef struct FFOpenGLResult
|
||||
FFstrbuf renderer;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf slv;
|
||||
const char* library;
|
||||
FFstrbuf library;
|
||||
} FFOpenGLResult;
|
||||
|
||||
#define FF_OPENGL_BUFFER_WIDTH 1
|
||||
#define FF_OPENGL_BUFFER_HEIGHT 1
|
||||
|
||||
const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result);
|
||||
|
@ -6,22 +6,20 @@
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/OpenGL.h> // This brings in CGL, not GL
|
||||
|
||||
static const char* glHandleResult(FFOpenGLResult* result)
|
||||
{
|
||||
ffStrbufAppendS(&result->version, (const char*) glGetString(GL_VERSION));
|
||||
ffStrbufAppendS(&result->renderer, (const char*) glGetString(GL_RENDERER));
|
||||
ffStrbufAppendS(&result->vendor, (const char*) glGetString(GL_VENDOR));
|
||||
ffStrbufAppendS(&result->slv, (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
result->library = "CGL";
|
||||
return NULL;
|
||||
}
|
||||
void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglGetString);
|
||||
|
||||
static const char* cglHandleContext(FFOpenGLResult* result, CGLContextObj context)
|
||||
{
|
||||
if(CGLSetCurrentContext(context) != kCGLNoError)
|
||||
return "CGLSetCurrentContext() failed";
|
||||
|
||||
return glHandleResult(result);
|
||||
ffOpenGLHandleResult(result, &glGetString);
|
||||
|
||||
GLint major, minor;
|
||||
CGLGetVersion(&major, &minor);
|
||||
ffStrbufSetF(&result->library, "CGL %d.%d", major, minor);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* cglHandlePixelFormat(FFOpenGLResult* result, CGLPixelFormatObj pixelFormat)
|
||||
|
@ -10,146 +10,19 @@
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#define FF_OPENGL_BUFFER_WIDTH 1
|
||||
#define FF_OPENGL_BUFFER_HEIGHT 1
|
||||
|
||||
typedef struct GLData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
} GLData;
|
||||
|
||||
static const char* glHandleResult(FFOpenGLResult* result, const GLData* data, const char* library)
|
||||
{
|
||||
ffStrbufAppendS(&result->version, (const char*) data->ffglGetString(GL_VERSION));
|
||||
ffStrbufAppendS(&result->renderer, (const char*) data->ffglGetString(GL_RENDERER));
|
||||
ffStrbufAppendS(&result->vendor, (const char*) data->ffglGetString(GL_VENDOR));
|
||||
ffStrbufAppendS(&result->slv, (const char*) data->ffglGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
result->library = library;
|
||||
return NULL;
|
||||
}
|
||||
void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglGetString);
|
||||
|
||||
#endif // FF_HAVE_GL
|
||||
|
||||
#ifdef FF_HAVE_EGL
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
typedef struct EGLData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(eglGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(eglGetDisplay)
|
||||
FF_LIBRARY_SYMBOL(eglInitialize)
|
||||
FF_LIBRARY_SYMBOL(eglBindAPI)
|
||||
FF_LIBRARY_SYMBOL(eglGetConfigs)
|
||||
FF_LIBRARY_SYMBOL(eglCreatePbufferSurface)
|
||||
FF_LIBRARY_SYMBOL(eglCreateContext)
|
||||
FF_LIBRARY_SYMBOL(eglMakeCurrent)
|
||||
FF_LIBRARY_SYMBOL(eglDestroyContext)
|
||||
FF_LIBRARY_SYMBOL(eglDestroySurface)
|
||||
FF_LIBRARY_SYMBOL(eglTerminate)
|
||||
|
||||
EGLDisplay display;
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
} EGLData;
|
||||
|
||||
static const char* eglHandleContext(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
if(data->ffeglMakeCurrent(data->display, data->surface, data->surface, data->context) != EGL_TRUE)
|
||||
return "eglMakeCurrent returned EGL_FALSE";
|
||||
|
||||
return glHandleResult(result, &data->glData, "EGL");
|
||||
}
|
||||
|
||||
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
|
||||
if(data->context == EGL_NO_CONTEXT)
|
||||
return "eglCreateContext returned EGL_NO_CONTEXT";
|
||||
|
||||
const char* error = eglHandleContext(result, data);
|
||||
data->ffeglDestroyContext(data->display, data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
if(data->ffeglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
|
||||
return "eglBindAPI returned EGL_FALSE";
|
||||
|
||||
EGLint eglConfigCount;
|
||||
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
|
||||
if(eglConfigCount == 0)
|
||||
return "eglGetConfigs returned 0 configs";
|
||||
|
||||
data->surface = data->ffeglCreatePbufferSurface(data->display, data->config, (EGLint[]){
|
||||
EGL_WIDTH, FF_OPENGL_BUFFER_WIDTH,
|
||||
EGL_HEIGHT, FF_OPENGL_BUFFER_HEIGHT,
|
||||
EGL_NONE
|
||||
});
|
||||
|
||||
if(data->surface == EGL_NO_SURFACE)
|
||||
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
|
||||
|
||||
const char* error = eglHandleSurface(result, data);
|
||||
data->ffeglDestroySurface(data->display, data->surface);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleData(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffeglGetProcAddress("glGetString");
|
||||
if(!data->glData.ffglGetString)
|
||||
return "eglGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(data->display == EGL_NO_DISPLAY)
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
|
||||
EGLint major, minor;
|
||||
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
|
||||
return "eglInitialize returned EGL_FALSE";
|
||||
|
||||
const char* error = eglHandleDisplay(result, data);
|
||||
data->ffeglTerminate(data->display);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglPrint(FFOpenGLResult* result)
|
||||
{
|
||||
EGLData eglData;
|
||||
|
||||
FF_LIBRARY_LOAD(egl, &instance.config.library.libEGL, "dlopen egl failed", "libEGL" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglInitialize);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglBindAPI);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetConfigs);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreatePbufferSurface);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroyContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
|
||||
|
||||
FF_SUPPRESS_IO();
|
||||
return eglHandleData(result, &eglData);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_EGL
|
||||
|
||||
#ifdef FF_HAVE_GLX
|
||||
#include <GL/glx.h>
|
||||
|
||||
typedef struct GLXData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
FF_LIBRARY_SYMBOL(glXGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(glXQueryVersion)
|
||||
FF_LIBRARY_SYMBOL(XOpenDisplay)
|
||||
FF_LIBRARY_SYMBOL(glXChooseVisual)
|
||||
FF_LIBRARY_SYMBOL(XCreatePixmap);
|
||||
@ -173,8 +46,15 @@ static const char* glxHandleContext(FFOpenGLResult* result, GLXData* data)
|
||||
{
|
||||
if(data->ffglXMakeCurrent(data->display, data->glxPixmap, data->context) != True)
|
||||
return "glXMakeCurrent returned False";
|
||||
ffOpenGLHandleResult(result, data->ffglGetString);
|
||||
|
||||
return glHandleResult(result, &data->glData, "GLX");
|
||||
int major, minor;
|
||||
if (data->ffglXQueryVersion(data->display, &major, &minor))
|
||||
ffStrbufSetF(&result->library, "GLX %d.%d", major, minor);
|
||||
else
|
||||
ffStrbufSetStatic(&result->library, "GLX");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* glxHandleGLXPixmap(FFOpenGLResult* result, GLXData* data)
|
||||
@ -223,8 +103,8 @@ static const char* glxHandleDisplay(FFOpenGLResult* result, GLXData* data)
|
||||
|
||||
static const char* glxHandleData(FFOpenGLResult* result, GLXData* data)
|
||||
{
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffglXGetProcAddress((const GLubyte*) "glGetString");
|
||||
if(data->glData.ffglGetString == NULL)
|
||||
data->ffglGetString = (__typeof__(data->ffglGetString)) data->ffglXGetProcAddress((const GLubyte*) "glGetString");
|
||||
if(data->ffglGetString == NULL)
|
||||
return "glXGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffXOpenDisplay(NULL);
|
||||
@ -236,12 +116,13 @@ static const char* glxHandleData(FFOpenGLResult* result, GLXData* data)
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* glxPrint(FFOpenGLResult* result)
|
||||
static const char* detectByGlx(FFOpenGLResult* result)
|
||||
{
|
||||
GLXData data;
|
||||
|
||||
FF_LIBRARY_LOAD(glx, &instance.config.library.libGLX, "dlopen glx failed", "libGLX" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXQueryVersion);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXChooseVisual);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCreatePixmap);
|
||||
@ -268,8 +149,7 @@ static const char* glxPrint(FFOpenGLResult* result)
|
||||
|
||||
typedef struct OSMesaData
|
||||
{
|
||||
GLData glData;
|
||||
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
FF_LIBRARY_SYMBOL(OSMesaGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(OSMesaCreateContext)
|
||||
FF_LIBRARY_SYMBOL(OSMesaMakeCurrent)
|
||||
@ -285,14 +165,15 @@ static const char* osMesaHandleContext(FFOpenGLResult* result, OSMesaData* data)
|
||||
if(data->ffOSMesaMakeCurrent(data->context, buffer, GL_UNSIGNED_BYTE, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT) != GL_TRUE)
|
||||
return "OSMesaMakeCurrent returned GL_FALSE";
|
||||
|
||||
return glHandleResult(result, &data->glData, "OSMesa");
|
||||
ffOpenGLHandleResult(result, data->ffglGetString);
|
||||
ffStrbufSetF(&result->library, "OSMesa %d.%d.%d", OSMESA_MAJOR_VERSION, OSMESA_MINOR_VERSION, OSMESA_PATCH_VERSION);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* osMesaHandleData(FFOpenGLResult* result, OSMesaData* data)
|
||||
{
|
||||
//The case to void* is required here, because OSMESAproc can't be cast to (__typeof__(data->glData.ffglGetString)) without a warning, even though it is the actual type.
|
||||
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) (void*) data->ffOSMesaGetProcAddress("glGetString");
|
||||
if(data->glData.ffglGetString == NULL)
|
||||
data->ffglGetString = (void*) data->ffOSMesaGetProcAddress("glGetString");
|
||||
if(data->ffglGetString == NULL)
|
||||
return "OSMesaGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->context = data->ffOSMesaCreateContext(OSMESA_RGBA, NULL);
|
||||
@ -304,7 +185,7 @@ static const char* osMesaHandleData(FFOpenGLResult* result, OSMesaData* data)
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* osMesaPrint(FFOpenGLResult* result)
|
||||
static const char* detectByOsMesa(FFOpenGLResult* result)
|
||||
{
|
||||
OSMesaData data;
|
||||
|
||||
@ -326,7 +207,7 @@ const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
if(options->library == FF_OPENGL_LIBRARY_GLX)
|
||||
{
|
||||
#ifdef FF_HAVE_GLX
|
||||
return glxPrint(result);
|
||||
return detectByGlx(result);
|
||||
#else
|
||||
return "fastfetch was compiled without glx support";
|
||||
#endif
|
||||
@ -335,7 +216,8 @@ const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
if(options->library == FF_OPENGL_LIBRARY_EGL)
|
||||
{
|
||||
#ifdef FF_HAVE_EGL
|
||||
return eglPrint(result);
|
||||
const char* ffOpenGLDetectByEGL(FFOpenGLResult* result);
|
||||
return ffOpenGLDetectByEGL(result);
|
||||
#else
|
||||
return "fastfetch was compiled without egl support";
|
||||
#endif
|
||||
@ -344,7 +226,7 @@ const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
if(options->library == FF_OPENGL_LIBRARY_OSMESA)
|
||||
{
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
return osMesaPrint(result);
|
||||
return detectByOsMesa(result);
|
||||
#else
|
||||
return "fastfetch was compiled without osmesa support";
|
||||
#endif
|
||||
@ -353,12 +235,13 @@ const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
const char* error = ""; // not NULL dummy value
|
||||
|
||||
#ifdef FF_HAVE_EGL
|
||||
error = eglPrint(result);
|
||||
const char* ffOpenGLDetectByEGL(FFOpenGLResult* result);
|
||||
error = ffOpenGLDetectByEGL(result);
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_GLX
|
||||
if(error != NULL)
|
||||
error = glxPrint(result);
|
||||
error = detectByGlx(result);
|
||||
#endif
|
||||
|
||||
//We don't use osmesa in auto mode here, because it is a software implementation,
|
||||
|
148
src/detection/opengl/opengl_shared.c
Normal file
148
src/detection/opengl/opengl_shared.c
Normal file
@ -0,0 +1,148 @@
|
||||
#include "opengl.h"
|
||||
#include "common/library.h"
|
||||
|
||||
#if __has_include(<GL/gl.h>)
|
||||
#include <GL/gl.h>
|
||||
#elif __has_include(<OpenGL/gl.h>)
|
||||
#define GL_SILENCE_DEPRECATION 1
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#define FF_HAVE_NO_GL 1
|
||||
#endif
|
||||
|
||||
#ifndef FF_HAVE_NO_GL
|
||||
|
||||
#ifndef GL_SHADING_LANGUAGE_VERSION // For WGL
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#endif
|
||||
|
||||
void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglGetString)
|
||||
{
|
||||
ffStrbufAppendS(&result->version, (const char*) ffglGetString(GL_VERSION));
|
||||
ffStrbufAppendS(&result->renderer, (const char*) ffglGetString(GL_RENDERER));
|
||||
ffStrbufAppendS(&result->vendor, (const char*) ffglGetString(GL_VENDOR));
|
||||
ffStrbufAppendS(&result->slv, (const char*) ffglGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
}
|
||||
|
||||
#if defined(FF_HAVE_EGL) || __has_include(<EGL/egl.h>)
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
typedef struct EGLData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
FF_LIBRARY_SYMBOL(eglGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(eglGetDisplay)
|
||||
FF_LIBRARY_SYMBOL(eglQueryString)
|
||||
FF_LIBRARY_SYMBOL(eglInitialize)
|
||||
FF_LIBRARY_SYMBOL(eglBindAPI)
|
||||
FF_LIBRARY_SYMBOL(eglGetConfigs)
|
||||
FF_LIBRARY_SYMBOL(eglCreatePbufferSurface)
|
||||
FF_LIBRARY_SYMBOL(eglCreateContext)
|
||||
FF_LIBRARY_SYMBOL(eglMakeCurrent)
|
||||
FF_LIBRARY_SYMBOL(eglDestroyContext)
|
||||
FF_LIBRARY_SYMBOL(eglDestroySurface)
|
||||
FF_LIBRARY_SYMBOL(eglTerminate)
|
||||
|
||||
EGLDisplay display;
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
} EGLData;
|
||||
|
||||
static const char* eglHandleContext(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
if(data->ffeglMakeCurrent(data->display, data->surface, data->surface, data->context) != EGL_TRUE)
|
||||
return "eglMakeCurrent returned EGL_FALSE";
|
||||
|
||||
ffOpenGLHandleResult(result, data->ffglGetString);
|
||||
ffStrbufSetF(&result->library, "EGL %s", data->ffeglQueryString(data->display, EGL_VERSION));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
|
||||
if(data->context == EGL_NO_CONTEXT)
|
||||
return "eglCreateContext returned EGL_NO_CONTEXT";
|
||||
|
||||
const char* error = eglHandleContext(result, data);
|
||||
data->ffeglDestroyContext(data->display, data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
if(data->ffeglBindAPI(
|
||||
#ifdef _WIN32
|
||||
EGL_OPENGL_ES_API
|
||||
#else
|
||||
EGL_OPENGL_API
|
||||
#endif
|
||||
) != EGL_TRUE)
|
||||
return "eglBindAPI returned EGL_FALSE";
|
||||
|
||||
EGLint eglConfigCount;
|
||||
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
|
||||
if(eglConfigCount == 0)
|
||||
return "eglGetConfigs returned 0 configs";
|
||||
|
||||
data->surface = data->ffeglCreatePbufferSurface(data->display, data->config, (EGLint[]){
|
||||
EGL_WIDTH, FF_OPENGL_BUFFER_WIDTH,
|
||||
EGL_HEIGHT, FF_OPENGL_BUFFER_HEIGHT,
|
||||
EGL_NONE
|
||||
});
|
||||
|
||||
if(data->surface == EGL_NO_SURFACE)
|
||||
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
|
||||
|
||||
const char* error = eglHandleSurface(result, data);
|
||||
data->ffeglDestroySurface(data->display, data->surface);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* eglHandleData(FFOpenGLResult* result, EGLData* data)
|
||||
{
|
||||
data->ffglGetString = (__typeof__(&glGetString)) data->ffeglGetProcAddress("glGetString");
|
||||
if(!data->ffglGetString)
|
||||
return "eglGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(data->display == EGL_NO_DISPLAY)
|
||||
return "eglGetDisplay returned EGL_NO_DISPLAY";
|
||||
|
||||
EGLint major, minor;
|
||||
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
|
||||
return "eglInitialize returned EGL_FALSE";
|
||||
|
||||
const char* error = eglHandleDisplay(result, data);
|
||||
data->ffeglTerminate(data->display);
|
||||
return error;
|
||||
}
|
||||
|
||||
const char* ffOpenGLDetectByEGL(FFOpenGLResult* result)
|
||||
{
|
||||
EGLData eglData;
|
||||
|
||||
FF_LIBRARY_LOAD(egl, &instance.config.library.libEGL, "dlopen egl failed", "libEGL" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetDisplay);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglQueryString);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglInitialize);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglBindAPI);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetConfigs);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreatePbufferSurface);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroyContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
|
||||
|
||||
FF_SUPPRESS_IO();
|
||||
return eglHandleData(result, &eglData);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_EGL
|
||||
|
||||
#endif //FF_HAVE_NO_GL
|
@ -4,9 +4,6 @@
|
||||
|
||||
#include <Windows.h>
|
||||
#include <GL/gl.h>
|
||||
#ifndef GL_SHADING_LANGUAGE_VERSION // For WGL
|
||||
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
|
||||
#endif
|
||||
|
||||
typedef struct WGLData
|
||||
{
|
||||
@ -19,21 +16,15 @@ typedef struct WGLData
|
||||
FF_LIBRARY_SYMBOL(wglDeleteContext)
|
||||
} WGLData;
|
||||
|
||||
static const char* glHandleResult(WGLData* wglData)
|
||||
{
|
||||
ffStrbufAppendS(&wglData->result->version, (const char*) wglData->ffglGetString(GL_VERSION));
|
||||
ffStrbufAppendS(&wglData->result->renderer, (const char*) wglData->ffglGetString(GL_RENDERER));
|
||||
ffStrbufAppendS(&wglData->result->vendor, (const char*) wglData->ffglGetString(GL_VENDOR));
|
||||
ffStrbufAppendS(&wglData->result->slv, (const char*) wglData->ffglGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
wglData->result->library = "WGL";
|
||||
return NULL;
|
||||
}
|
||||
void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglGetString);
|
||||
|
||||
static const char* wglHandleContext(WGLData* wglData, HDC hdc, HGLRC context)
|
||||
{
|
||||
if(wglData->ffwglMakeCurrent(hdc, context) == FALSE)
|
||||
return "wglMakeCurrent() failed";
|
||||
return glHandleResult(wglData);
|
||||
ffOpenGLHandleResult(wglData->result, wglData->ffglGetString);
|
||||
ffStrbufSetStatic(&wglData->result->library, "WGL 1.0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* wglHandlePixelFormat(WGLData* wglData, HWND hWnd)
|
||||
@ -88,16 +79,16 @@ static LRESULT CALLBACK wglHandleWndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectOpenGL(FF_MAYBE_UNUSED FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
static const char* wglDetectOpenGL(FFOpenGLResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(opengl32, NULL, "dlopen opengl32" FF_LIBRARY_EXTENSION " failed", "opengl32" FF_LIBRARY_EXTENSION, 1);
|
||||
|
||||
WGLData data = { .result = result };
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, glGetString);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglDeleteContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, glGetString);
|
||||
|
||||
MSG msg = {0};
|
||||
WNDCLASSW wc = {
|
||||
@ -110,10 +101,28 @@ const char* ffDetectOpenGL(FF_MAYBE_UNUSED FFOpenGLOptions* options, FFOpenGLRes
|
||||
if(!RegisterClassW(&wc))
|
||||
return "RegisterClassW() failed";
|
||||
|
||||
HWND hWnd = CreateWindowW(wc.lpszClassName, L"ogl_version_check", 0, 0, 0, 1, 1, NULL, NULL, NULL, &data);
|
||||
HWND hWnd = CreateWindowW(wc.lpszClassName, L"ogl_version_check", 0, 0, 0, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, NULL, NULL, NULL, &data);
|
||||
|
||||
while(GetMessageW(&msg, hWnd, 0, 0) > 0)
|
||||
DispatchMessage(&msg);
|
||||
|
||||
return data.error;
|
||||
}
|
||||
|
||||
|
||||
const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
{
|
||||
if (options->library == FF_OPENGL_LIBRARY_AUTO)
|
||||
return wglDetectOpenGL(result);
|
||||
else if (options->library == FF_OPENGL_LIBRARY_EGL)
|
||||
{
|
||||
#if __has_include(<EGL/egl.h>)
|
||||
const char* ffOpenGLDetectByEGL(FFOpenGLResult* result);
|
||||
return ffOpenGLDetectByEGL(result);
|
||||
#else
|
||||
return "fastfetch was compiled without egl support";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return "Unsupported OpenGL library";
|
||||
}
|
||||
|
@ -149,6 +149,12 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/firmware_rev", devName);
|
||||
if (ffReadFileBuffer(pathSysBlock, &device->revision))
|
||||
ffStrbufTrimRightSpace(&device->revision);
|
||||
else
|
||||
{
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/rev", devName);
|
||||
if (ffReadFileBuffer(pathSysBlock, &device->revision))
|
||||
ffStrbufTrimRightSpace(&device->revision);
|
||||
}
|
||||
}
|
||||
|
||||
device->temperature = FF_PHYSICALDISK_TEMP_UNSET;
|
||||
|
@ -113,7 +113,15 @@ const char* ffDetectPhysicalMemory(FFlist* result)
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufSetF(&device->locator, "%s/%s", ffSmbiosLocateString(strings, data->BankLocator), ffSmbiosLocateString(strings, data->DeviceLocator));
|
||||
// https://github.com/fastfetch-cli/fastfetch/issues/1051#issuecomment-2206687345
|
||||
const char* lbank = ffSmbiosLocateString(strings, data->BankLocator);
|
||||
const char* ldevice = ffSmbiosLocateString(strings, data->DeviceLocator);
|
||||
if (lbank && ldevice)
|
||||
ffStrbufSetF(&device->locator, "%s/%s", lbank, ldevice);
|
||||
else if (lbank)
|
||||
ffStrbufSetS(&device->locator, lbank);
|
||||
else if (ldevice)
|
||||
ffStrbufSetS(&device->locator, ldevice);
|
||||
|
||||
switch (data->FormFactor)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
static bool detectWMThemeFromConfigFile(const char* configFile, const char* themeRegex, const char* defaultValue, FFstrbuf* themeOrError)
|
||||
{
|
||||
@ -91,8 +92,8 @@ static bool detectMutter(FFstrbuf* themeOrError)
|
||||
|
||||
static bool detectMuffin(FFstrbuf* themeOrError)
|
||||
{
|
||||
const char* name = ffSettingsGet("/org/cinnamon/theme/name", "org.cinnamon.theme", NULL, "name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
const char* theme = ffSettingsGet("/org/cinnamon/desktop/wm/preferences/theme", "org.cinnamon.desktop.wm.preferences", NULL, "theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
FF_AUTO_FREE const char* name = ffSettingsGet("/org/cinnamon/theme/name", "org.cinnamon.theme", NULL, "name", FF_VARIANT_TYPE_STRING).strValue;
|
||||
FF_AUTO_FREE const char* theme = ffSettingsGet("/org/cinnamon/desktop/wm/preferences/theme", "org.cinnamon.desktop.wm.preferences", NULL, "theme", FF_VARIANT_TYPE_STRING).strValue;
|
||||
|
||||
if(name == NULL && theme == NULL)
|
||||
{
|
||||
@ -133,7 +134,7 @@ static bool detectXFWM4(FFstrbuf* themeOrError)
|
||||
static bool detectOpenbox(const FFstrbuf* dePrettyName, FFstrbuf* themeOrError)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateA(64);
|
||||
const char *configFileSubpath = "openbox/rc.xml";
|
||||
const char *configFileSubpath = "openbox/rc.xml";
|
||||
if (ffStrbufIgnCaseCompS(dePrettyName, "LXQt") == 0)
|
||||
configFileSubpath = "openbox/lxqt-rc.xml";
|
||||
else if (ffStrbufIgnCaseCompS(dePrettyName, "LXDE") == 0)
|
||||
|
@ -319,44 +319,6 @@ static void listModules(bool pretty)
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary copy before new release of yyjson
|
||||
static bool ffyyjson_locate_pos(const char *str, size_t len, size_t pos,
|
||||
size_t *line, size_t *col, size_t *chr) {
|
||||
size_t line_sum = 0, line_pos = 0, chr_sum = 0;
|
||||
const uint8_t *cur = (const uint8_t *)str;
|
||||
const uint8_t *end = cur + pos;
|
||||
|
||||
if (!str || pos > len) {
|
||||
if (line) *line = 0;
|
||||
if (col) *col = 0;
|
||||
if (chr) *chr = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
while (cur < end) {
|
||||
uint8_t c = *cur;
|
||||
chr_sum += 1;
|
||||
if (__builtin_expect(c < 0x80, true)) { /* 0xxxxxxx (0x00-0x7F) ASCII */
|
||||
if (c == '\n') {
|
||||
line_sum += 1;
|
||||
line_pos = chr_sum;
|
||||
}
|
||||
cur += 1;
|
||||
}
|
||||
else if (c < 0xC0) cur += 1; /* 10xxxxxx (0x80-0xBF) Invalid */
|
||||
else if (c < 0xE0) cur += 2; /* 110xxxxx (0xC0-0xDF) 2-byte UTF-8 */
|
||||
else if (c < 0xF0) cur += 3; /* 1110xxxx (0xE0-0xEF) 3-byte UTF-8 */
|
||||
else if (c < 0xF8) cur += 4; /* 11110xxx (0xF0-0xF7) 4-byte UTF-8 */
|
||||
else cur += 1; /* 11111xxx (0xF8-0xFF) Invalid */
|
||||
}
|
||||
|
||||
if (line) *line = line_sum + 1;
|
||||
if (col) *col = chr_sum - line_pos + 1;
|
||||
if (chr) *chr = chr_sum;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool parseJsoncFile(const char* path)
|
||||
{
|
||||
assert(!instance.state.configDoc);
|
||||
@ -371,7 +333,7 @@ static bool parseJsoncFile(const char* path)
|
||||
size_t row = 0, col = error.pos;
|
||||
FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate();
|
||||
if (ffAppendFileBuffer(path, &content))
|
||||
ffyyjson_locate_pos(content.chars, content.length, error.pos, &row, &col, NULL);
|
||||
yyjson_locate_pos(content.chars, content.length, error.pos, &row, &col, NULL);
|
||||
fprintf(stderr, "Error: failed to parse JSON config file `%s` at (%zu, %zu): %s\n", path, row, col, error.msg);
|
||||
exit(477);
|
||||
}
|
||||
|
23
src/logo/ascii/arkane.txt
Normal file
23
src/logo/ascii/arkane.txt
Normal file
@ -0,0 +1,23 @@
|
||||
.:..
|
||||
..:::......
|
||||
$2.$1 .$2.$1.....
|
||||
$2+=$1...$2==$1....
|
||||
......:.$3:-$2:$1..$3+*$2=$1....
|
||||
$2:----::$1......
|
||||
$2.=***##*+=: $1..
|
||||
$2=$3***######*$2=
|
||||
$2.$3-*######+
|
||||
$2:+$3###%%%###$1:
|
||||
$2-+*$3########+$1.
|
||||
$2=++*$3#######$1-
|
||||
$2-+=+**$3*####$1=
|
||||
$1.$2-=++==***$3##*$1-
|
||||
$2-++++++==++++=
|
||||
.-+++**+++=+===$1.
|
||||
$2:---===++++=-=--$1.
|
||||
$2-===============$1-==--:
|
||||
$2.-==+++***++*$3*#########$1=:::.
|
||||
$2.-=++++*++++**$3#######%%###$1=
|
||||
$2.:==++++++**$3#############$1:
|
||||
$2.$1-+*++*+++==$3###$1+
|
||||
-$3*+$1:
|
13
src/logo/ascii/opak.txt
Normal file
13
src/logo/ascii/opak.txt
Normal file
@ -0,0 +1,13 @@
|
||||
.':ldkOOOOkxo:,.
|
||||
.:d0KKXXXXXXXXXXKkl,
|
||||
.;xOOO0000KKKKXXXXXXX0l.
|
||||
.cxxxkkkkOOO0000KKKKXXXXx'
|
||||
;ool;,,,,;coxkOOOO0000KKKd.
|
||||
.clc'.........:oxkkkkOOOO0O,
|
||||
.ccc:ccclc:,....,:oddxxdxkO;
|
||||
cllllccccccc;'........'lxx.
|
||||
'ooooolllllccc:;,''',,coo,
|
||||
,ddddooooollllllccccccl'
|
||||
cxxxdddddooooollllc;
|
||||
,dxxxxxddddddol.
|
||||
.';::,.
|
@ -381,6 +381,18 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_CYAN,
|
||||
.colorTitle = FF_COLOR_FG_CYAN,
|
||||
},
|
||||
// Arkane
|
||||
{
|
||||
.names = {"Arkane", "Arkane Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ARKANE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_256 "237",
|
||||
FF_COLOR_FG_256 "130",
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_256 "130",
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Armbian
|
||||
{
|
||||
.names = {"Armbian"},
|
||||
@ -2945,6 +2957,12 @@ static const FFlogo O[] = {
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
}
|
||||
},
|
||||
// Opak
|
||||
{
|
||||
.names = {"Opak"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OPAK,
|
||||
.colors = {}, // #1070
|
||||
},
|
||||
// OpenKylin
|
||||
{
|
||||
.names = {"openkylin", "open-kylin"},
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "common/io/io.h"
|
||||
#include "common/printing.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/base64.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
@ -16,48 +17,6 @@
|
||||
#include <sys/termios.h>
|
||||
#endif
|
||||
|
||||
// https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145
|
||||
static void base64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output)
|
||||
{
|
||||
static const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
char *out = output;
|
||||
const char *ends = str + (size - size % 3);
|
||||
while (str != ends) {
|
||||
uint32_t n = __builtin_bswap32(*(uint32_t*) str);
|
||||
*out++ = chars[(n >> 26) & 63];
|
||||
*out++ = chars[(n >> 20) & 63];
|
||||
*out++ = chars[(n >> 14) & 63];
|
||||
*out++ = chars[(n >> 8) & 63];
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (size % 3 == 1) {
|
||||
uint64_t n = (uint64_t)*str << 16;
|
||||
*out++ = chars[(n >> 18) & 63];
|
||||
*out++ = chars[(n >> 12) & 63];
|
||||
*out++ = '=';
|
||||
*out++ = '=';
|
||||
} else if (size % 3 == 2) {
|
||||
uint64_t n = (uint64_t)*str++ << 16;
|
||||
n |= (uint64_t)*str << 8;
|
||||
*out++ = chars[(n >> 18) & 63];
|
||||
*out++ = chars[(n >> 12) & 63];
|
||||
*out++ = chars[(n >> 6) & 63];
|
||||
*out++ = '=';
|
||||
}
|
||||
*out = '\0';
|
||||
*out_size = (uint32_t) (out - output);
|
||||
}
|
||||
|
||||
static FFstrbuf base64Encode(const FFstrbuf* in)
|
||||
{
|
||||
FFstrbuf out = ffStrbufCreateA(10 + in->length * 4 / 3);
|
||||
base64EncodeRaw(in->length, in->chars, &out.length, out.chars);
|
||||
assert(out.length < out.allocated);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool printImageIterm(bool printError)
|
||||
{
|
||||
const FFOptionsLogo* options = &instance.config.logo;
|
||||
@ -71,7 +30,7 @@ static bool printImageIterm(bool printError)
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&buf);
|
||||
FF_STRBUF_AUTO_DESTROY base64 = ffBase64EncodeStrbuf(&buf);
|
||||
ffStrbufClear(&buf);
|
||||
|
||||
if (!options->width || !options->height)
|
||||
@ -166,7 +125,7 @@ static bool printImageKittyDirect(bool printError)
|
||||
return false;
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&options->source);
|
||||
FF_STRBUF_AUTO_DESTROY base64 = ffBase64EncodeStrbuf(&options->source);
|
||||
|
||||
if (!options->width || !options->height)
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "modules/battery/battery.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_BATTERY_NUM_FORMAT_ARGS 9
|
||||
#define FF_BATTERY_NUM_FORMAT_ARGS 10
|
||||
|
||||
static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uint8_t index)
|
||||
{
|
||||
@ -57,20 +57,23 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY capacityStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&capacityStr, result->capacity, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY capacityNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&capacityNum, result->capacity, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY capacityBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&capacityBar, result->capacity, options->percent, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
|
||||
ffTempsAppendNum(result->temperature, &tempStr, options->tempConfig, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_BATTERY_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_BATTERY_NUM_FORMAT_ARGS, ((FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer, "manufacturer"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->modelName, "model-name"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->technology, "technology"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &capacityStr, "capacity"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &capacityNum, "capacity"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->status, "status"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr, "temperature"},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &result->cycleCount, "cycle-count"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->serial, "serial"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->manufactureDate, "manufacture-date"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &capacityBar, "capacity-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -225,12 +228,13 @@ void ffPrintBatteryHelpFormat(void)
|
||||
"Battery manufacturer - manufacturer",
|
||||
"Battery model name - model-name",
|
||||
"Battery technology - technology",
|
||||
"Battery capacity (percentage) - capacity",
|
||||
"Battery capacity (percentage num) - capacity",
|
||||
"Battery status - status",
|
||||
"Battery temperature (formatted) - temperature",
|
||||
"Battery cycle count - cycle-count",
|
||||
"Battery serial number - serial",
|
||||
"Battery manufactor date - manufacture-date",
|
||||
"Battery capacity (percentage bar) - capacity-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "modules/bluetooth/bluetooth.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_BLUETOOTH_NUM_FORMAT_ARGS 5
|
||||
#define FF_BLUETOOTH_NUM_FORMAT_ARGS 6
|
||||
|
||||
static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* device, uint8_t index)
|
||||
{
|
||||
@ -29,15 +29,18 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageStr, device->battery, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageNum, device->battery, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs);
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_BLUETOOTH_NUM_FORMAT_ARGS, ((FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name, "name"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->address, "address"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->type, "type"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr, "battery-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageNum, "battery-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &device->connected, "connected"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageBar, "battery-percentage-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -178,8 +181,9 @@ void ffPrintBluetoothHelpFormat(void)
|
||||
"Name - name",
|
||||
"Address - address",
|
||||
"Type - type",
|
||||
"Battery percentage - battery-percentage",
|
||||
"Battery percentage number - battery-percentage",
|
||||
"Is connected - connected",
|
||||
"Battery percentage bar - battery-percentage-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "modules/brightness/brightness.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_BRIGHTNESS_NUM_FORMAT_ARGS 5
|
||||
#define FF_BRIGHTNESS_NUM_FORMAT_ARGS 6
|
||||
|
||||
void ffPrintBrightness(FFBrightnessOptions* options)
|
||||
{
|
||||
@ -67,14 +67,17 @@ void ffPrintBrightness(FFBrightnessOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY valueStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&valueStr, percent, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY valueNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&valueNum, percent, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY valueBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&valueBar, percent, options->percent, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BRIGHTNESS_NUM_FORMAT_ARGS, ((FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &valueStr, "percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &valueNum, "percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->name, "name"},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &item->max, "max"},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &item->min, "min"},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &item->current, "current"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->current, "percentage-bar"},
|
||||
}));
|
||||
}
|
||||
|
||||
@ -175,11 +178,12 @@ void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options
|
||||
void ffPrintBrightnessHelpFormat(void)
|
||||
{
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BRIGHTNESS_MODULE_NAME, "{1}", FF_BRIGHTNESS_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Screen brightness (percentage) - percentage",
|
||||
"Screen brightness (percentage num) - percentage",
|
||||
"Screen name - name",
|
||||
"Maximum brightness value - max",
|
||||
"Minimum brightness value - min",
|
||||
"Current brightness value - current",
|
||||
"Screen brightness (percentage bar) - percentage-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_CPUUSAGE_DISPLAY_NAME "CPU Usage"
|
||||
#define FF_CPUUSAGE_NUM_FORMAT_ARGS 5
|
||||
#define FF_CPUUSAGE_NUM_FORMAT_ARGS 8
|
||||
|
||||
void ffPrintCPUUsage(FFCPUUsageOptions* options)
|
||||
{
|
||||
@ -73,18 +73,27 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY avgStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&avgStr, avgValue, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY minStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&minStr, minValue, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY maxStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&maxStr, maxValue, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY avgNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&avgNum, avgValue, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY avgBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&avgBar, avgValue, options->percent, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY minNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&minNum, minValue, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY minBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&minBar, minValue, options->percent, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY maxNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&maxNum, maxValue, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY maxBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&maxBar, maxValue, options->percent, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_CPUUSAGE_NUM_FORMAT_ARGS, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &avgStr, "avg"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &maxStr, "max"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &avgNum, "avg"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &maxNum, "max"},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &maxIndex, "max-index"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &minStr, "min"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &minNum, "min"},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &minIndex, "min-index"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &avgBar, "avg-bar"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &maxBar, "max-bar"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &minBar, "min-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -167,11 +176,14 @@ void ffGenerateCPUUsageJsonResult(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yy
|
||||
void ffPrintCPUUsageHelpFormat(void)
|
||||
{
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_CPUUSAGE_MODULE_NAME, "{1}", FF_CPUUSAGE_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"CPU usage (percentage, average) - avg",
|
||||
"CPU usage (percentage, maximum) - max",
|
||||
"CPU usage (percentage num, average) - avg",
|
||||
"CPU usage (percentage num, maximum) - max",
|
||||
"CPU core index of maximum usage - max-index",
|
||||
"CPU usage (percentage, minimum) - min",
|
||||
"CPU usage (percentage num, minimum) - min",
|
||||
"CPU core index of minimum usage - min-index",
|
||||
"CPU usage (percentage bar, average) - avg-bar",
|
||||
"CPU usage (percentage bar, maximum) - max-bar",
|
||||
"CPU usage (percentage bar, minimum) - min-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "modules/disk/disk.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_DISK_NUM_FORMAT_ARGS 12
|
||||
#define FF_DISK_NUM_FORMAT_ARGS 14
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
|
||||
static void printDisk(FFDiskOptions* options, const FFDisk* disk)
|
||||
@ -104,11 +104,16 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY bytesPercentageStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&bytesPercentageStr, bytesPercentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY filesPercentageStr = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY bytesPercentageNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&bytesPercentageNum, bytesPercentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY bytesPercentageBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs);
|
||||
|
||||
double filesPercentage = disk->filesTotal > 0 ? ((double) disk->filesUsed / (double) disk->filesTotal) * 100.0 : 0;
|
||||
ffPercentAppendNum(&filesPercentageStr, filesPercentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY filesPercentageNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&filesPercentageNum, filesPercentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY filesPercentageBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&filesPercentageBar, filesPercentage, options->percent, &options->moduleArgs);
|
||||
|
||||
bool isExternal = !!(disk->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT);
|
||||
bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT);
|
||||
@ -117,16 +122,18 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
|
||||
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISK_NUM_FORMAT_ARGS, ((FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty, "size-used"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty, "size-total"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bytesPercentageStr, "size-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bytesPercentageNum, "size-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &disk->filesUsed, "files-used"},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &disk->filesTotal, "files-total"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &filesPercentageStr, "files-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &filesPercentageNum, "files-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &isExternal, "is-external"},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &isHidden, "is-hidden"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &disk->filesystem, "filesystem"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &disk->name, "name"},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &isReadOnly, "is-readonly"},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, ffTimeToShortStr(disk->createTime), "create-time"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bytesPercentageBar, "size-percentage-bar"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &filesPercentageBar, "files-percentage-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -430,16 +437,18 @@ void ffPrintDiskHelpFormat(void)
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_DISK_MODULE_NAME, "{1} / {2} ({3}) - {9}", FF_DISK_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Size used - size-used",
|
||||
"Size total - size-total",
|
||||
"Size percentage - size-percentage",
|
||||
"Size percentage num - size-percentage",
|
||||
"Files used - files-used",
|
||||
"Files total - files-total",
|
||||
"Files percentage - files-percentage",
|
||||
"Files percentage num - files-percentage",
|
||||
"True if external volume - is-external",
|
||||
"True if hidden volume - is-hidden",
|
||||
"Filesystem - filesystem",
|
||||
"Label / name - name",
|
||||
"True if read-only - is-readonly",
|
||||
"Create time in local timezone - create-time",
|
||||
"Size percentage bar - size-percentage-bar",
|
||||
"Files percentage bar - files-percentage-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
@ -448,7 +457,7 @@ void ffInitDiskOptions(FFDiskOptions* options)
|
||||
ffOptionInitModuleBaseInfo(
|
||||
&options->moduleInfo,
|
||||
FF_DISK_MODULE_NAME,
|
||||
"Print partitions, space usage, disk type, etc",
|
||||
"Print partitions, space usage, file system, etc",
|
||||
ffParseDiskCommandOptions,
|
||||
ffParseDiskJsonObject,
|
||||
ffPrintDisk,
|
||||
|
@ -30,7 +30,7 @@ void ffPrintEditor(FFEditorOptions* options)
|
||||
{
|
||||
ffStrbufWriteTo(&result.exe, stdout);
|
||||
if (result.version.length)
|
||||
printf(" (%s)", result.version.chars);
|
||||
printf(" %s", result.version.chars);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "modules/gamepad/gamepad.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_GAMEPAD_NUM_FORMAT_ARGS 3
|
||||
#define FF_GAMEPAD_NUM_FORMAT_ARGS 4
|
||||
|
||||
static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device, uint8_t index)
|
||||
{
|
||||
@ -25,13 +25,16 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageStr, device->battery, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageNum, device->battery, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs);
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_GAMEPAD_NUM_FORMAT_ARGS, ((FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name, "name"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->serial, "serial"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr, "battery-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageNum, "battery-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageBar, "battery-percentage-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -138,7 +141,8 @@ void ffPrintGamepadHelpFormat(void)
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_GAMEPAD_MODULE_NAME, "{1} ({3})", FF_GAMEPAD_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Name - name",
|
||||
"Serial number - serial",
|
||||
"Battery percentage - battery-percentage",
|
||||
"Battery percentage num - battery-percentage",
|
||||
"Battery percentage bar - battery-percentage-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,9 @@ void ffPrintIcons(FFIconsOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.icons2, "icons2"},
|
||||
}));
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&result.icons1);
|
||||
ffStrbufDestroy(&result.icons2);
|
||||
}
|
||||
|
||||
bool ffParseIconsCommandOptions(FFIconsOptions* options, const char* key, const char* value)
|
||||
@ -94,6 +97,9 @@ void ffGenerateIconsJsonResult(FF_MAYBE_UNUSED FFIconsOptions* options, yyjson_m
|
||||
yyjson_mut_val* icons = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
yyjson_mut_obj_add_strbuf(doc, icons, "icons1", &result.icons1);
|
||||
yyjson_mut_obj_add_strbuf(doc, icons, "icons2", &result.icons2);
|
||||
|
||||
ffStrbufDestroy(&result.icons1);
|
||||
ffStrbufDestroy(&result.icons2);
|
||||
}
|
||||
|
||||
void ffPrintIconsHelpFormat(void)
|
||||
|
@ -105,7 +105,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options)
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
|
||||
printIp(ip, true);
|
||||
printIp(ip, !(options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT));
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "modules/memory/memory.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_MEMORY_NUM_FORMAT_ARGS 3
|
||||
#define FF_MEMORY_NUM_FORMAT_ARGS 4
|
||||
|
||||
void ffPrintMemory(FFMemoryOptions* options)
|
||||
{
|
||||
@ -56,12 +56,15 @@ void ffPrintMemory(FFMemoryOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageStr, percentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageNum, percentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_MEMORY_NUM_FORMAT_ARGS, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty, "used"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty, "total"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr, "percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageNum, "percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageBar, "percentage-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -130,7 +133,8 @@ void ffPrintMemoryHelpFormat(void)
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_MEMORY_MODULE_NAME, "{1} / {2} ({3})", FF_MEMORY_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Used size - used",
|
||||
"Total size - total",
|
||||
"Percentage used - percentage",
|
||||
"Percentage used (num) - percentage",
|
||||
"Percentage used (bar) - percentage-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options)
|
||||
ffStrbufInit(&result.renderer);
|
||||
ffStrbufInit(&result.vendor);
|
||||
ffStrbufInit(&result.slv);
|
||||
result.library = "Unknown";
|
||||
ffStrbufInit(&result.library);
|
||||
|
||||
const char* error = ffDetectOpenGL(options, &result);
|
||||
if(error)
|
||||
@ -34,7 +34,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.renderer, "renderer"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.vendor, "vendor"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.slv, "slv"},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result.library, "library"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.library, "library"},
|
||||
}));
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options)
|
||||
ffStrbufDestroy(&result.renderer);
|
||||
ffStrbufDestroy(&result.vendor);
|
||||
ffStrbufDestroy(&result.slv);
|
||||
ffStrbufDestroy(&result.library);
|
||||
}
|
||||
|
||||
bool ffParseOpenGLCommandOptions(FFOpenGLOptions* options, const char* key, const char* value)
|
||||
@ -51,8 +52,7 @@ bool ffParseOpenGLCommandOptions(FFOpenGLOptions* options, const char* key, cons
|
||||
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
|
||||
return true;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if (ffStrEqualsIgnCase(key, "library"))
|
||||
if (ffStrEqualsIgnCase(subKey, "library"))
|
||||
{
|
||||
options->library = (FFOpenGLLibrary) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
|
||||
{ "auto", FF_OPENGL_LIBRARY_AUTO },
|
||||
@ -61,8 +61,8 @@ bool ffParseOpenGLCommandOptions(FFOpenGLOptions* options, const char* key, cons
|
||||
{ "osmesa", FF_OPENGL_LIBRARY_OSMESA },
|
||||
{}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -80,7 +80,6 @@ void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module)
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
continue;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if (ffStrEqualsIgnCase(key, "library"))
|
||||
{
|
||||
int value;
|
||||
@ -97,7 +96,6 @@ void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module)
|
||||
options->library = (FFOpenGLLibrary) value;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key);
|
||||
}
|
||||
@ -110,7 +108,6 @@ void ffGenerateOpenGLJsonConfig(FFOpenGLOptions* options, yyjson_mut_doc* doc, y
|
||||
|
||||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if (options->library != defaultOptions.library)
|
||||
{
|
||||
switch (options->library)
|
||||
@ -129,7 +126,6 @@ void ffGenerateOpenGLJsonConfig(FFOpenGLOptions* options, yyjson_mut_doc* doc, y
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ffGenerateOpenGLJsonResult(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
@ -139,6 +135,7 @@ void ffGenerateOpenGLJsonResult(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson
|
||||
ffStrbufInit(&result.renderer);
|
||||
ffStrbufInit(&result.vendor);
|
||||
ffStrbufInit(&result.slv);
|
||||
ffStrbufInit(&result.library);
|
||||
|
||||
const char* error = ffDetectOpenGL(options, &result);
|
||||
if(error != NULL)
|
||||
@ -152,13 +149,14 @@ void ffGenerateOpenGLJsonResult(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "renderer", &result.renderer);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &result.vendor);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "slv", &result.slv);
|
||||
yyjson_mut_obj_add_str(doc, obj, "library", result.library);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "library", &result.library);
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&result.version);
|
||||
ffStrbufDestroy(&result.renderer);
|
||||
ffStrbufDestroy(&result.vendor);
|
||||
ffStrbufDestroy(&result.slv);
|
||||
ffStrbufDestroy(&result.library);
|
||||
}
|
||||
|
||||
void ffPrintOpenGLHelpFormat(void)
|
||||
@ -187,9 +185,7 @@ void ffInitOpenGLOptions(FFOpenGLOptions* options)
|
||||
);
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
options->library = FF_OPENGL_LIBRARY_AUTO;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ffDestroyOpenGLOptions(FFOpenGLOptions* options)
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "common/option.h"
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
|
||||
typedef enum FFOpenGLLibrary
|
||||
{
|
||||
FF_OPENGL_LIBRARY_AUTO,
|
||||
@ -12,14 +11,11 @@ typedef enum FFOpenGLLibrary
|
||||
FF_OPENGL_LIBRARY_GLX,
|
||||
FF_OPENGL_LIBRARY_OSMESA
|
||||
} FFOpenGLLibrary;
|
||||
#endif
|
||||
|
||||
typedef struct FFOpenGLOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
|
||||
FFOpenGLLibrary library;
|
||||
#endif
|
||||
} FFOpenGLOptions;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/wcwidth.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
@ -46,7 +47,7 @@ void ffPrintSeparator(FFSeparatorOptions* options)
|
||||
+ (fqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name
|
||||
ffLogoPrintLine();
|
||||
|
||||
if(options->outputColor.length)
|
||||
if(options->outputColor.length && !instance.config.display.pipe)
|
||||
ffPrintColor(&options->outputColor);
|
||||
if(__builtin_expect(options->string.length == 1, 1))
|
||||
{
|
||||
@ -88,6 +89,8 @@ void ffPrintSeparator(FFSeparatorOptions* options)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(options->outputColor.length && !instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
putchar('\n');
|
||||
setlocale(LC_CTYPE, "C");
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "modules/sound/sound.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_SOUND_NUM_FORMAT_ARGS 4
|
||||
#define FF_SOUND_NUM_FORMAT_ARGS 5
|
||||
|
||||
static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, uint8_t index)
|
||||
{
|
||||
@ -46,14 +46,17 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageStr, device->volume, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageNum, device->volume, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&percentageBar, device->volume, options->percent, &options->moduleArgs);
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_SOUND_NUM_FORMAT_ARGS, ((FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &device->main, "is-main"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name, "name"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr, "volume-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageNum, "volume-percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier, "identifier"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageBar, "volume-percentage-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -228,8 +231,9 @@ void ffPrintSoundHelpFormat(void)
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_SOUND_MODULE_NAME, "{2} ({3}%)", FF_SOUND_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Is main sound device - is-main",
|
||||
"Device name - name",
|
||||
"Volume (in percentage) - volume-percentage",
|
||||
"Volume (in percentage num) - volume-percentage",
|
||||
"Identifier - identifier",
|
||||
"Volume (in percentage bar) - volume-percentage-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "modules/swap/swap.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_SWAP_NUM_FORMAT_ARGS 3
|
||||
#define FF_SWAP_NUM_FORMAT_ARGS 4
|
||||
|
||||
void ffPrintSwap(FFSwapOptions* options)
|
||||
{
|
||||
@ -65,12 +65,15 @@ void ffPrintSwap(FFSwapOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY percentageStr = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageStr, percentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentageNum, percentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_SWAP_NUM_FORMAT_ARGS, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty, "used"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty, "total"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageStr, "percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageNum, "percentage"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentageBar, "percentage-bar"},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -139,7 +142,8 @@ void ffPrintSwapHelpFormat(void)
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_SWAP_MODULE_NAME, "{1} / {2} ({3})", FF_SWAP_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Used size - used",
|
||||
"Total size - total",
|
||||
"Percentage used - percentage",
|
||||
"Percentage used (num) - percentage",
|
||||
"Percentage used (bar) - percentage-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,9 @@ void ffPrintTheme(FFThemeOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result.theme2, "theme2"},
|
||||
}));
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&result.theme1);
|
||||
ffStrbufDestroy(&result.theme2);
|
||||
}
|
||||
|
||||
bool ffParseThemeCommandOptions(FFThemeOptions* options, const char* key, const char* value)
|
||||
@ -94,6 +97,9 @@ void ffGenerateThemeJsonResult(FF_MAYBE_UNUSED FFThemeOptions* options, yyjson_m
|
||||
yyjson_mut_val* theme = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
yyjson_mut_obj_add_strbuf(doc, theme, "theme1", &result.theme1);
|
||||
yyjson_mut_obj_add_strbuf(doc, theme, "theme2", &result.theme2);
|
||||
|
||||
ffStrbufDestroy(&result.theme1);
|
||||
ffStrbufDestroy(&result.theme2);
|
||||
}
|
||||
|
||||
void ffPrintThemeHelpFormat(void)
|
||||
|
@ -8,4 +8,6 @@ typedef struct FFWifiOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFColorRangeConfig percent;
|
||||
} FFWifiOptions;
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "modules/wifi/wifi.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_WIFI_NUM_FORMAT_ARGS 10
|
||||
#define FF_WIFI_NUM_FORMAT_ARGS 11
|
||||
|
||||
void ffPrintWifi(FFWifiOptions* options)
|
||||
{
|
||||
@ -30,22 +30,56 @@ void ffPrintWifi(FFWifiOptions* options)
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_WIFI_MODULE_NAME, moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if(item->conn.ssid.length)
|
||||
{
|
||||
ffStrbufWriteTo(&item->conn.ssid, stdout);
|
||||
if(item->conn.protocol.length)
|
||||
printf(" - %s", item->conn.protocol.chars);
|
||||
if(item->conn.security.length)
|
||||
printf(" - %s", item->conn.security.chars);
|
||||
putchar('\n');
|
||||
if(item->conn.signalQuality == item->conn.signalQuality)
|
||||
{
|
||||
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
|
||||
{
|
||||
ffPercentAppendBar(&buffer, item->conn.signalQuality, options->percent, &options->moduleArgs);
|
||||
ffStrbufAppendC(&buffer, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
if (!(instance.config.display.percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT))
|
||||
{
|
||||
ffStrbufAppend(&buffer, &item->conn.ssid);
|
||||
|
||||
if(item->conn.protocol.length)
|
||||
{
|
||||
ffStrbufAppendS(&buffer, " - ");
|
||||
ffStrbufAppend(&buffer, &item->conn.protocol);
|
||||
}
|
||||
if(item->conn.security.length)
|
||||
{
|
||||
ffStrbufAppendS(&buffer, " - ");
|
||||
ffStrbufAppend(&buffer, &item->conn.security);
|
||||
}
|
||||
ffStrbufAppendC(&buffer, ' ');
|
||||
}
|
||||
|
||||
if(item->conn.signalQuality == item->conn.signalQuality)
|
||||
{
|
||||
if(instance.config.display.percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
|
||||
ffPercentAppendNum(&buffer, item->conn.signalQuality, options->percent, buffer.length > 0, &options->moduleArgs);
|
||||
}
|
||||
|
||||
ffStrbufTrimRight(&buffer, ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
puts(item->inf.status.chars);
|
||||
ffStrbufAppend(&buffer, &item->inf.status);
|
||||
}
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY percentNum = ffStrbufCreate();
|
||||
ffPercentAppendNum(&percentNum, item->conn.signalQuality, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY percentBar = ffStrbufCreate();
|
||||
ffPercentAppendBar(&percentBar, item->conn.signalQuality, options->percent, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_WIFI_MODULE_NAME, moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_WIFI_NUM_FORMAT_ARGS, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.description, "inf-desc"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.status, "inf-status"},
|
||||
@ -53,10 +87,11 @@ void ffPrintWifi(FFWifiOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid, "ssid"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress, "mac-address"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.protocol, "protocol"},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.signalQuality, "signal-quality"},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &percentNum, "signal-quality"},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate, "rx-rate"},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.txRate, "tx-rate"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.security, "security"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &percentBar, "signal-quality-bar"},
|
||||
}));
|
||||
}
|
||||
|
||||
@ -77,6 +112,9 @@ bool ffParseWifiCommandOptions(FFWifiOptions* options, const char* key, const ch
|
||||
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
|
||||
return true;
|
||||
|
||||
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -93,6 +131,9 @@ void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module)
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
continue;
|
||||
|
||||
if (ffPercentParseJsonObject(key, val, &options->percent))
|
||||
continue;
|
||||
|
||||
ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key);
|
||||
}
|
||||
}
|
||||
@ -103,6 +144,8 @@ void ffGenerateWifiJsonConfig(FFWifiOptions* options, yyjson_mut_doc* doc, yyjso
|
||||
ffInitWifiOptions(&defaultOptions);
|
||||
|
||||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
|
||||
|
||||
ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent);
|
||||
}
|
||||
|
||||
void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
@ -156,10 +199,11 @@ void ffPrintWifiHelpFormat(void)
|
||||
"Connection SSID - ssid",
|
||||
"Connection BSSID - bssid",
|
||||
"Connection protocol - protocol",
|
||||
"Connection signal quality (percentage) - signal-quality",
|
||||
"Connection signal quality (percentage num) - signal-quality",
|
||||
"Connection RX rate - rx-rate",
|
||||
"Connection TX rate - tx-rate",
|
||||
"Connection Security algorithm - security",
|
||||
"Connection signal quality (percentage bar) - signal-quality-bar",
|
||||
}));
|
||||
}
|
||||
|
||||
@ -177,6 +221,8 @@ void ffInitWifiOptions(FFWifiOptions* options)
|
||||
ffGenerateWifiJsonConfig
|
||||
);
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
|
||||
options->percent = (FFColorRangeConfig) { 50, 20 };
|
||||
}
|
||||
|
||||
void ffDestroyWifiOptions(FFWifiOptions* options)
|
||||
|
@ -27,6 +27,8 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va
|
||||
ffStrbufSetS(&options->libChafa, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "z"))
|
||||
ffStrbufSetS(&options->libZ, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "egl"))
|
||||
ffStrbufSetS(&options->libEGL, yyjson_get_str(val));
|
||||
|
||||
#ifdef __ANDROID__
|
||||
else if (ffStrEqualsIgnCase(key, "freetype"))
|
||||
@ -54,8 +56,6 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va
|
||||
ffStrbufSetS(&options->libXFConf, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "rpm"))
|
||||
ffStrbufSetS(&options->librpm, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "egl"))
|
||||
ffStrbufSetS(&options->libEGL, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "glx"))
|
||||
ffStrbufSetS(&options->libGLX, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "osmesa"))
|
||||
@ -94,6 +94,8 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key
|
||||
ffOptionParseString(key, value, &options->libChafa);
|
||||
else if(ffStrEqualsIgnCase(subkey, "z"))
|
||||
ffOptionParseString(key, value, &options->libZ);
|
||||
else if(ffStrEqualsIgnCase(subkey, "egl"))
|
||||
ffOptionParseString(key, value, &options->libEGL);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
else if(ffStrEqualsIgnCase(subkey, "freetype"))
|
||||
@ -121,8 +123,6 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key
|
||||
ffOptionParseString(key, value, &options->libXFConf);
|
||||
else if(ffStrEqualsIgnCase(subkey, "rpm"))
|
||||
ffOptionParseString(key, value, &options->librpm);
|
||||
else if(ffStrEqualsIgnCase(subkey, "egl"))
|
||||
ffOptionParseString(key, value, &options->libEGL);
|
||||
else if(ffStrEqualsIgnCase(subkey, "glx"))
|
||||
ffOptionParseString(key, value, &options->libGLX);
|
||||
else if(ffStrEqualsIgnCase(subkey, "osmesa"))
|
||||
@ -184,7 +184,10 @@ void ffOptionsGenerateLibraryJsonConfig(FFOptionsLibrary* options, yyjson_mut_do
|
||||
if (!ffStrbufEqual(&options->libZ, &defaultOptions.libZ))
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "z", &options->libZ);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if (!ffStrbufEqual(&options->libEGL, &defaultOptions.libEGL))
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "egl", &options->libEGL);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
|
||||
if (!ffStrbufEqual(&options->libWayland, &defaultOptions.libWayland))
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "wayland", &options->libWayland);
|
||||
|
||||
@ -215,9 +218,6 @@ void ffOptionsGenerateLibraryJsonConfig(FFOptionsLibrary* options, yyjson_mut_do
|
||||
if (!ffStrbufEqual(&options->librpm, &defaultOptions.librpm))
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "rpm", &options->librpm);
|
||||
|
||||
if (!ffStrbufEqual(&options->libEGL, &defaultOptions.libEGL))
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "egl", &options->libEGL);
|
||||
|
||||
if (!ffStrbufEqual(&options->libGLX, &defaultOptions.libGLX))
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "glx", &options->libGLX);
|
||||
|
||||
|
@ -10,6 +10,7 @@ typedef struct FFOptionsLibrary
|
||||
FFstrbuf libImageMagick;
|
||||
FFstrbuf libChafa;
|
||||
FFstrbuf libZ;
|
||||
FFstrbuf libEGL;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
FFstrbuf libfreetype;
|
||||
@ -26,7 +27,6 @@ typedef struct FFOptionsLibrary
|
||||
FFstrbuf libDBus;
|
||||
FFstrbuf libXFConf;
|
||||
FFstrbuf librpm;
|
||||
FFstrbuf libEGL;
|
||||
FFstrbuf libGLX;
|
||||
FFstrbuf libOSMesa;
|
||||
FFstrbuf libPulse;
|
||||
|
112
src/util/base64.c
Normal file
112
src/util/base64.c
Normal file
@ -0,0 +1,112 @@
|
||||
#include "base64.h"
|
||||
|
||||
// https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145
|
||||
void ffBase64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output)
|
||||
{
|
||||
static const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
char *out = output;
|
||||
const char *ends = str + (size - size % 3);
|
||||
while (str != ends)
|
||||
{
|
||||
uint32_t n = __builtin_bswap32(*(uint32_t *)str);
|
||||
*out++ = chars[(n >> 26) & 63];
|
||||
*out++ = chars[(n >> 20) & 63];
|
||||
*out++ = chars[(n >> 14) & 63];
|
||||
*out++ = chars[(n >> 8) & 63];
|
||||
str += 3;
|
||||
}
|
||||
|
||||
if (size % 3 == 1)
|
||||
{
|
||||
uint64_t n = (uint64_t)*str << 16;
|
||||
*out++ = chars[(n >> 18) & 63];
|
||||
*out++ = chars[(n >> 12) & 63];
|
||||
*out++ = '=';
|
||||
*out++ = '=';
|
||||
}
|
||||
else if (size % 3 == 2)
|
||||
{
|
||||
uint64_t n = (uint64_t)*str++ << 16;
|
||||
n |= (uint64_t)*str << 8;
|
||||
*out++ = chars[(n >> 18) & 63];
|
||||
*out++ = chars[(n >> 12) & 63];
|
||||
*out++ = chars[(n >> 6) & 63];
|
||||
*out++ = '=';
|
||||
}
|
||||
*out = '\0';
|
||||
*out_size = (uint32_t)(out - output);
|
||||
}
|
||||
|
||||
static uint8_t decode_table[256];
|
||||
|
||||
void init_decode_table()
|
||||
{
|
||||
uint8_t ch = 0;
|
||||
do
|
||||
{
|
||||
int32_t code = -1;
|
||||
if (ch >= 'A' && ch <= 'Z')
|
||||
code = ch - 0x41;
|
||||
if (ch >= 'a' && ch <= 'z')
|
||||
code = ch - 0x47;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
code = ch + 0x04;
|
||||
if (ch == '+' || ch == '-')
|
||||
code = 0x3E;
|
||||
if (ch == '/' || ch == '_')
|
||||
code = 0x3F;
|
||||
decode_table[ch] = (uint8_t) code;
|
||||
} while (ch++ < 0xFF);
|
||||
}
|
||||
|
||||
#define next_char(x) uint8_t x = decode_table[(uint8_t) *str++];
|
||||
|
||||
bool ffBase64DecodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output)
|
||||
{
|
||||
if (*(uint64_t*) decode_table == 0)
|
||||
init_decode_table();
|
||||
|
||||
char *out = output;
|
||||
while (size > 0 && (str[size - 1] == '\n' || str[size - 1] == '\r' || str[size - 1] == '='))
|
||||
size--;
|
||||
|
||||
const char *ends = str + size - 4;
|
||||
while (true)
|
||||
{
|
||||
if (str > ends)
|
||||
break;
|
||||
while (*str == '\n' || *str == '\r')
|
||||
str++;
|
||||
|
||||
if (str > ends)
|
||||
break;
|
||||
next_char(a);
|
||||
next_char(b);
|
||||
next_char(c);
|
||||
next_char(d);
|
||||
|
||||
*out++ = (char)(a << 2 | b >> 4);
|
||||
*out++ = (char)(b << 4 | c >> 2);
|
||||
*out++ = (char)(c << 6 | d >> 0);
|
||||
}
|
||||
|
||||
uint8_t mod = (uint8_t) (ends - str + 4) % 4;
|
||||
if (mod == 2)
|
||||
{
|
||||
next_char(a);
|
||||
next_char(b);
|
||||
*out++ = (char)(a << 2 | b >> 4);
|
||||
}
|
||||
else if (mod == 3)
|
||||
{
|
||||
next_char(a);
|
||||
next_char(b);
|
||||
next_char(c);
|
||||
*out++ = (char)(a << 2 | b >> 4);
|
||||
*out++ = (char)(b << 4 | c >> 2);
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
*out_size = (uint32_t) (out - output);
|
||||
return true;
|
||||
}
|
23
src/util/base64.h
Normal file
23
src/util/base64.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffBase64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output);
|
||||
static inline FFstrbuf ffBase64EncodeStrbuf(const FFstrbuf* in)
|
||||
{
|
||||
FFstrbuf out = ffStrbufCreateA(10 + in->length * 4 / 3);
|
||||
ffBase64EncodeRaw(in->length, in->chars, &out.length, out.chars);
|
||||
assert(out.length < out.allocated);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool ffBase64DecodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output);
|
||||
static inline FFstrbuf ffBase64DecodeStrbuf(const FFstrbuf* in)
|
||||
{
|
||||
FFstrbuf out = ffStrbufCreateA(10 + in->length * 3 / 4);
|
||||
ffBase64DecodeRaw(in->length, in->chars, &out.length, out.chars);
|
||||
assert(out.length < out.allocated);
|
||||
|
||||
return out;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user