Date: Mon, 9 Sep 2024 21:25:22 GMT From: Christoph Moench-Tegeder <cmt@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: 191df03872e5 - main - www/firefox-esr: update to 128.2.0 Message-ID: <202409092125.489LPMne088328@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by cmt: URL: https://cgit.FreeBSD.org/ports/commit/?id=191df03872e5f2ed15cef9ca9ef25cb5d6905c31 commit 191df03872e5f2ed15cef9ca9ef25cb5d6905c31 Author: Christoph Moench-Tegeder <cmt@FreeBSD.org> AuthorDate: 2024-09-09 21:24:38 +0000 Commit: Christoph Moench-Tegeder <cmt@FreeBSD.org> CommitDate: 2024-09-09 21:24:38 +0000 www/firefox-esr: update to 128.2.0 Release Notes: https://www.mozilla.org/en-US/firefox/128.2.0/releasenotes/ --- www/firefox-esr/Makefile | 10 +- www/firefox-esr/distinfo | 6 +- www/firefox-esr/files/patch-addon-search | 20 +- .../files/patch-browser-app-nsBrowserApp.cpp | 14 +- www/firefox-esr/files/patch-bug1427152 | 10 - www/firefox-esr/files/patch-bug1559213 | 57 +- www/firefox-esr/files/patch-bug1626236 | 40 +- www/firefox-esr/files/patch-bug1628567 | 32 - www/firefox-esr/files/patch-bug1680982 | 388 - www/firefox-esr/files/patch-bug1841919 | 75 - www/firefox-esr/files/patch-bug1873379 | 34 - www/firefox-esr/files/patch-bug1876366 | 23 + www/firefox-esr/files/patch-bug847568 | 100 +- .../files/patch-dom_media_flac_FlacDecoder.cpp | 23 - ...edia_webrtc_third__party__build_webrtc.mozbuild | 27 + .../files/patch-gfx_skia_skia_src_base_SkEndian.h | 24 +- .../files/patch-gfx_skia_skia_src_core_SkCpu.cpp | 32 - ...patch-gfx_skia_skia_src_core_SkRasterPipeline.h | 14 +- www/firefox-esr/files/patch-libwebrtc-generated | 38475 ++++++++++--------- www/firefox-esr/files/patch-llvm18 | 199 - www/firefox-esr/files/patch-mozglue_misc_SSE.h | 84 + www/firefox-esr/files/patch-pipewire_init | 33 +- ...patch-python_mozbuild_mozbuild_gn__processor.py | 17 +- www/firefox-esr/files/patch-rust-1.78.0 | 3582 -- ...rd__party_libwebrtc_build_config_BUILDCONFIG.gn | 116 +- ..._desktop__capture_linux_wayland__egl__dmabuf.cc | 26 + .../files/patch-toolkit_xre_glxtest.cpp | 17 - .../files/patch-tools_profiler_core_patform.cpp | 51 - 28 files changed, 21112 insertions(+), 22417 deletions(-) diff --git a/www/firefox-esr/Makefile b/www/firefox-esr/Makefile index 50e0c2f90e12..1a85da360c7d 100644 --- a/www/firefox-esr/Makefile +++ b/www/firefox-esr/Makefile @@ -1,5 +1,5 @@ PORTNAME= firefox -DISTVERSION= 115.15.0 +DISTVERSION= 128.2.0 PORTEPOCH= 1 CATEGORIES= www wayland MASTER_SITES= MOZILLA/${PORTNAME}/releases/${DISTVERSION}esr/source \ @@ -12,14 +12,14 @@ COMMENT= Web browser based on the browser portion of Mozilla WWW= https://www.mozilla.com/firefox BUILD_DEPENDS= nspr>=4.32:devel/nspr \ - nss>=3.90:security/nss \ + nss>=3.101:security/nss \ icu>=73.1,1:devel/icu \ libevent>=2.1.8:devel/libevent \ - harfbuzz>=7.3.0:print/harfbuzz \ + harfbuzz>=8.5.0:print/harfbuzz \ graphite2>=1.3.14:graphics/graphite2 \ - png>=1.6.39:graphics/png \ + png>=1.6.43:graphics/png \ dav1d>=1.0.0:multimedia/dav1d \ - libvpx>=1.13.0:multimedia/libvpx \ + libvpx>=1.14.0:multimedia/libvpx \ ${PYTHON_PKGNAMEPREFIX}sqlite3>0:databases/py-sqlite3@${PY_FLAVOR} \ v4l_compat>0:multimedia/v4l_compat \ autoconf2.13:devel/autoconf2.13 \ diff --git a/www/firefox-esr/distinfo b/www/firefox-esr/distinfo index 1be978c18a8e..69a755a38707 100644 --- a/www/firefox-esr/distinfo +++ b/www/firefox-esr/distinfo @@ -1,3 +1,3 @@ -TIMESTAMP = 1724686968 -SHA256 (firefox-115.15.0esr.source.tar.xz) = effed92aa0d961871614c611259dfe3eab72e5ebfe8f2405f9bc92c5e7feae81 -SIZE (firefox-115.15.0esr.source.tar.xz) = 507920832 +TIMESTAMP = 1725799196 +SHA256 (firefox-128.2.0esr.source.tar.xz) = 9617a1e547d373fe25c2f5477ba1b2fc482b642dc54adf28d815fc36ed72d0c2 +SIZE (firefox-128.2.0esr.source.tar.xz) = 560831528 diff --git a/www/firefox-esr/files/patch-addon-search b/www/firefox-esr/files/patch-addon-search index b6dbf7924b43..a0adc808c9fa 100644 --- a/www/firefox-esr/files/patch-addon-search +++ b/www/firefox-esr/files/patch-addon-search @@ -2,10 +2,10 @@ https://github.com/mozilla/addons/issues/708 https://github.com/mozilla/addons-frontend/issues/4610 diff --git browser/app/profile/firefox.js browser/app/profile/firefox.js -index 621900f90fc1..401ef9074bd0 100644 +index 5964d40ca3a3..ed81b06af8d5 100644 --- browser/app/profile/firefox.js +++ browser/app/profile/firefox.js -@@ -38,7 +38,7 @@ pref("extensions.postDownloadThirdPartyPrompt", true); +@@ -39,7 +39,7 @@ pref("extensions.postDownloadThirdPartyPrompt", true); // Preferences for AMO integration pref("extensions.getAddons.cache.enabled", true); pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/api/v4/addons/search/?guid=%IDS%&lang=%LOCALE%"); @@ -14,7 +14,7 @@ index 621900f90fc1..401ef9074bd0 100644 pref("extensions.getAddons.link.url", "https://addons.mozilla.org/%LOCALE%/firefox/"); pref("extensions.getAddons.langpacks.url", "https://services.addons.mozilla.org/api/v4/addons/language-tools/?app=firefox&type=language&appversion=%VERSION%"); pref("extensions.getAddons.discovery.api_url", "https://services.addons.mozilla.org/api/v4/discovery/?lang=%LOCALE%&edition=%DISTRIBUTION%"); -@@ -204,8 +204,8 @@ pref("app.update.langpack.enabled", true); +@@ -214,8 +214,8 @@ pref("app.update.langpack.enabled", true); // .. etc .. // pref("extensions.update.enabled", true); @@ -26,10 +26,10 @@ index 621900f90fc1..401ef9074bd0 100644 // Themes every day diff --git toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs -index f906f244b658..7bb2eb6697c6 100644 +index e854e04b3ce2..27e8247eb886 100644 --- toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs +++ toolkit/mozapps/extensions/internal/AddonRepository.sys.mjs -@@ -596,7 +596,7 @@ export var AddonRepository = { +@@ -715,7 +715,7 @@ export var AddonRepository = { addon.version = String(aEntry.current_version.version); if (Array.isArray(aEntry.current_version.files)) { for (let file of aEntry.current_version.files) { @@ -38,11 +38,11 @@ index f906f244b658..7bb2eb6697c6 100644 if (file.url) { addon.sourceURI = lazy.NetUtil.newURI(file.url); } -diff --git toolkit/mozapps/extensions/internal/XPIDatabase.jsm toolkit/mozapps/extensions/internal/XPIDatabase.jsm -index 03186dad43a4..4053fc6f2702 100644 ---- toolkit/mozapps/extensions/internal/XPIDatabase.jsm -+++ toolkit/mozapps/extensions/internal/XPIDatabase.jsm -@@ -634,7 +634,7 @@ class AddonInternal { +diff --git toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs +index 5d1d2c19706b..4dcba06a95f4 100644 +--- toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs ++++ toolkit/mozapps/extensions/internal/XPIDatabase.sys.mjs +@@ -632,7 +632,7 @@ export class AddonInternal { // Something is causing errors in here try { for (let platform of this.targetPlatforms) { diff --git a/www/firefox-esr/files/patch-browser-app-nsBrowserApp.cpp b/www/firefox-esr/files/patch-browser-app-nsBrowserApp.cpp index 68cb778b95a7..3b9097714e21 100644 --- a/www/firefox-esr/files/patch-browser-app-nsBrowserApp.cpp +++ b/www/firefox-esr/files/patch-browser-app-nsBrowserApp.cpp @@ -1,12 +1,14 @@ ---- browser/app/nsBrowserApp.cpp.orig 2016-09-19 16:19:28 UTC +diff --git browser/app/nsBrowserApp.cpp browser/app/nsBrowserApp.cpp +index 87c2e16..a41f1d9 100644 +--- browser/app/nsBrowserApp.cpp +++ browser/app/nsBrowserApp.cpp -@@ -324,6 +324,9 @@ int main(int argc, char* argv[], char* e - { - mozilla::TimeStamp start = mozilla::TimeStamp::Now(); +@@ -337,6 +337,9 @@ int main(int argc, char* argv[], char* envp[]) { + } + #endif + setenv("MOZ_GMP_PATH", "%%LOCALBASE%%/lib/browser_plugins/symlinks/gecko", 0); + setenv("MOZ_PLUGIN_PATH", "%%LOCALBASE%%/lib/browser_plugins/symlinks/gecko", 0); + #ifdef HAS_DLL_BLOCKLIST - DllBlocklist_Initialize(); - + DllBlocklist_Initialize(gBlocklistInitFlags); + #endif diff --git a/www/firefox-esr/files/patch-bug1427152 b/www/firefox-esr/files/patch-bug1427152 deleted file mode 100644 index 49bd5a581ac8..000000000000 --- a/www/firefox-esr/files/patch-bug1427152 +++ /dev/null @@ -1,10 +0,0 @@ ---- modules/libpref/Preferences.cpp.orig 2023-05-11 21:42:41 UTC -+++ modules/libpref/Preferences.cpp -@@ -6126,6 +6126,7 @@ static const PrefListEntry sDynamicPrefOverrideList[]{ - PREF_LIST_ENTRY("logging.config.LOG_FILE"), - PREF_LIST_ENTRY("media.audio_loopback_dev"), - PREF_LIST_ENTRY("media.decoder-doctor."), -+ PREF_LIST_ENTRY("media.cubeb.backend"), - PREF_LIST_ENTRY("media.cubeb.output_device"), - PREF_LIST_ENTRY("media.getusermedia.fake-camera-name"), - PREF_LIST_ENTRY("media.hls.server.url"), diff --git a/www/firefox-esr/files/patch-bug1559213 b/www/firefox-esr/files/patch-bug1559213 index 49bbb0fb05ff..ae11fb38f989 100644 --- a/www/firefox-esr/files/patch-bug1559213 +++ b/www/firefox-esr/files/patch-bug1559213 @@ -11,10 +11,10 @@ Date: Thu Jun 13 11:53:00 2019 -0700 4 files changed, 34 insertions(+), 3 deletions(-) diff --git config/external/moz.build config/external/moz.build -index ab77121..75595d9 100644 +index 2fc8df57992e..63d18e50a961 100644 --- config/external/moz.build +++ config/external/moz.build -@@ -49,8 +49,9 @@ if not CONFIG["MOZ_SYSTEM_LIBVPX"]: +@@ -40,8 +40,9 @@ if not CONFIG["MOZ_SYSTEM_LIBVPX"]: external_dirs += ["media/libvpx"] if CONFIG["MOZ_AV1"]: @@ -26,30 +26,11 @@ index ab77121..75595d9 100644 if not CONFIG["MOZ_SYSTEM_PNG"]: external_dirs += ["media/libpng"] -diff --git config/system-headers.mozbuild config/system-headers.mozbuild -index a1b58eb..65729f9 100644 ---- config/system-headers.mozbuild -+++ config/system-headers.mozbuild -@@ -1289,6 +1289,14 @@ if CONFIG['MOZ_ENABLE_LIBPROXY']: - 'proxy.h', - ] - -+if CONFIG['MOZ_SYSTEM_AV1']: -+ system_headers += [ -+ 'aom/aom_decoder.h', -+ 'aom/aomdx.h', -+ 'aom/aom_image.h', -+ 'dav1d/dav1d.h', -+ ] -+ - if CONFIG['MOZ_SYSTEM_LIBVPX']: - system_headers += [ - 'vpx_mem/vpx_mem.h', diff --git dom/media/platforms/moz.build dom/media/platforms/moz.build -index 8509aec..eb6f129 100644 +index 5c6e25b3980b..ce99ebfb6d3f 100644 --- dom/media/platforms/moz.build +++ dom/media/platforms/moz.build -@@ -78,6 +78,11 @@ if CONFIG["MOZ_AV1"]: +@@ -81,6 +81,11 @@ if CONFIG["MOZ_AV1"]: "agnostic/AOMDecoder.cpp", "agnostic/DAV1DDecoder.cpp", ] @@ -62,33 +43,33 @@ index 8509aec..eb6f129 100644 if CONFIG["MOZ_OMX"]: EXPORTS += [ diff --git media/ffvpx/libavcodec/moz.build media/ffvpx/libavcodec/moz.build -index 0069865..e806fc8 100644 ---- media/ffvpx/libavcodec/moz.build.orig +index 761fc8cf4cd9..793a5b8697a8 100644 +--- media/ffvpx/libavcodec/moz.build +++ media/ffvpx/libavcodec/moz.build -@@ -108,10 +108,14 @@ - 'vp9prob.c', - 'vp9recon.c' +@@ -120,10 +120,14 @@ if not CONFIG['MOZ_FFVPX_AUDIOONLY']: + 'vp9recon.c', + 'vpx_rac.c', ] - USE_LIBS += [ - 'dav1d', - 'media_libdav1d_asm', - ] + if CONFIG["MOZ_SYSTEM_AV1"]: -+ CFLAGS += CONFIG['MOZ_SYSTEM_LIBDAV1D_CFLAGS'] -+ OS_LIBS += CONFIG['MOZ_SYSTEM_LIBDAV1D_LIBS'] ++ CFLAGS += CONFIG['MOZ_SYSTEM_LIBDAV1D_CFLAGS'] ++ OS_LIBS += CONFIG['MOZ_SYSTEM_LIBDAV1D_LIBS'] + else: -+ USE_LIBS += [ -+ 'dav1d', -+ 'media_libdav1d_asm', -+ ] - if CONFIG['MOZ_WAYLAND']: ++ USE_LIBS += [ ++ 'dav1d', ++ 'media_libdav1d_asm', ++ ] + if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": LOCAL_INCLUDES += ['/media/mozva'] SOURCES += [ diff --git toolkit/moz.configure toolkit/moz.configure -index 0069865..e806fc8 100644 +index f93a5d64fec8..814357f4e979 100644 --- toolkit/moz.configure +++ toolkit/moz.configure -@@ -523,7 +523,23 @@ def av1(value): +@@ -744,7 +744,23 @@ def av1(value): return True @@ -113,7 +94,7 @@ index 0069865..e806fc8 100644 def dav1d_asm(target): if target.cpu in ("aarch64", "x86", "x86_64"): return True -@@ -539,6 +555,7 @@ set_config("MOZ_DAV1D_ASM", dav1d_asm) +@@ -760,6 +776,7 @@ set_config("MOZ_DAV1D_ASM", dav1d_asm) set_define("MOZ_DAV1D_ASM", dav1d_asm) set_config("MOZ_AV1", av1) set_define("MOZ_AV1", av1) diff --git a/www/firefox-esr/files/patch-bug1626236 b/www/firefox-esr/files/patch-bug1626236 index ccb417b61f15..ae3b522f6b90 100644 --- a/www/firefox-esr/files/patch-bug1626236 +++ b/www/firefox-esr/files/patch-bug1626236 @@ -9,10 +9,11 @@ https://bug1626236.bmoattachments.org/attachment.cgi?id=9137096 # Parent 9cd90914846f667f18babc491a74c164ae5d6e9f imported patch decoder_workaround.patch -diff -r 9cd90914846f image/decoders/nsGIFDecoder2.cpp ---- image/decoders/nsGIFDecoder2.cpp Thu Feb 27 12:57:14 2020 +0100 -+++ image/decoders/nsGIFDecoder2.cpp Fri Mar 27 13:06:18 2020 +0100 -@@ -422,6 +422,9 @@ +diff --git image/decoders/nsGIFDecoder2.cpp image/decoders/nsGIFDecoder2.cpp +index ebb0b7d..d52ef47 100644 +--- image/decoders/nsGIFDecoder2.cpp ++++ image/decoders/nsGIFDecoder2.cpp +@@ -422,6 +422,9 @@ void nsGIFDecoder2::ConvertColormap(uint32_t* aColormap, uint32_t aColors) { MOZ_ASSERT(mSwizzleFn); uint8_t* data = reinterpret_cast<uint8_t*>(aColormap); mSwizzleFn(data, data, aColors); @@ -22,10 +23,11 @@ diff -r 9cd90914846f image/decoders/nsGIFDecoder2.cpp } LexerResult nsGIFDecoder2::DoDecode(SourceBufferIterator& aIterator, -diff -r 9cd90914846f image/decoders/nsJPEGDecoder.cpp ---- image/decoders/nsJPEGDecoder.cpp Thu Feb 27 12:57:14 2020 +0100 -+++ image/decoders/nsJPEGDecoder.cpp Fri Mar 27 13:06:18 2020 +0100 -@@ -263,6 +263,9 @@ +diff --git image/decoders/nsJPEGDecoder.cpp image/decoders/nsJPEGDecoder.cpp +index 9ea4403..d82772c 100644 +--- image/decoders/nsJPEGDecoder.cpp ++++ image/decoders/nsJPEGDecoder.cpp +@@ -257,6 +257,9 @@ LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::ReadJPEGData( case JCS_YCbCr: // By default, we will output directly to BGRA. If we need to apply // special color transforms, this may change. @@ -35,7 +37,7 @@ diff -r 9cd90914846f image/decoders/nsJPEGDecoder.cpp switch (SurfaceFormat::OS_RGBX) { case SurfaceFormat::B8G8R8X8: mInfo.out_color_space = JCS_EXT_BGRX; -@@ -277,6 +280,7 @@ +@@ -271,6 +274,7 @@ LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::ReadJPEGData( mState = JPEG_ERROR; return Transition::TerminateFailure(); } @@ -43,10 +45,11 @@ diff -r 9cd90914846f image/decoders/nsJPEGDecoder.cpp break; case JCS_CMYK: case JCS_YCCK: -diff -r 9cd90914846f image/decoders/nsPNGDecoder.cpp ---- image/decoders/nsPNGDecoder.cpp Thu Feb 27 12:57:14 2020 +0100 -+++ image/decoders/nsPNGDecoder.cpp Fri Mar 27 13:06:18 2020 +0100 -@@ -361,7 +361,7 @@ +diff --git image/decoders/nsPNGDecoder.cpp image/decoders/nsPNGDecoder.cpp +index e3e4ef4..3cc7315 100644 +--- image/decoders/nsPNGDecoder.cpp ++++ image/decoders/nsPNGDecoder.cpp +@@ -356,7 +356,7 @@ LexerResult nsPNGDecoder::DoDecode(SourceBufferIterator& aIterator, IResumable* aOnResume) { MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!"); @@ -55,7 +58,7 @@ diff -r 9cd90914846f image/decoders/nsPNGDecoder.cpp [=](State aState, const char* aData, size_t aLength) { switch (aState) { case State::PNG_DATA: -@@ -371,6 +371,14 @@ +@@ -366,6 +366,14 @@ LexerResult nsPNGDecoder::DoDecode(SourceBufferIterator& aIterator, } MOZ_CRASH("Unknown State"); }); @@ -70,10 +73,11 @@ diff -r 9cd90914846f image/decoders/nsPNGDecoder.cpp } LexerTransition<nsPNGDecoder::State> nsPNGDecoder::ReadPNGData( -diff -r 9cd90914846f image/decoders/nsWebPDecoder.cpp ---- image/decoders/nsWebPDecoder.cpp Thu Feb 27 12:57:14 2020 +0100 -+++ image/decoders/nsWebPDecoder.cpp Fri Mar 27 13:06:18 2020 +0100 -@@ -237,7 +237,12 @@ +diff --git image/decoders/nsWebPDecoder.cpp image/decoders/nsWebPDecoder.cpp +index e58ca92..2056ebb 100644 +--- image/decoders/nsWebPDecoder.cpp ++++ image/decoders/nsWebPDecoder.cpp +@@ -247,7 +247,12 @@ nsresult nsWebPDecoder::CreateFrame(const OrientedIntRect& aFrameRect) { // WebP doesn't guarantee that the alpha generated matches the hint in the // header, so we always need to claim the input is BGRA. If the output is // BGRX, swizzling will mask off the alpha channel. diff --git a/www/firefox-esr/files/patch-bug1628567 b/www/firefox-esr/files/patch-bug1628567 deleted file mode 100644 index 32b0dc260d22..000000000000 --- a/www/firefox-esr/files/patch-bug1628567 +++ /dev/null @@ -1,32 +0,0 @@ -Don't pass --target when CC/CXX contains clang - -diff --git third_party/rust/cc/src/lib.rs third_party/rust/cc/src/lib.rs -index 9d133a0..273e520 100644 ---- third_party/rust/cc/src/lib.rs -+++ third_party/rust/cc/src/lib.rs -@@ -2667,24 +2667,7 @@ impl Tool { - } - - fn with_features(path: PathBuf, clang_driver: Option<&str>, cuda: bool) -> Self { -- // Try to detect family of the tool from its name, falling back to Gnu. -- let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) { -- if fname.contains("clang-cl") { -- ToolFamily::Msvc { clang_cl: true } -- } else if fname.ends_with("cl") || fname == "cl.exe" { -- ToolFamily::Msvc { clang_cl: false } -- } else if fname.contains("clang") { -- match clang_driver { -- Some("cl") => ToolFamily::Msvc { clang_cl: true }, -- _ => ToolFamily::Clang, -- } -- } else { -- ToolFamily::Gnu -- } -- } else { -- ToolFamily::Gnu -- }; -- -+ let family = ToolFamily::Gnu; - Tool { - path: path, - cc_wrapper_path: None, diff --git a/www/firefox-esr/files/patch-bug1680982 b/www/firefox-esr/files/patch-bug1680982 deleted file mode 100644 index c9fc2344bb44..000000000000 --- a/www/firefox-esr/files/patch-bug1680982 +++ /dev/null @@ -1,388 +0,0 @@ -commit 3204512f58a1 -Author: Greg V <greg@unrelenting.technology> -Date: Sun Dec 6 22:07:00 2020 +0000 - - Bug 1680982 - Use evdev instead of the Linux legacy joystick API for gamepads - - Using evdev is a prerequisite for adding rumble (haptic feedback) and LED support. - - - BTN_GAMEPAD semantic buttons are interpreted directly, - since all kernel drivers are supposed to use them correctly: - https://www.kernel.org/doc/html/latest/input/gamepad.html - - BTN_JOYSTICK legacy style numbered buttons use the model specific remappers - - we support even strange devices that combine both styles in one device - - the Linux gamepad module is enabled on FreeBSD and DragonFly, because - these kernels provide evdev, and libudev-devd provides enough of libudev - (evdev headers are provided by the devel/evdev-proto package) - - Differential Revision: https://phabricator.services.mozilla.com/D98868 ---- - dom/gamepad/linux/LinuxGamepad.cpp | 262 ++++++++++++++++++++++++++++++++----- - dom/gamepad/moz.build | 2 +- - 2 files changed, 229 insertions(+), 35 deletions(-) - -diff --git dom/gamepad/linux/LinuxGamepad.cpp dom/gamepad/linux/LinuxGamepad.cpp -index deee47b9d267..31f0aad7ae4a 100644 ---- dom/gamepad/linux/LinuxGamepad.cpp -+++ dom/gamepad/linux/LinuxGamepad.cpp -@@ -5,15 +5,16 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - /* -- * LinuxGamepadService: A Linux backend for the GamepadService. -- * Derived from the kernel documentation at -- * http://www.kernel.org/doc/Documentation/input/joystick-api.txt -+ * LinuxGamepadService: An evdev backend for the GamepadService. -+ * -+ * Ref: https://www.kernel.org/doc/html/latest/input/gamepad.html - */ - #include <algorithm> -+#include <unordered_map> - #include <cstddef> - - #include <glib.h> --#include <linux/joystick.h> -+#include <linux/input.h> - #include <stdio.h> - #include <stdint.h> - #include <sys/ioctl.h> -@@ -21,10 +22,14 @@ - #include "nscore.h" - #include "mozilla/dom/GamepadHandle.h" - #include "mozilla/dom/GamepadPlatformService.h" -+#include "mozilla/dom/GamepadRemapping.h" - #include "mozilla/Tainting.h" - #include "mozilla/UniquePtr.h" - #include "udev.h" - -+#define LONG_BITS (sizeof(long) * 8) -+#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS) -+ - namespace { - - using namespace mozilla::dom; -@@ -36,19 +41,29 @@ using mozilla::udev_list_entry; - using mozilla::udev_monitor; - using mozilla::UniquePtr; - --static const float kMaxAxisValue = 32767.0; --static const char kJoystickPath[] = "/dev/input/js"; -+static const char kEvdevPath[] = "/dev/input/event"; -+ -+static inline bool TestBit(const unsigned long* arr, int bit) { -+ return !!(arr[bit / LONG_BITS] & (1LL << (bit % LONG_BITS))); -+} -+ -+static inline double ScaleAxis(const input_absinfo& info, int value) { -+ return 2.0 * (value - info.minimum) / (double)(info.maximum - info.minimum) - -+ 1.0; -+} - - // TODO: should find a USB identifier for each device so we can - // provide something that persists across connect/disconnect cycles. --typedef struct { -+struct Gamepad { - GamepadHandle handle; -- guint source_id; -- int numAxes; -- int numButtons; -- char idstring[256]; -- char devpath[PATH_MAX]; --} Gamepad; -+ RefPtr<GamepadRemapper> remapper = nullptr; -+ guint source_id = UINT_MAX; -+ char idstring[256] = {0}; -+ char devpath[PATH_MAX] = {0}; -+ uint8_t key_map[KEY_MAX] = {0}; -+ uint8_t abs_map[ABS_MAX] = {0}; -+ std::unordered_map<uint16_t, input_absinfo> abs_info; -+}; - - class LinuxGamepadService { - public: -@@ -66,7 +81,7 @@ class LinuxGamepadService { - bool is_gamepad(struct udev_device* dev); - void ReadUdevChange(); - -- // handler for data from /dev/input/jsN -+ // handler for data from /dev/input/eventN - static gboolean OnGamepadData(GIOChannel* source, GIOCondition condition, - gpointer data); - -@@ -114,8 +129,14 @@ void LinuxGamepadService::AddDevice(struct udev_device* dev) { - g_io_channel_set_encoding(channel, nullptr, nullptr); - g_io_channel_set_buffered(channel, FALSE); - int fd = g_io_channel_unix_get_fd(channel); -+ -+ struct input_id id {}; -+ if (ioctl(fd, EVIOCGID, &id) == -1) { -+ return; -+ } -+ - char name[128]; -- if (ioctl(fd, JSIOCGNAME(sizeof(name)), &name) == -1) { -+ if (ioctl(fd, EVIOCGNAME(sizeof(name)), &name) == -1) { - strcpy(name, "unknown"); - } - const char* vendor_id = -@@ -131,20 +152,86 @@ void LinuxGamepadService::AddDevice(struct udev_device* dev) { - model_id = mUdev.udev_device_get_sysattr_value(parent, "id/product"); - } - } -+ if (!vendor_id && id.vendor != 0) { -+ vendor_id = (const char*)alloca(5); -+ snprintf((char*)vendor_id, 5, "%04x", id.vendor); -+ } -+ if (!model_id && id.product != 0) { -+ model_id = (const char*)alloca(5); -+ snprintf((char*)model_id, 5, "%04x", id.product); -+ } - snprintf(gamepad->idstring, sizeof(gamepad->idstring), "%s-%s-%s", - vendor_id ? vendor_id : "unknown", model_id ? model_id : "unknown", - name); - - char numAxes = 0, numButtons = 0; -- ioctl(fd, JSIOCGAXES, &numAxes); -- gamepad->numAxes = numAxes; -- ioctl(fd, JSIOCGBUTTONS, &numButtons); -- gamepad->numButtons = numButtons; -+ unsigned long key_bits[NLONGS(KEY_CNT)] = {0}; -+ unsigned long abs_bits[NLONGS(ABS_CNT)] = {0}; -+ ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits); -+ ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits); -+ -+ /* Here, we try to support even strange cases where proper semantic -+ * BTN_GAMEPAD button are combined with arbitrary extra buttons. */ -+ for (uint16_t i = BTN_JOYSTICK; i < KEY_MAX; i++) { -+ /* Do not map semantic buttons, they are handled directly */ -+ if (i == BTN_GAMEPAD) { -+ i = BTN_THUMBR + 1; -+ continue; -+ } -+ if (i == BTN_DPAD_UP) { -+ i = BTN_DPAD_RIGHT + 1; -+ continue; -+ } -+ if (TestBit(key_bits, i)) { -+ gamepad->key_map[i] = numButtons++; -+ } -+ } -+ for (uint16_t i = 0; i < BTN_JOYSTICK; i++) { -+ if (TestBit(key_bits, i)) { -+ gamepad->key_map[i] = numButtons++; -+ } -+ } -+ for (uint16_t i = BTN_GAMEPAD; i <= BTN_THUMBR; i++) { -+ /* But if any semantic event exists, count them all */ -+ if (TestBit(key_bits, i)) { -+ numButtons += BUTTON_INDEX_COUNT; -+ break; -+ } -+ } -+ for (uint16_t i = 0; i < ABS_MAX; ++i) { -+ if (TestBit(abs_bits, i)) { -+ gamepad->abs_info.emplace(i, input_absinfo{}); -+ if (ioctl(fd, EVIOCGABS(i), &gamepad->abs_info[i]) < 0) { -+ continue; -+ } -+ if (gamepad->abs_info[i].minimum == gamepad->abs_info[i].maximum) { -+ gamepad->abs_info.erase(i); -+ continue; -+ } -+ gamepad->abs_map[i] = numAxes++; -+ } -+ } -+ -+ if (numAxes == 0) { -+ NS_WARNING("Gamepad with zero axes detected?"); -+ } -+ if (numButtons == 0) { -+ NS_WARNING("Gamepad with zero buttons detected?"); -+ } -+ -+ bool defaultRemapper = false; -+ RefPtr<GamepadRemapper> remapper = -+ GetGamepadRemapper(id.vendor, id.product, defaultRemapper); -+ MOZ_ASSERT(remapper); -+ remapper->SetAxisCount(numAxes); -+ remapper->SetButtonCount(numButtons); - - gamepad->handle = service->AddGamepad( -- gamepad->idstring, mozilla::dom::GamepadMappingType::_empty, -- mozilla::dom::GamepadHand::_empty, gamepad->numButtons, gamepad->numAxes, -- 0, 0, 0); // TODO: Bug 680289, implement gamepad haptics for Linux. -+ gamepad->idstring, remapper->GetMappingType(), GamepadHand::_empty, -+ remapper->GetButtonCount(), remapper->GetAxisCount(), 0, -+ remapper->GetLightIndicatorCount(), remapper->GetTouchEventCount()); -+ gamepad->remapper = remapper.forget(); -+ // TODO: Bug 680289, implement gamepad haptics for Linux. - // TODO: Bug 1523355, implement gamepad lighindicator and touch for Linux. - - gamepad->source_id = -@@ -257,7 +344,7 @@ bool LinuxGamepadService::is_gamepad(struct udev_device* dev) { - if (!devpath) { - return false; - } -- if (strncmp(kJoystickPath, devpath, sizeof(kJoystickPath) - 1) != 0) { -+ if (strncmp(kEvdevPath, devpath, sizeof(kEvdevPath) - 1) != 0) { - return false; - } - -@@ -292,7 +379,7 @@ gboolean LinuxGamepadService::OnGamepadData(GIOChannel* source, - if (condition & G_IO_ERR || condition & G_IO_HUP) return FALSE; - - while (true) { -- struct js_event event; -+ struct input_event event {}; - gsize count; - GError* err = nullptr; - if (g_io_channel_read_chars(source, (gchar*)&event, sizeof(event), &count, -@@ -301,18 +388,125 @@ gboolean LinuxGamepadService::OnGamepadData(GIOChannel* source, - break; - } - -- // TODO: store device state? -- if (event.type & JS_EVENT_INIT) { -- continue; -- } -- - switch (event.type) { -- case JS_EVENT_BUTTON: -- service->NewButtonEvent(gamepad->handle, event.number, !!event.value); -+ case EV_KEY: -+ switch (event.code) { -+ /* The gamepad events are meaningful, and according to -+ * https://www.kernel.org/doc/html/latest/input/gamepad.html -+ * "No other devices, that do not look/feel like a gamepad, shall -+ * report these events" */ -+ case BTN_SOUTH: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_PRIMARY, -+ !!event.value); -+ break; -+ case BTN_EAST: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_SECONDARY, -+ !!event.value); -+ break; -+ case BTN_NORTH: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_QUATERNARY, -+ !!event.value); -+ break; -+ case BTN_WEST: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_TERTIARY, -+ !!event.value); -+ break; -+ case BTN_TL: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_LEFT_SHOULDER, -+ !!event.value); -+ break; -+ case BTN_TR: -+ service->NewButtonEvent(gamepad->handle, -+ BUTTON_INDEX_RIGHT_SHOULDER, !!event.value); -+ break; -+ case BTN_TL2: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_LEFT_TRIGGER, -+ !!event.value); -+ break; -+ case BTN_TR2: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_RIGHT_TRIGGER, -+ !!event.value); -+ break; -+ case BTN_SELECT: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_BACK_SELECT, -+ !!event.value); -+ break; -+ case BTN_START: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_START, -+ !!event.value); -+ break; -+ case BTN_MODE: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_META, -+ !!event.value); -+ break; -+ case BTN_THUMBL: -+ service->NewButtonEvent( -+ gamepad->handle, BUTTON_INDEX_LEFT_THUMBSTICK, !!event.value); -+ break; -+ case BTN_THUMBR: -+ service->NewButtonEvent( -+ gamepad->handle, BUTTON_INDEX_RIGHT_THUMBSTICK, !!event.value); -+ break; -+ case BTN_DPAD_UP: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_DPAD_UP, -+ !!event.value); -+ break; -+ case BTN_DPAD_DOWN: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_DPAD_DOWN, -+ !!event.value); -+ break; -+ case BTN_DPAD_LEFT: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_DPAD_LEFT, -+ !!event.value); -+ break; -+ case BTN_DPAD_RIGHT: -+ service->NewButtonEvent(gamepad->handle, BUTTON_INDEX_DPAD_RIGHT, -+ !!event.value); -+ break; -+ default: -+ /* For non-gamepad events, this is the "anything goes" numbered -+ * handling that should be handled with remappers. */ -+ gamepad->remapper->RemapButtonEvent( -+ gamepad->handle, gamepad->key_map[event.code], !!event.value); -+ break; -+ } - break; -- case JS_EVENT_AXIS: -- service->NewAxisMoveEvent(gamepad->handle, event.number, -- ((float)event.value) / kMaxAxisValue); -+ case EV_ABS: -+ if (!gamepad->abs_info.count(event.code)) continue; -+ switch (event.code) { -+ case ABS_HAT0X: -+ service->NewButtonEvent( -+ gamepad->handle, BUTTON_INDEX_DPAD_LEFT, -+ AxisNegativeAsButton( -+ ScaleAxis(gamepad->abs_info[event.code], event.value))); -+ service->NewButtonEvent( -+ gamepad->handle, BUTTON_INDEX_DPAD_RIGHT, -+ AxisPositiveAsButton( -+ ScaleAxis(gamepad->abs_info[event.code], event.value))); -+ break; -+ case ABS_HAT0Y: -+ service->NewButtonEvent( -+ gamepad->handle, BUTTON_INDEX_DPAD_UP, -+ AxisNegativeAsButton( -+ ScaleAxis(gamepad->abs_info[event.code], event.value))); -+ service->NewButtonEvent( -+ gamepad->handle, BUTTON_INDEX_DPAD_DOWN, -+ AxisPositiveAsButton( -+ ScaleAxis(gamepad->abs_info[event.code], event.value))); -+ break; -+ case ABS_HAT1X: -+ case ABS_HAT1Y: -+ case ABS_HAT2X: -+ case ABS_HAT2Y: -+ case ABS_HAT3X: -+ case ABS_HAT3Y: -+ break; -+ default: -+ gamepad->remapper->RemapAxisMoveEvent( -+ gamepad->handle, gamepad->abs_map[event.code], -+ ScaleAxis(gamepad->abs_info[event.code], event.value)); -+ break; -+ } - break; - } - } -diff --git dom/gamepad/moz.build dom/gamepad/moz.build -index 5f55d5a95e96..544b7f927736 100644 ---- dom/gamepad/moz.build -+++ dom/gamepad/moz.build -@@ -59,7 +59,7 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": - UNIFIED_SOURCES += ["windows/WindowsGamepad.cpp"] - elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": - UNIFIED_SOURCES += ["android/AndroidGamepad.cpp"] --elif CONFIG["OS_ARCH"] == "Linux": -+elif CONFIG["OS_ARCH"] in ("Linux", "FreeBSD", "DragonFly"): - UNIFIED_SOURCES += ["linux/LinuxGamepad.cpp"] - else: - UNIFIED_SOURCES += ["fallback/FallbackGamepad.cpp"] diff --git a/www/firefox-esr/files/patch-bug1841919 b/www/firefox-esr/files/patch-bug1841919 deleted file mode 100644 index 93bd00f462ae..000000000000 --- a/www/firefox-esr/files/patch-bug1841919 +++ /dev/null @@ -1,75 +0,0 @@ -commit 54ebf78999815570c3cd4d94bf00daa7dec6061d -Author: Mike Hommey <mh+mozilla@glandium.org> -Date: Thu Jul 6 02:34:07 2023 +0000 - - Bug 1841919 - Fix "variable does not need to be mutable" warnings in webrender. r=gfx-reviewers,lsalzman - - Differential Revision: https://phabricator.services.mozilla.com/D182851 - -diff --git gfx/wr/webrender/src/compositor/sw_compositor.rs gfx/wr/webrender/src/compositor/sw_compositor.rs -index e623870c86f3..854fef6fe2b9 100644 ---- gfx/wr/webrender/src/compositor/sw_compositor.rs -+++ gfx/wr/webrender/src/compositor/sw_compositor.rs -@@ -1026,7 +1026,7 @@ impl SwCompositor { - if let Some(surface) = self.surfaces.get_mut(id) { - if let Some(external_image) = surface.external_image { - assert!(!surface.tiles.is_empty()); -- let mut tile = &mut surface.tiles[0]; -+ let tile = &mut surface.tiles[0]; - if let Some(info) = self.composite_surfaces.get(&external_image) { - tile.valid_rect = DeviceIntRect::from_size(info.size); - return; -diff --git gfx/wr/webrender/src/picture.rs gfx/wr/webrender/src/picture.rs -index bd685d48a113..72c0e1efa038 100644 ---- gfx/wr/webrender/src/picture.rs -+++ gfx/wr/webrender/src/picture.rs -@@ -2888,7 +2888,7 @@ impl TileCacheInstance { - let prim_clip_chain = &prim_instance.vis.clip_chain; - - // Accumulate the exact (clipped) local rect in to the parent surface -- let mut surface = &mut surfaces[prim_surface_index.0]; -+ let surface = &mut surfaces[prim_surface_index.0]; - surface.clipped_local_rect = surface.clipped_local_rect.union(&prim_clip_chain.pic_coverage_rect); - - // If the primitive is directly drawn onto this picture cache surface, then -diff --git gfx/wr/webrender_api/src/display_item_cache.rs gfx/wr/webrender_api/src/display_item_cache.rs -index 6cd1eb3e3a44..60d41c591d36 100644 ---- gfx/wr/webrender_api/src/display_item_cache.rs -+++ gfx/wr/webrender_api/src/display_item_cache.rs -@@ -58,13 +58,13 @@ pub struct DisplayItemCache { - - impl DisplayItemCache { - fn add_item(&mut self, key: ItemKey, item: CachedDisplayItem) { -- let mut entry = &mut self.entries[key as usize]; -+ let entry = &mut self.entries[key as usize]; - entry.items.push(item); - entry.occupied = true; - } - - fn clear_entry(&mut self, key: ItemKey) { -- let mut entry = &mut self.entries[key as usize]; -+ let entry = &mut self.entries[key as usize]; - entry.items.clear(); - entry.occupied = false; - } -commit 8300555a01bdcc478ae103dcf2b469bf24e4dd41 -Author: Mike Hommey <mh+mozilla@glandium.org> -Date: Thu Jul 6 04:26:41 2023 +0000 - - Bug 1841919 - Fix "variable does not need to be mutable" warning in wrench. r=gfx-reviewers,jrmuizel - - Differential Revision: https://phabricator.services.mozilla.com/D182858 - -diff --git gfx/wr/wrench/src/reftest.rs gfx/wr/wrench/src/reftest.rs -index 136a4477205d..0e900224b883 100644 ---- gfx/wr/wrench/src/reftest.rs -+++ gfx/wr/wrench/src/reftest.rs -@@ -514,7 +514,7 @@ impl ReftestManifest { - max_difference: options.allow_max_difference, - num_differences: options.allow_num_differences }), - 1 => { -- let mut fuzzy = &mut fuzziness[0]; -+ let fuzzy = &mut fuzziness[0]; - fuzzy.max_difference = cmp::max(fuzzy.max_difference, options.allow_max_difference); - fuzzy.num_differences = cmp::max(fuzzy.num_differences, options.allow_num_differences); - }, diff --git a/www/firefox-esr/files/patch-bug1873379 b/www/firefox-esr/files/patch-bug1873379 deleted file mode 100644 index 658bc576eef1..000000000000 --- a/www/firefox-esr/files/patch-bug1873379 +++ /dev/null @@ -1,34 +0,0 @@ -commit 627cc80defb3fa48e82ce656536d666176b9f8d1 -Author: Emilio Cobos Álvarez <emilio@crisal.io> -Date: Sat Jan 13 14:35:33 2024 +0000 - - Bug 1873379 - Ignore std::tuple harder. r=firefox-style-system-reviewers,zrhoffman - - In libc++ 18 it seems to be in a nested namespace. Make sure to account - for that. - - Differential Revision: https://phabricator.services.mozilla.com/D198398 - -diff --git layout/style/ServoBindings.toml layout/style/ServoBindings.toml -index 2aea31f8f911..2deafbfb14b6 100644 ---- layout/style/ServoBindings.toml -+++ layout/style/ServoBindings.toml -@@ -366,6 +366,9 @@ opaque-types = [ - "std::namespace::atomic___base", "std::atomic__My_base", - "std::atomic", - "std::atomic___base", -+ "std::tuple.*", # Causes "Cannot find type _Pred in this scope" error on mac, like rust-skia#571 -+ "std::.*::tuple.*", -+ - # We want everything but FontVariation and Float to be opaque but we don't - # have negative regexes. - "mozilla::gfx::(.{0,4}|.{6,12}|.{14,}|([^F][^o][^n][^t][^V][^a][^r][^i][^a][^t][^i][^o][^n])|([^F][^l][^o][^a][^t]))", -@@ -391,8 +394,6 @@ opaque-types = [ - # for clang. - "mozilla::SeenPtrs", - "mozilla::SupportsWeakPtr", -- "std::tuple", -- "std::tuple_.*", # Causes "Cannot find type _Pred in this scope" error on mac, like rust-skia#571 - "SupportsWeakPtr", - "mozilla::detail::WeakReference", - "mozilla::WeakPtr", diff --git a/www/firefox-esr/files/patch-bug1876366 b/www/firefox-esr/files/patch-bug1876366 new file mode 100644 index 000000000000..78483c3fbab7 --- /dev/null +++ b/www/firefox-esr/files/patch-bug1876366 @@ -0,0 +1,23 @@ +commit 46a89fb0319d673b3139a068e3d89aed9f44fc16 +Author: Christoph Moench-Tegeder <cmt@burggraben.net> + + use gdk legacy cursor interface by default + + Upstream https://bugzilla.mozilla.org/show_bug.cgi?id=1876366#c16 + hints that we could re-test this once we have GTK 3.24.42 (with the + now-current gtk3-3.24.41 the original problem is still reproducable, + but toggling this flag does fix it for me) + +diff --git modules/libpref/init/StaticPrefList.yaml modules/libpref/init/StaticPrefList.yaml +index 835450712a12..f2249006c36d 100644 +--- modules/libpref/init/StaticPrefList.yaml ++++ modules/libpref/init/StaticPrefList.yaml +@@ -16070,7 +16070,7 @@ + # Whether to use gtk legacy cursor API. + - name: widget.gtk.legacy-cursors.enabled + type: bool +- value: false ++ value: true + mirror: always + + # Whether to use gtk high contrast themes to disable content styling like on diff --git a/www/firefox-esr/files/patch-bug847568 b/www/firefox-esr/files/patch-bug847568 index 2b3c5e14e99e..2ee46579d43d 100644 --- a/www/firefox-esr/files/patch-bug847568 +++ b/www/firefox-esr/files/patch-bug847568 @@ -1,11 +1,11 @@ # Allow building against system-wide graphite2/harfbuzz. diff --git config/system-headers.mozbuild config/system-headers.mozbuild -index a1b58eb..a0a0943 100644 +index 0c06f581b33b..10f125be25ab 100644 --- config/system-headers.mozbuild +++ config/system-headers.mozbuild -@@ -1289,6 +1289,19 @@ if CONFIG['MOZ_ENABLE_LIBPROXY']: - 'proxy.h', +@@ -1307,6 +1307,19 @@ if CONFIG["MOZ_ENABLE_LIBPROXY"]: + "proxy.h", ] +if CONFIG['MOZ_SYSTEM_GRAPHITE2']: @@ -21,14 +21,14 @@ index a1b58eb..a0a0943 100644 + 'harfbuzz/hb.h', + ] + - if CONFIG['MOZ_SYSTEM_LIBVPX']: + if CONFIG["MOZ_SYSTEM_ICU"]: system_headers += [ - 'vpx_mem/vpx_mem.h', + "unicode/calendar.h", *** 89161 LINES SKIPPED ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202409092125.489LPMne088328>