Merge pull request #1083 from fastfetch-cli/dev

Release: v2.18.0
This commit is contained in:
Carter Li 2024-07-10 15:39:24 +08:00 committed by GitHub
commit 5060c265a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
67 changed files with 2981 additions and 598 deletions

View File

@ -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

View File

@ -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:

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.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

View File

@ -356,7 +356,6 @@ __fastfetch_completion()
local FF_OPTIONS_PATH=(
"-c"
"--config"
"--lib-pci"
"--lib-vulkan"
"--lib-wayland"
"--lib-xcb-randr"

View File

@ -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
View File

@ -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
View File

@ -1 +1 @@
fastfetch_2.17.1_source.buildinfo universe/utils optional
fastfetch_2.17.2_source.buildinfo universe/utils optional

View File

@ -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"
],

View File

@ -47,6 +47,7 @@
"cpuusage",
{
"type": "gpu",
"driverSpecific": true,
"temp": true
},
"memory",
@ -63,6 +64,7 @@
"showIpv6": true,
"showMac": true
},
"dns",
"wifi",
"datetime",
"locale",

View File

@ -49,6 +49,7 @@
"cpuusage",
{
"type": "gpu",
"driverSpecific": true,
"temp": true
},
"memory",
@ -65,6 +66,7 @@
"showIpv6": true,
"showMac": true
},
"dns",
"wifi",
"datetime",
"locale",

View File

@ -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"
}

View File

@ -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;

View File

@ -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);
/**

View File

@ -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
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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",

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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)) &registry_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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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,

View 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

View File

@ -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";
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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)

View File

@ -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
View 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
View File

@ -0,0 +1,13 @@
.':ldkOOOOkxo:,.
.:d0KKXXXXXXXXXXKkl,
.;xOOO0000KKKKXXXXXXX0l.
.cxxxkkkkOOO0000KKKKXXXXx'
;ool;,,,,;coxkOOOO0000KKKd.
.clc'.........:oxkkkkOOOO0O,
.ccc:ccclc:,....,:oddxxdxkO;
cllllccccccc;'........'lxx.
'ooooolllllccc:;,''',,coo,
,ddddooooollllllccccccl'
cxxxdddddooooollllc;
,dxxxxxddddddol.
.';::,.

View File

@ -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"},

View File

@ -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)
{

View File

@ -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",
}));
}

View File

@ -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",
}));
}

View File

@ -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",
}));
}

View File

@ -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",
}));
}

View File

@ -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,

View File

@ -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
{

View File

@ -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",
}));
}

View File

@ -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)

View File

@ -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

View File

@ -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",
}));
}

View File

@ -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)

View File

@ -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;

View File

@ -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");
}

View File

@ -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",
}));
}

View File

@ -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",
}));
}

View File

@ -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)

View File

@ -8,4 +8,6 @@ typedef struct FFWifiOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
FFColorRangeConfig percent;
} FFWifiOptions;

View File

@ -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)

View File

@ -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);

View File

@ -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
View 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
View 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;
}