diff --git a/www-client/floorp/additional-files/mozconfig b/www-client/floorp/additional-files/mozconfig
index 0c4a88632..5817c6c81 100644
--- a/www-client/floorp/additional-files/mozconfig
+++ b/www-client/floorp/additional-files/mozconfig
@@ -33,6 +33,9 @@ mk_add_options MOZ_DATA_REPORTING=0
mk_add_options MOZ_SERVICES_HEALTHREPORT=0
mk_add_options MOZ_TELEMETRY_REPORTING=0
+# Enable
+ac_add_options --enable-webrtc
+
# Linker
export LD="lld"
export LDFLAGS="-fuse-ld=lld -Wl,--no-keep-memory -Wl,--undefined-version"
diff --git a/www-client/floorp/floorp-11.24.0.recipe b/www-client/floorp/floorp-11.25.0.recipe
similarity index 91%
rename from www-client/floorp/floorp-11.24.0.recipe
rename to www-client/floorp/floorp-11.25.0.recipe
index bc74a2651..7f4d02cb7 100644
--- a/www-client/floorp/floorp-11.24.0.recipe
+++ b/www-client/floorp/floorp-11.25.0.recipe
@@ -16,11 +16,11 @@ COPYRIGHT="1995-2025 Mozilla Developers, Floorp Projects & Ablaze"
LICENSE="MPL v2.0"
REVISION="1"
SOURCE_URI="https://github.com/Floorp-Projects/Floorp/archive/refs/tags/v$portVersion.tar.gz"
-CHECKSUM_SHA256="3215e156e13b3e4cdfa21d450ee8409cec1db897f2221f6eede1f236c3b434f1"
+CHECKSUM_SHA256="ad975ceb1934f55f09a74b991fbe0c91111127ee8bb55091f6cfef8a63b8879b"
SOURCE_DIR="Floorp-$portVersion"
-srcGitRev2="c2c1a0fb64ac5de39ca1b7f27ae88436d3c6c3db"
+srcGitRev2="c7a8b87560e62ffe00cf3b7289cc94e73a8198b2"
SOURCE_URI_2="https://github.com/Floorp-Projects/Floorp-core/archive/$srcGitRev2.tar.gz"
-CHECKSUM_SHA256_2="0739648ffbc5a25195e0117d659df89b4bad822b372c0f0e6dced102d82b0dba"
+CHECKSUM_SHA256_2="db8a241217977dab9fdb2ffc51ecc40aa7e0a20d581f3f1d232ba241f3fa3031"
SOURCE_DIR_2="Floorp-core-$srcGitRev2"
srcGitRev3="29bb9bed37ae970fbac4c8222010328b7fbf7e15"
SOURCE_URI_3="https://github.com/Floorp-Projects/Unified-l10n-central/archive/$srcGitRev3.tar.gz"
@@ -52,6 +52,7 @@ REQUIRES="
lib:libgtk_3
lib:libharfbuzz
lib:libintl
+ lib:libmediahelpers
lib:libnspr4
lib:libnss3
lib:libpango_1.0
@@ -67,6 +68,7 @@ BUILD_REQUIRES="
devel:libevent
devel:libglib_2.0
devel:libgtk_3
+ devel:libmediahelpers
devel:libnspr4
devel:libnss3
devel:libpng16
@@ -84,6 +86,7 @@ BUILD_PREREQUIRES="
cmd:gawk
cmd:gcc
cmd:git
+ cmd:gn
cmd:lld >= 18
cmd:m4
cmd:make
@@ -125,6 +128,8 @@ BUILD()
--application-choice="Firefox for Desktop" \
--exclude=sysroot-wasm32-wasi
+ ./mach python python/mozbuild/mozbuild/gn_processor.py dom/media/webrtc/third_party_build/gn-configs/webrtc.json
+
./mach build
}
diff --git a/www-client/floorp/patches/floorp-11.24.0.patchset b/www-client/floorp/patches/floorp-11.25.0.patchset
similarity index 61%
rename from www-client/floorp/patches/floorp-11.24.0.patchset
rename to www-client/floorp/patches/floorp-11.25.0.patchset
index 8458b50ec..3cb3a07bb 100644
--- a/www-client/floorp/patches/floorp-11.24.0.patchset
+++ b/www-client/floorp/patches/floorp-11.25.0.patchset
@@ -1,16 +1,19 @@
-From 055c3d320459ca0f7ee2bfa06f9aa18d6ef2bdd8 Mon Sep 17 00:00:00 2001
+From 1c36b72e727dac7c115618f7791ac654c34443bb Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
-Date: Tue, 11 Mar 2025 23:15:03 +1000
+Date: Tue, 1 Apr 2025 13:50:00 +1000
Subject: Add Haiku build support
Based on patches sourced from https://github.com/kenz-gelsoft/gecko-dev/
-- Enabled building for the Haiku.
-- Implemented the cubeb audio backend for MediaKit.
+- Enabled building for Haiku.
+- Implemented the cubeb audio backend for MediaKit (input and output).
+- Implemented native notifications.
+- Fixed build with WebRTC enabled.
+- Implemented WebRTC modules for desktop capture and video capture.
- Made additional modifications for Haiku compatibility.
diff --git a/.cargo/config.toml.in b/.cargo/config.toml.in
-index 827f912774..b7264742b6 100644
+index 827f912..b726474 100644
--- a/.cargo/config.toml.in
+++ b/.cargo/config.toml.in
@@ -55,6 +55,16 @@ git = "https://github.com/jfkthame/mapped_hyph.git"
@@ -31,7 +34,7 @@ index 827f912774..b7264742b6 100644
git = "https://github.com/mozilla-spidermonkey/jsparagus"
rev = "61f399c53a641ebd3077c1f39f054f6d396a633c"
diff --git a/Cargo.lock b/Cargo.lock
-index dd0db2d9d6..381af73e61 100644
+index dd0db2d..381af73 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2458,8 +2458,7 @@ dependencies = [
@@ -55,7 +58,7 @@ index dd0db2d9d6..381af73e61 100644
"cc",
"libc",
diff --git a/Cargo.toml b/Cargo.toml
-index a4248187be..b3aaba275a 100644
+index a424818..b3aaba2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -237,6 +237,10 @@ mio_0_8 = { package = "mio", git = "https://github.com/glandium/mio", rev = "9a2
@@ -70,7 +73,7 @@ index a4248187be..b3aaba275a 100644
neqo-bin = { path = "third_party/rust/neqo-bin" }
neqo-common = { path = "third_party/rust/neqo-common" }
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
-index 832388c145..9d6bf0fece 100644
+index 832388c..9d6bf0f 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -15,7 +15,9 @@
@@ -103,7 +106,7 @@ index 832388c145..9d6bf0fece 100644
#else
pref("browser.tabs.searchclipboardfor.middleclick", false);
diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc
-index 89d56dad95..80a23ea132 100644
+index 89d56da..80a23ea 100644
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -6,6 +6,12 @@
@@ -144,7 +147,7 @@ index 89d56dad95..80a23ea132 100644
#expand
#expand
diff --git a/build/gecko_templates.mozbuild b/build/gecko_templates.mozbuild
-index e4c781ce04..79e990d98e 100644
+index e4c781c..79e990d 100644
--- a/build/gecko_templates.mozbuild
+++ b/build/gecko_templates.mozbuild
@@ -42,7 +42,8 @@ def GeckoBinary(linkage="dependent", mozglue=None):
@@ -158,7 +161,7 @@ index e4c781ce04..79e990d98e 100644
LIBRARY_DEFINES["MOZ_HAS_MOZGLUE"] = True
if not CONFIG["MOZ_GLUE_IN_PROGRAM"]:
diff --git a/build/moz.configure/bindgen.configure b/build/moz.configure/bindgen.configure
-index 72f4d4173b..4c682da412 100644
+index 72f4d41..4c682da 100644
--- a/build/moz.configure/bindgen.configure
+++ b/build/moz.configure/bindgen.configure
@@ -203,7 +203,7 @@ def bindgen_libclang_path(libclang_path, clang, library_name_info, host):
@@ -171,7 +174,7 @@ index 72f4d4173b..4c682da412 100644
if host.os == "OpenBSD":
diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure
-index 97b9bab167..854f1fcc69 100644
+index 97b9bab..854f1fc 100644
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -539,6 +539,8 @@ def split_triplet(triplet, allow_wasi=False):
@@ -199,8 +202,21 @@ index 97b9bab167..854f1fcc69 100644
@depends(target)
def target_is_solaris(target):
if target.kernel == "SunOS":
+diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
+index 264027e..f1ce6c7 100644
+--- a/build/moz.configure/toolchain.configure
++++ b/build/moz.configure/toolchain.configure
+@@ -2693,7 +2693,7 @@ def security_hardening_cflags(
+ if (
+ c_compiler.type == "clang"
+ and c_compiler.version >= "11.0.1"
+- and target.os not in ("WINNT", "OSX", "OpenBSD")
++ and target.os not in ("WINNT", "OSX", "OpenBSD", "Haiku")
+ and target.cpu in ("x86", "x86_64", "ppc64", "s390x")
+ ):
+ flags.append("-fstack-clash-protection")
diff --git a/dom/events/ShortcutKeyDefinitions.cpp b/dom/events/ShortcutKeyDefinitions.cpp
-index 3f34f45240..97b7c986af 100644
+index 3f34f45..97b7c98 100644
--- a/dom/events/ShortcutKeyDefinitions.cpp
+++ b/dom/events/ShortcutKeyDefinitions.cpp
@@ -435,13 +435,13 @@ ShortcutKeyData ShortcutKeys::sBrowserHandlers[] = {
@@ -220,7 +236,7 @@ index 3f34f45240..97b7c986af 100644
{u"keypress", u"VK_RIGHT", nullptr, u"alt", u"cmd_moveRight2"}, // macOS
{u"keypress", u"VK_LEFT", nullptr, u"alt,shift", u"cmd_selectLeft2"}, // macOS
diff --git a/dom/media/CallbackThreadRegistry.cpp b/dom/media/CallbackThreadRegistry.cpp
-index 84ef7b7cb4..e041636121 100644
+index 84ef7b7..e041636 100644
--- a/dom/media/CallbackThreadRegistry.cpp
+++ b/dom/media/CallbackThreadRegistry.cpp
@@ -96,7 +96,9 @@ void CallbackThreadRegistry::Unregister(ProfilerThreadId aThreadId) {
@@ -233,8 +249,257 @@ index 84ef7b7cb4..e041636121 100644
}
} // namespace mozilla
+diff --git a/dom/media/webrtc/transport/common.build b/dom/media/webrtc/transport/common.build
+index b907b57..7d37654 100644
+--- a/dom/media/webrtc/transport/common.build
++++ b/dom/media/webrtc/transport/common.build
+@@ -64,6 +64,11 @@ if CONFIG["OS_TARGET"] in ["Darwin", "DragonFly", "FreeBSD", "NetBSD", "OpenBSD"
+ LOCAL_INCLUDES += [
+ "/dom/media/webrtc/transport/third_party/nrappkit/src/port/darwin/include",
+ ]
++elif CONFIG["OS_TARGET"] == "Haiku":
++ DEFINES["HAIKU"] = True
++ LOCAL_INCLUDES += [
++ "/dom/media/webrtc/transport/third_party/nrappkit/src/port/haiku/include",
++ ]
+ elif CONFIG["OS_TARGET"] == "Linux":
+ DEFINES["LINUX"] = True
+ LOCAL_INCLUDES += [
+diff --git a/dom/media/webrtc/transport/third_party/nICEr/nicer.gyp b/dom/media/webrtc/transport/third_party/nICEr/nicer.gyp
+index 488b9b2..2d8e672 100644
+--- a/dom/media/webrtc/transport/third_party/nICEr/nicer.gyp
++++ b/dom/media/webrtc/transport/third_party/nICEr/nicer.gyp
+@@ -7,7 +7,8 @@
+ #
+ {
+ 'variables' : {
+- 'have_ethtool_cmd_speed_hi%': 1
++ 'have_ethtool_cmd_speed_hi%': 1,
++ 'OS' : 'haiku'
+ },
+ 'targets' : [
+ {
+@@ -185,6 +186,38 @@
+ ],
+ }],
+
++ ## Haiku
++ [ 'OS == "haiku"', {
++ 'cflags_mozilla': [
++ '-Wall',
++ '-Wno-parentheses',
++ '-Wno-strict-prototypes',
++ '-Wmissing-prototypes',
++ '-Wno-format',
++ '-Wno-format-security',
++ ],
++ 'defines' : [
++ 'HAIKU',
++ 'HAVE_LIBM=1',
++ 'HAVE_STRDUP=1',
++ 'HAVE_STRLCPY=1',
++ 'HAVE_SYS_TIME_H=1',
++ 'HAVE_VFPRINTF=1',
++ 'NEW_STDIO'
++ 'RETSIGTYPE=void',
++ 'TIME_WITH_SYS_TIME_H=1',
++ '__UNUSED__=__attribute__((unused))',
++ 'NO_REG_RPC'
++ ],
++
++ 'include_dirs': [
++ '../nrappkit/src/port/haiku/include'
++ ],
++
++ 'sources': [
++ ],
++ }],
++
+ ## Win
+ [ 'OS == "win"', {
+ 'defines' : [
+diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c
+index 51f72f4..18ad233 100644
+--- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c
++++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/addrs.c
+@@ -204,8 +204,12 @@ nr_stun_get_addrs(nr_local_addr addrs[], int maxaddrs, int *count)
+ if (maxaddrs > 0) {
+ memset(addrs, 0, maxaddrs * sizeof(nr_local_addr));
+ }
+-
++#if defined(HAIKU)
++ count = 0;
++ _status = R_INTERNAL;
++#else
+ _status = stun_getaddrs_filtered(addrs, maxaddrs, count);
++#endif
+
+ for (i = 0; i < *count; ++i) {
+ nr_local_addr_fmt_info_string(addrs+i,typestr,sizeof(typestr));
+diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun.h b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun.h
+index a32751d..ca054e0 100644
+--- a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun.h
++++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun.h
+@@ -53,9 +53,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #include
+ #endif
+ #include
++#ifdef HAIKU
++#include
++#else
+ #ifndef LINUX
+ #include
+ #endif
++#endif
+ #include
+ #include
+ #endif
+diff --git a/dom/media/webrtc/transport/third_party/nrappkit/nrappkit.gyp b/dom/media/webrtc/transport/third_party/nrappkit/nrappkit.gyp
+index c3f88af..987a7e4 100644
+--- a/dom/media/webrtc/transport/third_party/nrappkit/nrappkit.gyp
++++ b/dom/media/webrtc/transport/third_party/nrappkit/nrappkit.gyp
+@@ -6,6 +6,9 @@
+ #
+ #
+ {
++ 'variables' : {
++ 'OS' : 'haiku'
++ },
+ 'targets' : [
+ {
+ 'target_name' : 'nrappkit',
+@@ -181,6 +184,39 @@
+ ],
+ }],
+
++ ## Haiku
++ [ 'OS == "haiku"', {
++ 'cflags_mozilla': [
++ '-Wall',
++ '-Wno-parentheses',
++ '-Wno-strict-prototypes',
++ '-Wmissing-prototypes',
++ '-Wno-format',
++ '-Wno-format-security',
++ ],
++ 'defines' : [
++ 'HAIKU',
++ 'HAVE_LIBM=1',
++ 'HAVE_STRDUP=1',
++ 'HAVE_STRLCPY=1',
++ 'HAVE_SYS_TIME_H=1',
++ 'HAVE_VFPRINTF=1',
++ 'NEW_STDIO'
++ 'RETSIGTYPE=void',
++ 'TIME_WITH_SYS_TIME_H=1',
++ '__UNUSED__=__attribute__((unused))',
++ 'NO_REG_RPC'
++ ],
++
++ 'include_dirs': [
++ 'src/port/haiku/include'
++ ],
++
++ 'sources': [
++ './src/port/haiku/include/csi_platform.h',
++ ],
++ }],
++
+ ## Win
+ [ 'OS == "win"', {
+ 'defines' : [
+diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c
+index bb47cda..0d92120 100644
+--- a/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c
++++ b/dom/media/webrtc/transport/third_party/nrappkit/src/log/r_log.c
+@@ -36,7 +36,7 @@
+ ekr@rtfm.com Mon Dec 3 15:24:38 2001
+ */
+
+-#ifdef LINUX
++#if defined(LINUX) || defined(HAIKU)
+ #define _BSD_SOURCE
+ #define _DEFAULT_SOURCE
+ #endif
+diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/port/haiku/include/csi_platform.h b/dom/media/webrtc/transport/third_party/nrappkit/src/port/haiku/include/csi_platform.h
+new file mode 100644
+index 0000000..bc8ad50
+--- /dev/null
++++ b/dom/media/webrtc/transport/third_party/nrappkit/src/port/haiku/include/csi_platform.h
+@@ -0,0 +1,58 @@
++/**
++ platform.h
++
++
++ Copyright (C) 2005, Network Resonance, Inc.
++ Copyright (C) 2006, Network Resonance, Inc.
++ All Rights Reserved
++
++ Redistribution and use in source and binary forms, with or without
++ modification, are permitted provided that the following conditions
++ are met:
++
++ 1. Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ 2. Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++ 3. Neither the name of Network Resonance, Inc. nor the name of any
++ contributors to this software may be used to endorse or promote
++ products derived from this software without specific prior written
++ permission.
++
++ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
++ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++ POSSIBILITY OF SUCH DAMAGE.
++
++
++ briank@network-resonance.com Tue Mar 15 14:28:12 PST 2005
++ */
++
++
++#ifndef _platform_h
++#define _platform_h
++
++#include
++#include
++
++#define STDIO_BYTES_BUFFERED(fp) (fp->_r)
++
++#ifdef NR_SOCKET_IS_VOID_PTR
++typedef void* NR_SOCKET;
++#else
++typedef int NR_SOCKET;
++#define NR_SOCKET_READ(sock,buf,count) read((sock),(buf),(count))
++#define NR_SOCKET_WRITE(sock,buf,count) write((sock),(buf),(count))
++#define NR_SOCKET_CLOSE(sock) close(sock)
++#endif
++
++#endif
++
+diff --git a/dom/media/webrtc/transport/third_party/nrappkit/src/share/nr_common.h b/dom/media/webrtc/transport/third_party/nrappkit/src/share/nr_common.h
+index ac3ff44..8356dc2 100644
+--- a/dom/media/webrtc/transport/third_party/nrappkit/src/share/nr_common.h
++++ b/dom/media/webrtc/transport/third_party/nrappkit/src/share/nr_common.h
+@@ -54,6 +54,8 @@
+ #ifdef WIN32
+ #include
+ #include
++#elif defined(HAIKU)
++#include
+ #else
+ #include
+ #endif
diff --git a/gfx/angle/checkout/src/common/system_utils_posix.cpp b/gfx/angle/checkout/src/common/system_utils_posix.cpp
-index ab0faee0bc..f9c9389035 100644
+index ab0faee..f9c9389 100644
--- a/gfx/angle/checkout/src/common/system_utils_posix.cpp
+++ b/gfx/angle/checkout/src/common/system_utils_posix.cpp
@@ -201,7 +201,9 @@ void *OpenSystemLibraryWithExtensionAndGetError(const char *libraryName,
@@ -248,7 +513,7 @@ index ab0faee0bc..f9c9389035 100644
std::string fullPath = directory + libraryName;
diff --git a/gfx/layers/wr/IpcResourceUpdateQueue.cpp b/gfx/layers/wr/IpcResourceUpdateQueue.cpp
-index d19dc7f2f9..dcbd9e3a42 100644
+index d19dc7f..dcbd9e3 100644
--- a/gfx/layers/wr/IpcResourceUpdateQueue.cpp
+++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp
@@ -51,7 +51,8 @@ layers::OffsetRange ShmSegmentsWriter::Write(Range aBytes) {
@@ -262,7 +527,7 @@ index d19dc7f2f9..dcbd9e3a42 100644
if (range.length()) {
// Allocation was successful
diff --git a/gfx/skia/skia/include/private/base/SkTArray.h b/gfx/skia/skia/include/private/base/SkTArray.h
-index c02498e800..9370949898 100644
+index c02498e..9370949 100644
--- a/gfx/skia/skia/include/private/base/SkTArray.h
+++ b/gfx/skia/skia/include/private/base/SkTArray.h
@@ -539,7 +539,7 @@ private:
@@ -275,7 +540,7 @@ index c02498e800..9370949898 100644
void setDataFromBytes(SkSpan allocation) {
T* data = TCast(allocation.data());
diff --git a/image/SurfaceCache.cpp b/image/SurfaceCache.cpp
-index cccbd505f5..df9fadd116 100644
+index cccbd50..df9fadd 100644
--- a/image/SurfaceCache.cpp
+++ b/image/SurfaceCache.cpp
@@ -1626,7 +1626,7 @@ void SurfaceCache::Initialize() {
@@ -288,7 +553,7 @@ index cccbd505f5..df9fadd116 100644
#endif
memorySize = 256 * 1024 * 1024; // Fall back to 256MB.
diff --git a/ipc/chromium/moz.build b/ipc/chromium/moz.build
-index 429c068d34..50d8c91fbe 100644
+index 429c068..50d8c91 100644
--- a/ipc/chromium/moz.build
+++ b/ipc/chromium/moz.build
@@ -102,7 +102,7 @@ if CONFIG["TARGET_OS"] == "iOS":
@@ -301,7 +566,7 @@ index 429c068d34..50d8c91fbe 100644
"src/base/process_util_linux.cc",
"src/base/time_posix.cc",
diff --git a/ipc/chromium/src/base/message_loop.cc b/ipc/chromium/src/base/message_loop.cc
-index c82d555ee5..f4270f9870 100644
+index c82d555..f4270f9 100644
--- a/ipc/chromium/src/base/message_loop.cc
+++ b/ipc/chromium/src/base/message_loop.cc
@@ -27,7 +27,7 @@
@@ -323,7 +588,7 @@ index c82d555ee5..f4270f9870 100644
# endif // XP_LINUX
} else if (type_ == TYPE_IO) {
diff --git a/ipc/chromium/src/base/platform_thread.h b/ipc/chromium/src/base/platform_thread.h
-index f3a65e8797..40ad58b8c3 100644
+index f3a65e8..40ad58b 100644
--- a/ipc/chromium/src/base/platform_thread.h
+++ b/ipc/chromium/src/base/platform_thread.h
@@ -24,7 +24,7 @@ typedef void* PlatformThreadHandle; // HANDLE
@@ -336,7 +601,7 @@ index f3a65e8797..40ad58b8c3 100644
# include
typedef pid_t PlatformThreadId;
diff --git a/ipc/chromium/src/base/platform_thread_posix.cc b/ipc/chromium/src/base/platform_thread_posix.cc
-index d28abbc91f..af56adf9ff 100644
+index d28abbc..af56adf 100644
--- a/ipc/chromium/src/base/platform_thread_posix.cc
+++ b/ipc/chromium/src/base/platform_thread_posix.cc
@@ -16,6 +16,8 @@
@@ -358,7 +623,7 @@ index d28abbc91f..af56adf9ff 100644
}
diff --git a/ipc/chromium/src/base/process_util_posix.cc b/ipc/chromium/src/base/process_util_posix.cc
-index 57ae82ebbf..a33b94c74d 100644
+index 57ae82e..a33b94c 100644
--- a/ipc/chromium/src/base/process_util_posix.cc
+++ b/ipc/chromium/src/base/process_util_posix.cc
@@ -123,7 +123,7 @@ void CloseSuperfluousFds(void* aCtx, bool (*aShouldPreserve)(void*, int)) {
@@ -371,7 +636,7 @@ index 57ae82ebbf..a33b94c74d 100644
static const char kFDDir[] = "/proc/self/fd";
#elif defined(XP_DARWIN)
diff --git a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
-index 19e777a52a..f893ba4a8b 100644
+index 19e777a..f893ba4 100644
--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
+++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
@@ -326,6 +326,18 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
@@ -404,7 +669,7 @@ index 19e777a52a..f893ba4a8b 100644
}
}
diff --git a/js/src/moz.build b/js/src/moz.build
-index b2befdb350..946707f846 100644
+index b2befdb..946707f 100644
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -509,6 +509,11 @@ elif CONFIG["OS_ARCH"] == "WASI":
@@ -420,7 +685,7 @@ index b2befdb350..946707f846 100644
"threading/posix/CpuCount.cpp",
"threading/posix/PosixThread.cpp",
diff --git a/js/src/util/NativeStack.cpp b/js/src/util/NativeStack.cpp
-index 4e4189d397..37dc13aefb 100644
+index 4e4189d..37dc13a 100644
--- a/js/src/util/NativeStack.cpp
+++ b/js/src/util/NativeStack.cpp
@@ -31,6 +31,9 @@
@@ -449,7 +714,7 @@ index 4e4189d397..37dc13aefb 100644
// Since we rearrange the layout for wasi via --stack-first flag for the linker
diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp
-index f838b7bec0..228e5e8e95 100644
+index f838b7b..228e5e8 100644
--- a/js/src/wasm/WasmSignalHandlers.cpp
+++ b/js/src/wasm/WasmSignalHandlers.cpp
@@ -234,6 +234,17 @@ using mozilla::DebugOnly;
@@ -470,8 +735,21 @@ index f838b7bec0..228e5e8e95 100644
# elif defined(XP_DARWIN)
# define EIP_sig(p) ((p)->thread.uts.ts32.__eip)
# define EBP_sig(p) ((p)->thread.uts.ts32.__ebp)
+diff --git a/media/ffvpx/config_unix64.h b/media/ffvpx/config_unix64.h
+index 7d63f47..2fe6932 100644
+--- a/media/ffvpx/config_unix64.h
++++ b/media/ffvpx/config_unix64.h
+@@ -291,7 +291,7 @@
+ #define HAVE_COMMANDLINETOARGVW 0
+ #define HAVE_FCNTL 1
+ #define HAVE_GETADDRINFO 1
+-#define HAVE_GETAUXVAL 1
++#define HAVE_GETAUXVAL 0
+ #define HAVE_GETENV 1
+ #define HAVE_GETHRTIME 0
+ #define HAVE_GETOPT 1
diff --git a/media/libcubeb/src/cubeb.c b/media/libcubeb/src/cubeb.c
-index b0db033d4f..efe0927d4a 100644
+index b0db033..efe0927 100644
--- a/media/libcubeb/src/cubeb.c
+++ b/media/libcubeb/src/cubeb.c
@@ -79,6 +79,10 @@ oss_init(cubeb ** context, char const * context_name);
@@ -506,8 +784,966 @@ index b0db033d4f..efe0927d4a 100644
#if defined(USE_OPENSL)
opensl_init,
#endif
+diff --git a/media/libcubeb/src/cubeb_haiku.cpp b/media/libcubeb/src/cubeb_haiku.cpp
+new file mode 100644
+index 0000000..db30a02
+--- /dev/null
++++ b/media/libcubeb/src/cubeb_haiku.cpp
+@@ -0,0 +1,952 @@
++/*
++ * Copyright © 2024-2025 Troeglazov Gerasim
++ *
++ * This program is made available under an ISC-style license. See the
++ * accompanying file LICENSE for details.
++ */
++
++#include "cubeb-internal.h"
++#include "cubeb/cubeb.h"
++#include "cubeb_utils.h"
++#include "cubeb_ringbuffer.h"
++
++#include
++#include
++#include
++#include
++#include
++#include
++
++// Workaround for gcc_hidden.h hack of libxul.so
++#pragma GCC visibility push(default)
++
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++
++#include
++
++#pragma GCC visibility pop
++
++static const int MAX_CHANNELS = 2;
++static const char DEFAULT_CONTEXT_NAME[] = "Cubeb";
++
++static const char HAIKU_DEFAULT_IN[] = "Default Input";
++static const char HAIKU_DEFAULT_OUT[] = "Default Output";
++
++#define HAIKU_DEFAULT_IN_ID ((cubeb_devid)(uintptr_t)HAIKU_DEFAULT_IN)
++#define HAIKU_DEFAULT_OUT_ID ((cubeb_devid)(uintptr_t)HAIKU_DEFAULT_OUT)
++
++// Function Declarations
++extern "C" {
++int haiku_init(cubeb ** context, char const * context_name);
++}
++static void haiku_destroy(cubeb* context);
++static char const* haiku_get_backend_id(cubeb* context);
++static int haiku_get_max_channel_count(cubeb* ctx, uint32_t* max_channels);
++static int haiku_get_min_latency(cubeb* ctx, cubeb_stream_params params, uint32_t* latency_frames);
++static int haiku_get_preferred_sample_rate(cubeb* ctx, uint32_t* rate);
++static int haiku_stream_init(cubeb* context,
++ cubeb_stream** stream,
++ char const* stream_name,
++ cubeb_devid input_device,
++ cubeb_stream_params* input_stream_params,
++ cubeb_devid output_device,
++ cubeb_stream_params* output_stream_params,
++ unsigned int latency_frames,
++ cubeb_data_callback data_callback,
++ cubeb_state_callback state_callback,
++ void* user_ptr);
++static void haiku_stream_destroy(cubeb_stream* stream);
++static int haiku_stream_start(cubeb_stream* stream);
++static int haiku_stream_stop(cubeb_stream* stream);
++static int haiku_stream_get_position(cubeb_stream* stream, uint64_t* position);
++static int haiku_stream_get_latency(cubeb_stream* stream, uint32_t* latency_frames);
++static int haiku_stream_set_volume(cubeb_stream* stream, float volume);
++static int haiku_stream_get_current_device(cubeb_stream* stream, cubeb_device** const device);
++static int haiku_enumerate_devices(cubeb* context, cubeb_device_type type, cubeb_device_collection* collection);
++static int haiku_device_collection_destroy(cubeb* context, cubeb_device_collection* collection);
++
++// Cubeb Ops Table
++static struct cubeb_ops const cubeb_haiku_ops = {
++ .init = haiku_init,
++ .get_backend_id = haiku_get_backend_id,
++ .get_max_channel_count = haiku_get_max_channel_count,
++ .get_min_latency = haiku_get_min_latency,
++ .get_preferred_sample_rate = haiku_get_preferred_sample_rate,
++ .get_supported_input_processing_params = NULL,
++ .enumerate_devices = haiku_enumerate_devices,
++ .device_collection_destroy = haiku_device_collection_destroy,
++ .destroy = haiku_destroy,
++ .stream_init = haiku_stream_init,
++ .stream_destroy = haiku_stream_destroy,
++ .stream_start = haiku_stream_start,
++ .stream_stop = haiku_stream_stop,
++ .stream_get_position = haiku_stream_get_position,
++ .stream_get_latency = haiku_stream_get_latency,
++ .stream_set_volume = haiku_stream_set_volume,
++ .stream_set_name = NULL,
++ .stream_get_current_device = haiku_stream_get_current_device,
++ .stream_set_input_mute = NULL,
++ .stream_set_input_processing_params = NULL,
++ .stream_device_destroy = NULL,
++ .stream_register_device_changed_callback = NULL,
++ .register_device_collection_changed = NULL,
++};
++
++// Forward declaration for input thread function
++static void* input_thread_func(void* user_data);
++
++// Stream and Context Structs
++struct cubeb_stream {
++ /* Note: Must match cubeb_stream layout in cubeb.c. */
++ cubeb* context;
++ void* user_ptr;
++ /**/
++
++ pthread_mutex_t mutex;
++
++ cubeb_data_callback data_callback;
++ cubeb_state_callback state_callback;
++
++ // Output related members
++ cubeb_stream_params output_params;
++ BSoundPlayer* sound_player;
++ media_raw_audio_format output_format_haiku;
++ uint64_t output_position;
++ bool output_pause;
++ float output_volume;
++
++ // Input related members
++ cubeb_stream_params input_params;
++ AudioCapture* audio_capturer;
++ lock_free_audio_ring_buffer* input_ring_buffer;
++ float* input_temp_buffer;
++ size_t input_temp_buffer_frames;
++ bool input_enabled;
++ uint32_t input_channels_cubeb;
++ uint32_t input_channels_capture;
++
++ // Input thread (for input-only streams)
++ pthread_t input_thread;
++ bool input_thread_running;
++ bool input_thread_created;
++
++ char stream_name[256];
++};
++
++struct cubeb {
++ struct cubeb_ops const* ops;
++ pthread_mutex_t mutex;
++ char context_name[256];
++};
++
++// AudioCapture Callback (Input)
++static void
++haiku_audio_input_callback(const float* stereoData, size_t frameCount, void* userData)
++{
++ cubeb_stream* stm = static_cast(userData);
++
++ if (!stm || !stm->input_enabled || !stm->input_ring_buffer) {
++ return;
++ }
++
++ // AudioCapture always provides stereo (2 channels)
++ if (stm->input_channels_cubeb == 1 && stm->input_channels_capture == 2) {
++ float* mono_buffer = (float*)malloc(frameCount * sizeof(float));
++ if (!mono_buffer) {
++ fprintf(stderr, "Cubeb Haiku: Failed to allocate mono buffer in capture callback!\n");
++ return;
++ }
++ for (size_t i = 0; i < frameCount; ++i) {
++ mono_buffer[i] = stereoData[i * 2]; // Take left channel
++ }
++ int written_frames = stm->input_ring_buffer->enqueue(mono_buffer, frameCount);
++ free(mono_buffer);
++ if (written_frames != (int)frameCount) {
++ fprintf(stderr, "Cubeb Haiku: Input ring buffer enqueue failed/partial (%d/%zu frames)\n", written_frames, frameCount);
++ }
++ } else {
++ int written_frames = stm->input_ring_buffer->enqueue(const_cast(stereoData), frameCount);
++ if (written_frames != (int)frameCount) {
++ fprintf(stderr, "Cubeb Haiku: Input ring buffer enqueue failed/partial (%d/%zu frames)\n", written_frames, frameCount);
++ }
++ }
++}
++
++// BSoundPlayer Callback (Output)
++static void
++haiku_audio_output_callback(void* cookie, void* buffer, size_t size, const media_raw_audio_format& format)
++{
++ cubeb_stream* stm = static_cast(cookie);
++
++ if (buffer == nullptr || cookie == nullptr) {
++ fprintf(stderr, "Cubeb Haiku: Invalid args in output callback\n");
++ return;
++ }
++
++ long output_frames = 0;
++ uint32_t output_bytes_per_frame = 0;
++ if (format.channel_count > 0) {
++ if (format.format == media_raw_audio_format::B_AUDIO_FLOAT) {
++ output_bytes_per_frame = format.channel_count * sizeof(float);
++ } else {
++ fprintf(stderr, "Cubeb Haiku: Unexpected output format in callback: 0x%x\n", format.format);
++ memset(buffer, 0, size); // Silence on error
++ return;
++ }
++ if (output_bytes_per_frame > 0) {
++ output_frames = size / output_bytes_per_frame;
++ }
++ }
++
++ if (output_frames <= 0) {
++ fprintf(stderr, "Cubeb Haiku: Zero frames requested in output callback\n");
++ return;
++ }
++
++ if (stm->output_pause) {
++ memset(buffer, 0, size);
++ return;
++ }
++
++ if (pthread_mutex_lock(&stm->mutex) != 0) {
++ // Failed to lock, mutex error. Output silence
++ fprintf(stderr, "Cubeb Haiku: Mutex lock failed in output callback\n");
++ memset(buffer, 0, size);
++ return;
++ }
++
++ void* input_buffer_ptr = nullptr;
++ long input_frames_read = 0; // Frames read from ring buffer
++
++ // Handle input if enabled
++ if (stm->input_enabled && stm->input_ring_buffer) {
++ // Ensure temporary input buffer is large enough
++ if (stm->input_temp_buffer_frames < (size_t)output_frames) {
++ free(stm->input_temp_buffer);
++ // Allocate based on channels requested by cubeb
++ stm->input_temp_buffer = (float*)malloc(output_frames * stm->input_params.channels * sizeof(float));
++ if (!stm->input_temp_buffer) {
++ fprintf(stderr, "Cubeb Haiku: Failed to allocate input temp buffer\n");
++ stm->input_temp_buffer_frames = 0;
++ memset(buffer, 0, size); // Output silence on error
++ pthread_mutex_unlock(&stm->mutex);
++ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
++ return;
++ }
++ stm->input_temp_buffer_frames = output_frames;
++ }
++
++ // Dequeue data from the ring buffer into the temp buffer
++ input_frames_read = stm->input_ring_buffer->dequeue(stm->input_temp_buffer, output_frames);
++
++ if (input_frames_read < output_frames) {
++ size_t remaining_frames = output_frames - input_frames_read;
++ size_t offset_samples = input_frames_read * stm->input_params.channels;
++ memset(stm->input_temp_buffer + offset_samples, 0, remaining_frames * stm->input_params.channels * sizeof(float));
++ input_frames_read = output_frames; // We filled the gap with silence
++ }
++ input_buffer_ptr = stm->input_temp_buffer;
++ }
++
++ // Call the user's data callback
++ long frames_processed = stm->data_callback(stm, stm->user_ptr,
++ input_buffer_ptr,
++ buffer,
++ output_frames);
++
++ // Check callback result
++ if (frames_processed < 0 || frames_processed > output_frames) {
++ memset(buffer, 0, size);
++ stm->output_position += output_frames;
++ pthread_mutex_unlock(&stm->mutex);
++ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
++ fprintf(stderr, "Cubeb Haiku: User callback error (%ld/%ld frames)\n", frames_processed, output_frames);
++ return;
++ }
++
++ if (frames_processed < output_frames) {
++ size_t remaining_frames = output_frames - frames_processed;
++ size_t offset_bytes = frames_processed * output_bytes_per_frame;
++ memset((char*)buffer + offset_bytes, 0, remaining_frames * output_bytes_per_frame);
++ }
++
++ stm->output_position += output_frames;
++ pthread_mutex_unlock(&stm->mutex);
++}
++
++// Input Thread Function (for Input-Only streams)
++static void* input_thread_func(void* user_data) {
++ cubeb_stream* stm = static_cast(user_data);
++ if (!stm || !stm->input_enabled || !stm->input_ring_buffer) {
++ return NULL;
++ }
++
++ // Target chunk size in frames (e.g., ~20ms)
++ unsigned int frames_per_iteration = (stm->input_params.rate * 20) / 1000;
++ if (frames_per_iteration < 128) frames_per_iteration = 128;
++
++ // Allocate buffer for reading data from ring buffer
++ float* read_buffer = (float*)malloc(frames_per_iteration * stm->input_params.channels * sizeof(float));
++ if (!read_buffer) {
++ fprintf(stderr, "Cubeb Haiku: Failed to allocate read buffer for input thread\n");
++ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
++ stm->input_thread_running = false;
++ return NULL;
++ }
++
++ printf("Cubeb Haiku: Input thread started (chunk size: %u frames)\n", frames_per_iteration);
++
++ while (stm->input_thread_running) {
++ // Check available frames without blocking excessively
++ int frames_available = stm->input_ring_buffer->available_read();
++
++ if (frames_available >= (int)frames_per_iteration) {
++ // Dequeue data
++ int frames_read = stm->input_ring_buffer->dequeue(read_buffer, frames_per_iteration);
++
++ if (frames_read > 0) {
++ // Lock mutex before calling user callback
++ if (pthread_mutex_lock(&stm->mutex) == 0) {
++ long frames_processed = stm->data_callback(stm, stm->user_ptr,
++ read_buffer,
++ nullptr,
++ frames_read);
++ pthread_mutex_unlock(&stm->mutex);
++
++ if (frames_processed < 0 || frames_processed > frames_read) {
++ fprintf(stderr, "Cubeb Haiku: User callback error in input thread (%ld/%d frames)\n", frames_processed, frames_read);
++ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
++ // Optional: Stop thread on error?
++ // stm->input_thread_running = false;
++ }
++ } else {
++ fprintf(stderr, "Cubeb Haiku: Mutex lock failed in input thread\n");
++ }
++ }
++ } else {
++ // Not enough data, wait a bit
++ usleep(5 * 1000); // Sleep 5ms
++ }
++ }
++
++ printf("Cubeb Haiku: Input thread stopping.\n");
++ free(read_buffer);
++ return NULL;
++}
++
++
++// Utility Functions
++
++static size_t calculate_haiku_buffer_size(cubeb_stream_params* params, unsigned int latency_frames)
++{
++ if (!params || params->rate == 0 || params->channels == 0)
++ return 2048;
++
++ return 1024 * params->channels;
++}
++
++
++static media_raw_audio_format
++cubeb_format_to_haiku(cubeb_stream_params *params, size_t buffer_size_bytes)
++{
++ media_raw_audio_format format;
++ memset(&format, 0, sizeof(format));
++ if (!params) return format;
++
++ format.frame_rate = params->rate;
++ format.channel_count = params->channels;
++ format.buffer_size = buffer_size_bytes;
++ format.byte_order = B_MEDIA_HOST_ENDIAN;
++
++ if (params->format == CUBEB_SAMPLE_FLOAT32NE) {
++ format.format = media_raw_audio_format::B_AUDIO_FLOAT;
++ } else {
++ format.format = 0; // Mark as invalid/unsupported
++ }
++ return format;
++}
++
++// Cubeb API Implementation
++
++int
++haiku_init(cubeb** context, char const* context_name)
++{
++ *context = NULL;
++ cubeb* ctx = (cubeb*)calloc(1, sizeof(*ctx));
++ if (!ctx)
++ return CUBEB_ERROR;
++
++ ctx->ops = &cubeb_haiku_ops;
++ if (pthread_mutex_init(&ctx->mutex, NULL) != 0) {
++ free(ctx);
++ return CUBEB_ERROR;
++ }
++
++ snprintf(ctx->context_name, sizeof(ctx->context_name), "%s", context_name ? context_name : DEFAULT_CONTEXT_NAME);
++ *context = ctx;
++
++ return CUBEB_OK;
++}
++
++static void
++haiku_destroy(cubeb* context)
++{
++ if (!context)
++ return;
++
++ pthread_mutex_destroy(&context->mutex);
++ free(context);
++}
++
++static char const*
++haiku_get_backend_id(cubeb* context)
++{
++ return "haiku";
++}
++
++static int
++haiku_get_max_channel_count(cubeb* ctx, uint32_t* max_channels)
++{
++ *max_channels = MAX_CHANNELS;
++ return CUBEB_OK;
++}
++
++static int
++haiku_get_min_latency(cubeb* ctx, cubeb_stream_params params, uint32_t* latency_frames)
++{
++ if (params.rate == 0)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ *latency_frames = (params.rate * 10) / 1000; // ~10ms
++ if (*latency_frames < 128) *latency_frames = 128;
++
++ return CUBEB_OK;
++}
++
++static int
++haiku_get_preferred_sample_rate(cubeb* ctx, uint32_t* rate)
++{
++ *rate = 48000;
++ return CUBEB_OK;
++}
++
++static int
++haiku_stream_init(cubeb* context,
++ cubeb_stream** stream,
++ char const* stream_name,
++ cubeb_devid input_device,
++ cubeb_stream_params* input_stream_params,
++ cubeb_devid output_device,
++ cubeb_stream_params* output_stream_params,
++ unsigned int latency_frames,
++ cubeb_data_callback data_callback,
++ cubeb_state_callback state_callback,
++ void* user_ptr)
++{
++ if (!context || !stream || !data_callback || !state_callback)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ if (!input_stream_params && !output_stream_params)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ if (output_stream_params) {
++ if (output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE)
++ return CUBEB_ERROR_INVALID_FORMAT;
++ if (output_stream_params->rate == 0 || output_stream_params->channels == 0 || output_stream_params->channels > MAX_CHANNELS)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++ if (output_device != NULL && output_device != HAIKU_DEFAULT_OUT_ID)
++ return CUBEB_ERROR_DEVICE_UNAVAILABLE;
++ if (output_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK)
++ return CUBEB_ERROR_NOT_SUPPORTED;
++ }
++
++ if (input_stream_params) {
++ if (input_stream_params->format != CUBEB_SAMPLE_FLOAT32NE)
++ return CUBEB_ERROR_INVALID_FORMAT;
++ if (input_stream_params->rate == 0 || input_stream_params->channels == 0 || input_stream_params->channels > MAX_CHANNELS)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++ if (input_device != NULL && input_device != HAIKU_DEFAULT_IN_ID)
++ return CUBEB_ERROR_DEVICE_UNAVAILABLE;
++ if (input_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK)
++ return CUBEB_ERROR_NOT_SUPPORTED;
++ }
++
++ if (input_stream_params && output_stream_params && input_stream_params->rate != output_stream_params->rate) {
++ fprintf(stderr, "Cubeb Haiku: Input/output rate mismatch not supported (%u != %u).\n",
++ input_stream_params->rate, output_stream_params->rate);
++ return CUBEB_ERROR_INVALID_PARAMETER;
++ }
++
++ // Allocate Stream
++ *stream = NULL;
++ cubeb_stream* stm = reinterpret_cast(calloc(1, sizeof(*stm)));
++ if (!stm)
++ return CUBEB_ERROR;
++
++ stm->context = context;
++ stm->user_ptr = user_ptr;
++ stm->data_callback = data_callback;
++ stm->state_callback = state_callback;
++ stm->output_volume = 1.0f;
++ stm->output_position = 0;
++ stm->sound_player = nullptr;
++ stm->audio_capturer = nullptr;
++ stm->input_ring_buffer = nullptr;
++ stm->input_temp_buffer = nullptr;
++ stm->input_temp_buffer_frames = 0;
++ stm->input_thread_created = false;
++ stm->input_thread_running = false;
++
++ pthread_mutex_lock(&context->mutex);
++ if (stream_name && strcmp(stream_name, "AudioStream") != 0) {
++ snprintf(stm->stream_name, sizeof(stm->stream_name), "%s", stream_name);
++ } else {
++ snprintf(stm->stream_name, sizeof(stm->stream_name), "%s", context->context_name);
++ }
++ pthread_mutex_unlock(&context->mutex);
++
++ if (pthread_mutex_init(&stm->mutex, NULL) != 0) {
++ free(stm);
++ return CUBEB_ERROR;
++ }
++
++ pthread_mutex_lock(&stm->mutex);
++
++ // Configure Input
++ if (input_stream_params) {
++ stm->input_enabled = true;
++ stm->input_params = *input_stream_params;
++ stm->input_channels_cubeb = input_stream_params->channels;
++
++ uint32_t rate;
++ haiku_get_preferred_sample_rate(context, &rate);
++
++ stm->audio_capturer = new AudioCapture(haiku_audio_input_callback, stm, rate);
++ if (!stm->audio_capturer || stm->audio_capturer->Status() != B_OK) {
++ fprintf(stderr, "Cubeb Haiku: Failed to initialize AudioCapture: %s\n", stm->audio_capturer ? strerror(stm->audio_capturer->Status()) : "alloc failed");
++ goto init_error;
++ }
++
++ float capture_rate = stm->audio_capturer->TargetSampleRate();
++ if (abs(capture_rate - input_stream_params->rate) > 1.0f) {
++ fprintf(stderr, "Cubeb Haiku: Input sample rate mismatch! Requested: %u, Device: %.1f\n", input_stream_params->rate, capture_rate);
++ goto init_error_format;
++ }
++ stm->input_channels_capture = stm->audio_capturer->InputChannelCount();
++ if (stm->input_channels_cubeb > stm->input_channels_capture) {
++ fprintf(stderr, "Cubeb Haiku: Requested input channels (%u) > available (%u)\n", stm->input_channels_cubeb, stm->input_channels_capture);
++ goto init_error_param;
++ }
++
++ // Initialize Ring Buffer
++ size_t ring_buffer_frames = latency_frames * 8;
++ if (ring_buffer_frames < 2048)
++ ring_buffer_frames = 2048;
++
++ stm->input_ring_buffer = new lock_free_audio_ring_buffer(stm->input_params.channels, ring_buffer_frames);
++ if (!stm->input_ring_buffer) {
++ fprintf(stderr, "Cubeb Haiku: Failed to initialize input ring buffer (alloc)\n");
++ goto init_error_nomem;
++ }
++ } else {
++ stm->input_enabled = false;
++ }
++
++ // Configure Output
++ if (output_stream_params) {
++ stm->output_params = *output_stream_params;
++ size_t buffer_size_bytes = calculate_haiku_buffer_size(&stm->output_params, latency_frames);
++ stm->output_format_haiku = cubeb_format_to_haiku(&stm->output_params, buffer_size_bytes);
++ if (stm->output_format_haiku.format == 0) {
++ fprintf(stderr, "Cubeb Haiku: Output format mapping failed.\n");
++ goto init_error_format;
++ }
++ } else {
++ memset(&stm->output_params, 0, sizeof(stm->output_params));
++ }
++
++ *stream = stm;
++
++ pthread_mutex_unlock(&stm->mutex);
++
++ return CUBEB_OK;
++
++// --- Error Handling ---
++init_error_nomem:
++ if (stm->audio_capturer) delete stm->audio_capturer;
++ pthread_mutex_unlock(&stm->mutex);
++ pthread_mutex_destroy(&stm->mutex);
++ free(stm);
++ return CUBEB_ERROR;
++
++init_error_format:
++ if (stm->audio_capturer) delete stm->audio_capturer;
++ if (stm->input_ring_buffer) delete stm->input_ring_buffer;
++ pthread_mutex_unlock(&stm->mutex);
++ pthread_mutex_destroy(&stm->mutex);
++ free(stm);
++ return CUBEB_ERROR_INVALID_FORMAT;
++
++init_error_param:
++ if (stm->audio_capturer) delete stm->audio_capturer;
++ if (stm->input_ring_buffer) delete stm->input_ring_buffer;
++ pthread_mutex_unlock(&stm->mutex);
++ pthread_mutex_destroy(&stm->mutex);
++ free(stm);
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++init_error: // Generic error
++ if (stm->audio_capturer) delete stm->audio_capturer;
++ if (stm->input_ring_buffer) delete stm->input_ring_buffer;
++ pthread_mutex_unlock(&stm->mutex);
++ pthread_mutex_destroy(&stm->mutex);
++ free(stm);
++ return CUBEB_ERROR;
++}
++
++static void
++haiku_stream_destroy(cubeb_stream* stm)
++{
++ if (!stm)
++ return;
++
++ haiku_stream_stop(stm);
++
++ pthread_mutex_lock(&stm->mutex);
++
++ free(stm->input_temp_buffer);
++
++ if (stm->audio_capturer)
++ delete stm->audio_capturer;
++
++ if (stm->input_ring_buffer)
++ delete stm->input_ring_buffer;
++
++ pthread_mutex_unlock(&stm->mutex);
++ pthread_mutex_destroy(&stm->mutex);
++
++ free(stm);
++}
++
++static int
++haiku_stream_start(cubeb_stream* stm)
++{
++ if (!stm)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ int rc = CUBEB_OK;
++ bool input_started = false, output_started = false;
++
++ pthread_mutex_lock(&stm->mutex);
++
++ // Start Input
++ if (stm->input_enabled && stm->audio_capturer && !stm->audio_capturer->IsRunning()) {
++ status_t capture_status = stm->audio_capturer->Start();
++ if (capture_status == B_OK) {
++ input_started = true;
++ } else {
++ fprintf(stderr, "Cubeb Haiku: Failed start AudioCapture: %s\n", strerror(capture_status));
++ rc = CUBEB_ERROR;
++ }
++ } else if (stm->input_enabled && stm->audio_capturer && stm->audio_capturer->IsRunning()) {
++ input_started = true;
++ }
++
++ // Start Input Thread
++ if (rc == CUBEB_OK && input_started && !stm->sound_player && stm->output_params.rate == 0 && !stm->input_thread_created) {
++ stm->input_thread_running = true;
++ if (pthread_create(&stm->input_thread, NULL, input_thread_func, stm) == 0) {
++ stm->input_thread_created = true;
++ } else {
++ fprintf(stderr, "Cubeb Haiku: Failed create input thread\n");
++
++ stm->input_thread_running = false;
++ rc = CUBEB_ERROR;
++
++ if (stm->audio_capturer)
++ stm->audio_capturer->Stop();
++
++ input_started = false;
++ }
++ }
++
++ // Start Output
++ if (rc == CUBEB_OK && stm->output_params.rate > 0) {
++ if (!stm->sound_player) {
++ stm->sound_player = new BSoundPlayer(&stm->output_format_haiku, stm->stream_name,
++ haiku_audio_output_callback, nullptr, stm);
++ if (!stm->sound_player || stm->sound_player->InitCheck() != B_OK) {
++ fprintf(stderr, "Cubeb Haiku: Failed create BSoundPlayer: %s\n",
++ stm->sound_player ? strerror(stm->sound_player->InitCheck()) : "alloc failed");
++ delete stm->sound_player;
++
++ stm->sound_player = nullptr;
++ rc = CUBEB_ERROR;
++
++ if (input_started && stm->audio_capturer)
++ stm->audio_capturer->Stop();
++
++ if (stm->input_thread_created)
++ stm->input_thread_running = false;
++ } else {
++ stm->output_pause = false;
++ stm->sound_player->SetVolume(stm->output_volume);
++ stm->sound_player->Start();
++ stm->sound_player->SetHasData(true);
++ output_started = true;
++ }
++ } else {
++ stm->output_pause = false;
++ stm->sound_player->SetHasData(true);
++ output_started = true;
++ }
++ }
++
++ pthread_mutex_unlock(&stm->mutex);
++
++ // State Callback
++ if (rc == CUBEB_OK && (input_started || output_started)) {
++ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
++ } else if (rc != CUBEB_OK) {
++ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
++ }
++
++ return rc;
++}
++
++static int
++haiku_stream_stop(cubeb_stream* stm)
++{
++ printf("haiku_stream_stop\n");
++ if (!stm)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ bool needs_stopped_cb = false;
++
++ // Stop Input Thread
++ if (stm->input_thread_created) {
++ pthread_mutex_lock(&stm->mutex);
++ bool was_running = stm->input_thread_running;
++ stm->input_thread_running = false;
++ pthread_mutex_unlock(&stm->mutex);
++ if (was_running) {
++ pthread_join(stm->input_thread, NULL);
++ needs_stopped_cb = true;
++ }
++ stm->input_thread_created = false;
++ }
++
++ pthread_mutex_lock(&stm->mutex);
++
++ // Stop Input Device
++ if (stm->input_enabled && stm->audio_capturer && stm->audio_capturer->IsRunning()) {
++ stm->audio_capturer->Stop();
++ needs_stopped_cb = true;
++ }
++
++ // Stop Output Device
++ if (stm->sound_player) {
++ stm->output_pause = true;
++ stm->sound_player->SetHasData(false);
++ stm->sound_player->Stop();
++ delete stm->sound_player;
++ stm->sound_player = nullptr;
++ needs_stopped_cb = true;
++ }
++
++ pthread_mutex_unlock(&stm->mutex);
++
++ // State Callback
++ if (needs_stopped_cb)
++ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
++
++ return CUBEB_OK;
++}
++
++static int
++haiku_stream_get_position(cubeb_stream* stm, uint64_t* position)
++{
++ if (!stm || !position)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ pthread_mutex_lock(&stm->mutex);
++ *position = stm->output_position;
++ pthread_mutex_unlock(&stm->mutex);
++
++ return CUBEB_OK;
++}
++
++static int
++haiku_stream_get_latency(cubeb_stream* stm, uint32_t* latency_frames)
++{
++ if (!stm || !latency_frames) return CUBEB_ERROR_INVALID_PARAMETER;
++ pthread_mutex_lock(&stm->mutex);
++ if (stm->sound_player && stm->output_format_haiku.channel_count > 0) {
++ uint32_t bytes_per_frame = stm->output_format_haiku.channel_count * sizeof(float);
++ *latency_frames = (bytes_per_frame > 0) ? (stm->output_format_haiku.buffer_size / bytes_per_frame) : 0;
++ } else if (stm->input_enabled && stm->input_ring_buffer) {
++ // Estimate: half ring buffer + capture latency guess
++ size_t ring_buffer_latency = stm->input_ring_buffer->capacity() / 2;
++ uint32_t capture_latency_est = (stm->input_params.rate * 15) / 1000; // ~15ms
++ *latency_frames = capture_latency_est + ring_buffer_latency;
++ } else { *latency_frames = 0; }
++ pthread_mutex_unlock(&stm->mutex);
++ return CUBEB_OK;
++}
++
++static int
++haiku_stream_set_volume(cubeb_stream* stm, float volume)
++{
++ if (!stm)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ float clamped_volume = std::max(0.0f, std::min(1.0f, volume));
++
++ pthread_mutex_lock(&stm->mutex);
++
++ stm->output_volume = clamped_volume;
++
++ if (stm->sound_player)
++ stm->sound_player->SetVolume(stm->output_volume);
++
++ pthread_mutex_unlock(&stm->mutex);
++
++ return CUBEB_OK;
++}
++
++
++static int
++haiku_stream_get_current_device(cubeb_stream* stm, cubeb_device** const device)
++{
++ if (!stm || !device)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ static cubeb_device output_device_info;
++ static cubeb_device input_device_info;
++ static bool static_devices_initialized = false;
++
++ if (!static_devices_initialized) {
++ output_device_info.output_name = (char *)HAIKU_DEFAULT_OUT;
++ output_device_info.input_name = NULL;
++ input_device_info.input_name = (char *)HAIKU_DEFAULT_IN;
++ input_device_info.output_name = NULL;
++ static_devices_initialized = true;
++ }
++
++ pthread_mutex_lock(&stm->mutex);
++ bool has_output = (stm->output_params.rate > 0);
++ bool has_input = stm->input_enabled;
++ pthread_mutex_unlock(&stm->mutex);
++
++ if (has_output) {
++ *device = &output_device_info;
++ } else if (has_input) {
++ *device = &input_device_info;
++ } else {
++ return CUBEB_ERROR;
++ }
++
++ return CUBEB_OK;
++}
++
++static int
++haiku_enumerate_devices(cubeb* context, cubeb_device_type type,
++ cubeb_device_collection* collection)
++{
++ if (!context || !collection)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ collection->device = NULL;
++ collection->count = 0;
++ int device_count = 0;
++
++ if (type & CUBEB_DEVICE_TYPE_OUTPUT)
++ device_count++;
++
++ if (type & CUBEB_DEVICE_TYPE_INPUT)
++ device_count++;
++
++ if (device_count == 0)
++ return CUBEB_OK;
++
++ cubeb_device_info* devices = (cubeb_device_info*)calloc(device_count, sizeof(cubeb_device_info));
++ if (!devices)
++ return CUBEB_ERROR;
++
++ uint32_t rate;
++ haiku_get_preferred_sample_rate(context, &rate);
++
++ uint32_t latency;
++ haiku_get_min_latency(context, {}, &latency);
++
++ int current_index = 0;
++
++ if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
++ cubeb_device_info* cur = &devices[current_index++];
++ cur->devid = HAIKU_DEFAULT_OUT_ID;
++ cur->device_id = HAIKU_DEFAULT_OUT;
++ cur->friendly_name = HAIKU_DEFAULT_OUT;
++ cur->group_id = HAIKU_DEFAULT_OUT;
++ cur->vendor_name = strdup("MediaKit");
++ cur->type = CUBEB_DEVICE_TYPE_OUTPUT;
++ cur->state = CUBEB_DEVICE_STATE_ENABLED;
++ cur->preferred = CUBEB_DEVICE_PREF_ALL;
++ cur->format = CUBEB_DEVICE_FMT_F32NE;
++ cur->default_format = CUBEB_DEVICE_FMT_F32NE;
++ cur->max_channels = MAX_CHANNELS;
++ cur->min_rate = rate;
++ cur->max_rate = rate;
++ cur->default_rate = rate;
++ cur->latency_lo = latency;
++ cur->latency_hi = latency * 4;
++ collection->count++;
++ }
++
++ if (type & CUBEB_DEVICE_TYPE_INPUT) {
++ cubeb_device_info* cur = &devices[current_index++];
++ cur->devid = HAIKU_DEFAULT_IN_ID;
++ cur->device_id = HAIKU_DEFAULT_IN;
++ cur->friendly_name = HAIKU_DEFAULT_IN;
++ cur->group_id = HAIKU_DEFAULT_IN;
++ cur->vendor_name = strdup("MediaKit");
++ cur->type = CUBEB_DEVICE_TYPE_INPUT;
++ cur->state = CUBEB_DEVICE_STATE_ENABLED;
++ cur->preferred = CUBEB_DEVICE_PREF_ALL;
++ cur->format = CUBEB_DEVICE_FMT_F32NE;
++ cur->default_format = CUBEB_DEVICE_FMT_F32NE;
++ cur->max_channels = MAX_CHANNELS;
++ cur->min_rate = rate;
++ cur->max_rate = rate;
++ cur->default_rate = rate;
++ cur->latency_lo = latency;
++ cur->latency_hi = latency * 4;
++ collection->count++;
++ }
++
++ collection->device = devices;
++
++ return CUBEB_OK;
++}
++
++static int
++haiku_device_collection_destroy(cubeb* context,
++ cubeb_device_collection* collection)
++{
++ if (!context || !collection)
++ return CUBEB_ERROR_INVALID_PARAMETER;
++
++ if (collection->device) {
++ free(collection->device);
++ collection->device = NULL;
++ collection->count = 0;
++ }
++
++ return CUBEB_OK;
++}
diff --git a/media/libcubeb/src/moz.build b/media/libcubeb/src/moz.build
-index fd6c6842a4..880d8711ae 100644
+index fd6c684..880d871 100644
--- a/media/libcubeb/src/moz.build
+++ b/media/libcubeb/src/moz.build
@@ -30,6 +30,7 @@ if CONFIG['MOZ_SUNAUDIO']:
@@ -542,7 +1778,7 @@ index fd6c6842a4..880d8711ae 100644
# We allow warnings for third-party code that can be updated from upstream.
diff --git a/mfbt/Assertions.h b/mfbt/Assertions.h
-index 0b7395177d..9549421ee3 100644
+index 0b73951..9549421 100644
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -220,7 +220,7 @@ MOZ_NoReturn(int aLine) {
@@ -555,7 +1791,7 @@ index 0b7395177d..9549421ee3 100644
# define MOZ_REALLY_CRASH(line) __builtin_trap()
diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml
-index 4bf5bc6eac..fc24f4e3e3 100644
+index 4bf5bc6..fc24f4e 100644
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -10145,6 +10145,8 @@
@@ -631,7 +1867,7 @@ index 4bf5bc6eac..fc24f4e3e3 100644
value: false
#endif
diff --git a/moz.configure b/moz.configure
-index 804b9a375a..9c3d2592a3 100755
+index 804b9a3..9c3d259 100755
--- a/moz.configure
+++ b/moz.configure
@@ -879,6 +879,8 @@ def strip_flags(flags, profiling, target):
@@ -644,7 +1880,7 @@ index 804b9a375a..9c3d2592a3 100755
set_config("STRIP_FLAGS", strip_flags)
diff --git a/mozglue/baseprofiler/core/ProfilerUtils.cpp b/mozglue/baseprofiler/core/ProfilerUtils.cpp
-index 517efcbb29..d896644822 100644
+index 517efcb..d896644 100644
--- a/mozglue/baseprofiler/core/ProfilerUtils.cpp
+++ b/mozglue/baseprofiler/core/ProfilerUtils.cpp
@@ -129,6 +129,19 @@ BaseProfilerThreadId profiler_current_thread_id() {
@@ -668,7 +1904,7 @@ index 517efcbb29..d896644822 100644
# else
diff --git a/mozglue/baseprofiler/public/BaseProfilerUtils.h b/mozglue/baseprofiler/public/BaseProfilerUtils.h
-index ab02e03b95..6d55f37465 100644
+index ab02e03..6d55f37 100644
--- a/mozglue/baseprofiler/public/BaseProfilerUtils.h
+++ b/mozglue/baseprofiler/public/BaseProfilerUtils.h
@@ -66,6 +66,13 @@ namespace mozilla::baseprofiler::detail {
@@ -686,7 +1922,7 @@ index ab02e03b95..6d55f37465 100644
# else
diff --git a/mozglue/misc/MutexPlatformData_posix.h b/mozglue/misc/MutexPlatformData_posix.h
-index d1659d8d7b..b43e029d2a 100644
+index d1659d8..b43e029 100644
--- a/mozglue/misc/MutexPlatformData_posix.h
+++ b/mozglue/misc/MutexPlatformData_posix.h
@@ -11,8 +11,19 @@
@@ -710,7 +1946,7 @@ index d1659d8d7b..b43e029d2a 100644
+
#endif // MutexPlatformData_posix_h
diff --git a/mozglue/misc/PlatformMutex.h b/mozglue/misc/PlatformMutex.h
-index ac5459cf10..d014d11f93 100644
+index ac5459c..d014d11 100644
--- a/mozglue/misc/PlatformMutex.h
+++ b/mozglue/misc/PlatformMutex.h
@@ -49,10 +49,17 @@ class MutexImpl {
@@ -732,7 +1968,7 @@ index ac5459cf10..d014d11f93 100644
void* platformData_[6];
#endif
diff --git a/mozglue/misc/TimeStamp_posix.cpp b/mozglue/misc/TimeStamp_posix.cpp
-index ba32a230eb..6d9f022dcb 100644
+index ba32a23..6d9f022 100644
--- a/mozglue/misc/TimeStamp_posix.cpp
+++ b/mozglue/misc/TimeStamp_posix.cpp
@@ -13,7 +13,9 @@
@@ -747,7 +1983,7 @@ index ba32a230eb..6d9f022dcb 100644
#include
#include
diff --git a/netwerk/base/nsStandardURL.cpp b/netwerk/base/nsStandardURL.cpp
-index fac8e4ca7f..5e6f4a0f80 100644
+index fac8e4c..5e6f4a0 100644
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -319,7 +319,7 @@ struct DumpLeakedURLs {
@@ -760,7 +1996,7 @@ index fac8e4ca7f..5e6f4a0f80 100644
if (!gAllURLs.isEmpty()) {
printf("Leaked URLs:\n");
diff --git a/netwerk/dns/moz.build b/netwerk/dns/moz.build
-index c926d14707..d6e226359c 100644
+index c926d14..d6e2263 100644
--- a/netwerk/dns/moz.build
+++ b/netwerk/dns/moz.build
@@ -120,3 +120,7 @@ LOCAL_INCLUDES += [
@@ -771,8 +2007,146 @@ index c926d14707..d6e226359c 100644
+OS_LIBS += [
+ "network"
+]
+diff --git a/netwerk/sctp/src/netinet/sctp.h b/netwerk/sctp/src/netinet/sctp.h
+index 6129e77..be8e413 100644
+--- a/netwerk/sctp/src/netinet/sctp.h
++++ b/netwerk/sctp/src/netinet/sctp.h
+@@ -35,7 +35,7 @@
+ #ifndef _NETINET_SCTP_H_
+ #define _NETINET_SCTP_H_
+
+-#if defined(__APPLE__) || defined(__linux__)
++#if defined(__APPLE__) || defined(__linux__) || defined(__HAIKU__)
+ #include
+ #endif
+ #if defined(__FreeBSD__) && !defined(__Userspace__)
+diff --git a/netwerk/sctp/src/netinet/sctp_input.c b/netwerk/sctp/src/netinet/sctp_input.c
+index 361b8b2..02e2969 100644
+--- a/netwerk/sctp/src/netinet/sctp_input.c
++++ b/netwerk/sctp/src/netinet/sctp_input.c
+@@ -6308,11 +6308,11 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
+ #if defined(_WIN32) && !defined(__Userspace__)
+ NTOHS(ip->ip_len);
+ #endif
+-#if defined(__linux__) || (defined(_WIN32) && defined(__Userspace__))
++#if defined(__linux__) || defined(__HAIKU__) || (defined(_WIN32) && defined(__Userspace__))
+ ip->ip_len = ntohs(ip->ip_len);
+ #endif
+ #if defined(__Userspace__)
+-#if defined(__linux__) || defined(_WIN32)
++#if defined(__linux__) || defined(_WIN32) || defined(__HAIKU__)
+ length = ip->ip_len;
+ #else
+ length = ip->ip_len + iphlen;
+diff --git a/netwerk/sctp/src/netinet/sctp_os_userspace.h b/netwerk/sctp/src/netinet/sctp_os_userspace.h
+index 493ae02..cd160c5 100644
+--- a/netwerk/sctp/src/netinet/sctp_os_userspace.h
++++ b/netwerk/sctp/src/netinet/sctp_os_userspace.h
+@@ -1145,7 +1145,7 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int a
+
+ #define SCTP_IS_LISTENING(inp) ((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) != 0)
+
+-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__native_client__) || defined(__NetBSD__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
++#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__native_client__) || defined(__NetBSD__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__HAIKU__) || defined(__EMSCRIPTEN__)
+ int
+ timingsafe_bcmp(const void *, const void *, size_t);
+ #endif
+diff --git a/netwerk/sctp/src/netinet/sctp_userspace.c b/netwerk/sctp/src/netinet/sctp_userspace.c
+index 7188890..fac3e16 100644
+--- a/netwerk/sctp/src/netinet/sctp_userspace.c
++++ b/netwerk/sctp/src/netinet/sctp_userspace.c
+@@ -94,7 +94,7 @@ sctp_userspace_set_threadname(const char *name)
+ #endif
+ }
+
+-#if !defined(_WIN32) && !defined(__native_client__)
++#if !defined(_WIN32) && !defined(__HAIKU__) && !defined(__native_client__)
+ int
+ sctp_userspace_get_mtu_from_ifn(uint32_t if_index)
+ {
+@@ -129,7 +129,7 @@ sctp_userspace_get_mtu_from_ifn(uint32_t if_index)
+ }
+ #endif
+
+-#if defined(__native_client__)
++#if defined(__native_client__) || defined(__HAIKU__)
+ int
+ sctp_userspace_get_mtu_from_ifn(uint32_t if_index)
+ {
+@@ -137,7 +137,7 @@ sctp_userspace_get_mtu_from_ifn(uint32_t if_index)
+ }
+ #endif
+
+-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__native_client__) || defined(__NetBSD__) || defined(__QNX__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
++#if defined(__APPLE__) || defined(__DragonFly__) || defined(__linux__) || defined(__native_client__) || defined(__NetBSD__) || defined(__QNX__) || defined(_WIN32) || defined(__Fuchsia__) || defined(__HAIKU__) || defined(__EMSCRIPTEN__)
+ int
+ timingsafe_bcmp(const void *b1, const void *b2, size_t n)
+ {
+diff --git a/netwerk/sctp/src/user_environment.c b/netwerk/sctp/src/user_environment.c
+index ea52f0a..85b37ee 100644
+--- a/netwerk/sctp/src/user_environment.c
++++ b/netwerk/sctp/src/user_environment.c
+@@ -172,7 +172,7 @@ finish_random(void)
+ {
+ return;
+ }
+-#elif (defined(__ANDROID__) && (__ANDROID_API__ < 28)) || defined(__QNX__) || defined(__EMSCRIPTEN__)
++#elif (defined(__ANDROID__) && (__ANDROID_API__ < 28)) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__HAIKU__)
+ #include
+
+ static int fd = -1;
+diff --git a/netwerk/sctp/src/user_socket.c b/netwerk/sctp/src/user_socket.c
+index cde6ecc..0407d01 100644
+--- a/netwerk/sctp/src/user_socket.c
++++ b/netwerk/sctp/src/user_socket.c
+@@ -50,6 +50,9 @@
+ #if defined(__linux__)
+ #define __FAVOR_BSD /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */
+ #endif
++#if defined(__HAIKU__)
++#define UIO_MAXIOV _SC_IOV_MAX
++#endif
+ #if !defined(_WIN32)
+ #if defined INET || defined INET6
+ #include
+@@ -1020,7 +1023,7 @@ userspace_sctp_recvmsg(struct socket *so,
+ if (error) {
+ if ((auio.uio_resid != ulen) &&
+ (error == EINTR ||
+-#if !defined(__NetBSD__)
++#if !defined(__NetBSD__) && !defined(__HAIKU__)
+ error == ERESTART ||
+ #endif
+ error == EWOULDBLOCK)) {
+@@ -1113,7 +1116,7 @@ usrsctp_recvv(struct socket *so,
+ if (errno) {
+ if ((auio.uio_resid != ulen) &&
+ (errno == EINTR ||
+-#if !defined(__NetBSD__)
++#if !defined(__NetBSD__) && !defined(__HAIKU__)
+ errno == ERESTART ||
+ #endif
+ errno == EWOULDBLOCK)) {
+@@ -1929,7 +1932,7 @@ int user_connect(struct socket *so, struct sockaddr *sa)
+ error = pthread_cond_wait(SOCK_COND(so), SOCK_MTX(so));
+ #endif
+ if (error) {
+-#if defined(__NetBSD__)
++#if defined(__NetBSD__) || defined(__HAIKU__)
+ if (error == EINTR) {
+ #else
+ if (error == EINTR || error == ERESTART) {
+@@ -1949,7 +1952,7 @@ bad:
+ if (!interrupted) {
+ so->so_state &= ~SS_ISCONNECTING;
+ }
+-#if !defined(__NetBSD__)
++#if !defined(__NetBSD__) && !defined(__HAIKU__)
+ if (error == ERESTART) {
+ error = EINTR;
+ }
diff --git a/nsprpub/pr/src/misc/prsystem.c b/nsprpub/pr/src/misc/prsystem.c
-index dba093e9b1..5ff8f2fa37 100644
+index dba093e..5ff8f2f 100644
--- a/nsprpub/pr/src/misc/prsystem.c
+++ b/nsprpub/pr/src/misc/prsystem.c
@@ -280,7 +280,7 @@ PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void)
@@ -785,7 +2159,7 @@ index dba093e9b1..5ff8f2fa37 100644
long pageSize = sysconf(_SC_PAGESIZE);
long pageCount = sysconf(_SC_PHYS_PAGES);
diff --git a/python/mach/mach/site.py b/python/mach/mach/site.py
-index c48d282b2f..1bd404ae60 100644
+index c48d282..1bd404a 100644
--- a/python/mach/mach/site.py
+++ b/python/mach/mach/site.py
@@ -1342,6 +1342,14 @@ def _create_venv_with_pthfile(
@@ -804,7 +2178,7 @@ index c48d282b2f..1bd404ae60 100644
pthfile_contents = "\n".join(pthfile_lines)
with open(os.path.join(platlib_site_packages_dir, PTH_FILENAME), "w") as f:
diff --git a/python/mozboot/mozboot/base.py b/python/mozboot/mozboot/base.py
-index 81f9b52c60..24b2c4f458 100644
+index 81f9b52..24b2c4f 100644
--- a/python/mozboot/mozboot/base.py
+++ b/python/mozboot/mozboot/base.py
@@ -573,6 +573,8 @@ class BaseBootstrapper(object):
@@ -817,7 +2191,7 @@ index 81f9b52c60..24b2c4f458 100644
elif version:
print("Your version of Rust (%s) is too old." % version)
diff --git a/python/mozboot/mozboot/bootstrap.py b/python/mozboot/mozboot/bootstrap.py
-index 58f1cac5be..2ef8f41525 100644
+index 58f1cac..2ef8f41 100644
--- a/python/mozboot/mozboot/bootstrap.py
+++ b/python/mozboot/mozboot/bootstrap.py
@@ -35,6 +35,7 @@ from mozboot.centosfedora import CentOSFedoraBootstrapper
@@ -839,8 +2213,73 @@ index 58f1cac5be..2ef8f41525 100644
elif sys.platform.startswith("win32") or sys.platform.startswith("msys"):
if "MOZILLABUILD" in os.environ:
cls = MozillaBuildBootstrapper
+diff --git a/python/mozboot/mozboot/haiku.py b/python/mozboot/mozboot/haiku.py
+new file mode 100644
+index 0000000..bf8f9fc
+--- /dev/null
++++ b/python/mozboot/mozboot/haiku.py
+@@ -0,0 +1,59 @@
++# This Source Code Form is subject to the terms of the Mozilla Public
++# License, v. 2.0. If a copy of the MPL was not distributed with this file,
++# You can obtain one at http://mozilla.org/MPL/2.0/.
++
++from mozboot.base import BaseBootstrapper
++
++
++class HaikuBootstrapper(BaseBootstrapper):
++ def __init__(self, version, **kwargs):
++ BaseBootstrapper.__init__(self, **kwargs)
++
++ self.packages = [
++ "make",
++ "pkgconfig",
++ "rust_bin",
++ ]
++
++ self.browser_packages = [
++ "dbus_devel",
++ "dbus_glib_devel",
++ "gtk3_devel",
++ "libevent_devel",
++ "libvpx_devel",
++ "nasm",
++ "nodejs20",
++ "nspr_devel",
++ ]
++
++ def pkgman_install(self, *packages):
++ command = ["pkgman", "install"]
++ if self.no_interactive:
++ command.append("-y")
++
++ command.extend(packages)
++ self.run_as_root(command)
++
++ def install_system_packages(self):
++ self.pkgman_install(*self.packages)
++
++ def install_browser_packages(self, mozconfig_builder, artifact_mode=False):
++ self.pkgman_install(*self.browser_packages)
++
++ def install_browser_artifact_mode_packages(self, mozconfig_builder):
++ self.install_browser_packages(mozconfig_builder, artifact_mode=True)
++
++ def ensure_clang_static_analysis_package(self):
++ # TODO: we don't ship clang base static analysis for this platform
++ pass
++
++ def ensure_stylo_packages(self):
++ # Clang / llvm already installed as browser package
++ self.pkgman_install("cbindgen")
++
++ def ensure_nasm_packages(self):
++ # installed via install_browser_packages
++ pass
++
++ def ensure_node_packages(self):
++ self.pkgman_install("npm")
diff --git a/python/mozbuild/mozbuild/configure/constants.py b/python/mozbuild/mozbuild/configure/constants.py
-index 25f43bb9f8..967aee7ca3 100644
+index 25f43bb..967aee7 100644
--- a/python/mozbuild/mozbuild/configure/constants.py
+++ b/python/mozbuild/mozbuild/configure/constants.py
@@ -36,6 +36,7 @@ class OS(EnumString):
@@ -867,8 +2306,49 @@ index 25f43bb9f8..967aee7ca3 100644
"kFreeBSD": "__FreeBSD_kernel__",
"Linux": "__linux__",
"NetBSD": "__NetBSD__",
+diff --git a/python/mozbuild/mozbuild/gn_processor.py b/python/mozbuild/mozbuild/gn_processor.py
+index 3a9b9e7..ce15656 100644
+--- a/python/mozbuild/mozbuild/gn_processor.py
++++ b/python/mozbuild/mozbuild/gn_processor.py
+@@ -184,6 +184,7 @@ def filter_gn_config(path, gn_result, sandbox_vars, input_vars, gn_target):
+ "mips64el": "mips64",
+ }
+ oses = {
++ "haiku": "Haiku",
+ "android": "Android",
+ "linux": "Linux",
+ "mac": "Darwin",
+@@ -742,7 +743,7 @@ def main():
+
+ vars_set = []
+ for is_debug in (True, False):
+- for target_os in ("android", "linux", "mac", "openbsd", "win"):
++ for target_os in ("android", "linux", "mac", "openbsd", "haiku", "win"):
+ target_cpus = ["x64"]
+ if target_os in ("android", "linux", "mac", "win", "openbsd"):
+ target_cpus.append("arm64")
+@@ -759,7 +760,7 @@ def main():
+ "host_cpu": "x64",
+ "is_debug": is_debug,
+ "target_cpu": target_cpu,
+- "target_os": target_os,
++ "target_os": "haiku",
+ }
+ if target_os == "linux":
+ for use_x11 in (True, False):
+@@ -768,6 +769,10 @@ def main():
+ else:
+ if target_os == "openbsd":
+ vars["use_x11"] = True
++ else:
++ if target_os == "haiku":
++ vars["use_x11"] = False
++
+ vars_set.append(vars)
+
+ gn_configs = []
diff --git a/security/certverifier/ExtendedValidation.cpp b/security/certverifier/ExtendedValidation.cpp
-index 29c2f0036f..13ade1946a 100644
+index 29c2f00..13ade19 100644
--- a/security/certverifier/ExtendedValidation.cpp
+++ b/security/certverifier/ExtendedValidation.cpp
@@ -1337,7 +1337,9 @@ nsresult LoadExtendedValidationInfo() {
@@ -882,7 +2362,7 @@ index 29c2f0036f..13ade1946a 100644
unsigned char certFingerprint[SHA256_LENGTH];
srv = PK11_HashBuf(SEC_OID_SHA256, certFingerprint, cert->derCert.data,
diff --git a/security/manager/ssl/builtins/dynamic-library/moz.build b/security/manager/ssl/builtins/dynamic-library/moz.build
-index cf06de75a2..edc675dc67 100644
+index cf06de7..edc675d 100644
--- a/security/manager/ssl/builtins/dynamic-library/moz.build
+++ b/security/manager/ssl/builtins/dynamic-library/moz.build
@@ -20,6 +20,11 @@ else:
@@ -898,7 +2378,7 @@ index cf06de75a2..edc675dc67 100644
OS_LIBS += [
"advapi32",
diff --git a/security/manager/ssl/ipcclientcerts/dynamic-library/moz.build b/security/manager/ssl/ipcclientcerts/dynamic-library/moz.build
-index 3db25ac3bd..3d87cd45eb 100644
+index 3db25ac..3d87cd4 100644
--- a/security/manager/ssl/ipcclientcerts/dynamic-library/moz.build
+++ b/security/manager/ssl/ipcclientcerts/dynamic-library/moz.build
@@ -24,6 +24,11 @@ OS_LIBS += CONFIG["DL_LIBS"]
@@ -914,7 +2394,7 @@ index 3db25ac3bd..3d87cd45eb 100644
OS_LIBS += [
"advapi32",
diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml
-index f56d1510ff..a99886632b 100644
+index f56d151..a998866 100644
--- a/supply-chain/audits.toml
+++ b/supply-chain/audits.toml
@@ -2138,6 +2138,12 @@ criteria = "safe-to-deploy"
@@ -944,7 +2424,7 @@ index f56d1510ff..a99886632b 100644
who = "Mike Hommey "
criteria = "safe-to-deploy"
diff --git a/supply-chain/config.toml b/supply-chain/config.toml
-index 605220776b..db3773b79c 100644
+index 6052207..db3773b 100644
--- a/supply-chain/config.toml
+++ b/supply-chain/config.toml
@@ -68,6 +68,10 @@ notes = "Used for testing."
@@ -970,7 +2450,7 @@ index 605220776b..db3773b79c 100644
audit-as-crates-io = false
notes = "This was originally servo code which Bobby Holley put on crates.io some years ago and that was moved in-tree as first-party code later on."
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
-index 08728e583c..858fa0a34a 100644
+index 08728e5..858fa0a 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -805,7 +805,7 @@ who = "Nick Fitzgerald "
@@ -1009,7 +2489,7 @@ index 08728e583c..858fa0a34a 100644
aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
diff --git a/testing/mozbase/mozinfo/mozinfo/mozinfo.py b/testing/mozbase/mozinfo/mozinfo/mozinfo.py
-index 0114b17f66..6cf73c3d64 100755
+index 0114b17..6cf73c3 100755
--- a/testing/mozbase/mozinfo/mozinfo/mozinfo.py
+++ b/testing/mozbase/mozinfo/mozinfo/mozinfo.py
@@ -106,7 +106,7 @@ elif system == "Linux":
@@ -1022,7 +2502,7 @@ index 0114b17f66..6cf73c3d64 100755
version = os_version = sys.platform
elif system == "Darwin":
diff --git a/third_party/dav1d/src/thread.h b/third_party/dav1d/src/thread.h
-index c44de736c3..deb17c5b1d 100644
+index c44de73..deb17c5 100644
--- a/third_party/dav1d/src/thread.h
+++ b/third_party/dav1d/src/thread.h
@@ -170,14 +170,14 @@ static inline void dav1d_set_thread_name(const char *const name) {
@@ -1048,8 +2528,1252 @@ index c44de736c3..deb17c5b1d 100644
#else
#define dav1d_set_thread_name(name) do {} while (0)
+diff --git a/third_party/libepoxy/libepoxy/src/dispatch_common.c b/third_party/libepoxy/libepoxy/src/dispatch_common.c
+index 153eb7c..f59c4db 100644
+--- a/third_party/libepoxy/libepoxy/src/dispatch_common.c
++++ b/third_party/libepoxy/libepoxy/src/dispatch_common.c
+@@ -306,8 +306,10 @@ get_dlopen_handle(void **handle, const char *lib_name, bool exit_on_fail, bool l
+ pthread_mutex_lock(&api.mutex);
+ if (!*handle) {
+ int flags = RTLD_LAZY | RTLD_LOCAL;
++#ifndef __HAIKU__
+ if (!load)
+ flags |= RTLD_NOLOAD;
++#endif
+
+ *handle = dlopen(lib_name, flags);
+ if (!*handle) {
+diff --git a/third_party/libwebrtc/BUILD.gn b/third_party/libwebrtc/BUILD.gn
+index 85ead41..459712b 100644
+--- a/third_party/libwebrtc/BUILD.gn
++++ b/third_party/libwebrtc/BUILD.gn
+@@ -209,7 +209,7 @@ config("common_inherited_config") {
+ target_gen_dir,
+ ]
+ }
+- if (is_posix || is_fuchsia) {
++ if (is_posix || is_fuchsia || is_haiku) {
+ defines += [ "WEBRTC_POSIX" ]
+ }
+ if (is_ios) {
+@@ -218,7 +218,7 @@ config("common_inherited_config") {
+ "WEBRTC_IOS",
+ ]
+ }
+- if (is_linux || is_chromeos) {
++ if ((is_linux && !is_haiku) || is_chromeos) {
+ defines += [ "WEBRTC_LINUX" ]
+ }
+ if (is_bsd) {
+@@ -230,6 +230,9 @@ config("common_inherited_config") {
+ if (is_fuchsia) {
+ defines += [ "WEBRTC_FUCHSIA" ]
+ }
++ if (is_haiku) {
++ defines += [ "WEBRTC_HAIKU", "_BSD_SOURCE" ]
++ }
+ if (is_win) {
+ defines += [ "WEBRTC_WIN" ]
+ }
+diff --git a/third_party/libwebrtc/modules/desktop_capture/BUILD.gn b/third_party/libwebrtc/modules/desktop_capture/BUILD.gn
+index 34fba62..eb03d26 100644
+--- a/third_party/libwebrtc/modules/desktop_capture/BUILD.gn
++++ b/third_party/libwebrtc/modules/desktop_capture/BUILD.gn
+@@ -351,6 +351,19 @@ rtc_library("desktop_capture") {
+ ]
+ }
+
++ if (is_haiku) {
++ sources += [
++ "haiku/screen_capturer_haiku_impl.cc",
++ "screen_capturer_haiku.cc",
++ "mouse_cursor_monitor_haiku.cc",
++ "window_capturer_haiku.cc",
++ ]
++ libs = [
++ "be",
++ "game",
++ ]
++ }
++
+ if (rtc_use_x11_extensions) {
+ sources += [
+ "linux/x11/mouse_cursor_monitor_x11.cc",
+@@ -390,7 +403,7 @@ rtc_library("desktop_capture") {
+ }
+
+ if (!is_win && !is_mac && !rtc_use_x11_extensions && !rtc_use_pipewire &&
+- !is_fuchsia) {
++ !is_fuchsia && !is_haiku) {
+ sources += [
+ "mouse_cursor_monitor_null.cc",
+ "screen_capturer_null.cc",
+diff --git a/third_party/libwebrtc/modules/desktop_capture/haiku/screen_capturer_haiku_impl.cc b/third_party/libwebrtc/modules/desktop_capture/haiku/screen_capturer_haiku_impl.cc
+new file mode 100644
+index 0000000..f1569ee
+--- /dev/null
++++ b/third_party/libwebrtc/modules/desktop_capture/haiku/screen_capturer_haiku_impl.cc
+@@ -0,0 +1,111 @@
++/*
++ * Copyright 2025 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "modules/desktop_capture/haiku/screen_capturer_haiku_impl.h"
++
++#include
++#include
++
++#include
++#include
++
++#include "modules/desktop_capture/desktop_capture_options.h"
++#include "modules/desktop_capture/desktop_capturer.h"
++#include "modules/desktop_capture/desktop_frame.h"
++#include "modules/desktop_capture/desktop_geometry.h"
++#include "modules/desktop_capture/screen_capture_frame_queue.h"
++#include "modules/desktop_capture/screen_capturer_helper.h"
++#include "modules/desktop_capture/shared_desktop_frame.h"
++#include "rtc_base/checks.h"
++#include "rtc_base/logging.h"
++#include "rtc_base/sanitizer.h"
++#include "rtc_base/time_utils.h"
++#include "rtc_base/trace_event.h"
++
++#define MAX_FPS 5
++
++namespace webrtc {
++
++namespace {
++
++static constexpr DesktopCapturer::SourceId kDirectScreenId = 1;
++static constexpr DesktopCapturer::SourceId kGetBitmapScreenId = 2;
++
++}
++
++ScreenCapturerHaiku::ScreenCapturerHaiku() {
++ screen_ = new BScreen(B_MAIN_SCREEN_ID);
++ bitmap_ = new BBitmap(screen_->Frame(), B_RGB32);
++ memset(bitmap_->Bits(), 0, bitmap_->BitsLength());
++ reader_ = new ScreenReader(screen_);
++ reader_->Show();
++}
++
++ScreenCapturerHaiku::~ScreenCapturerHaiku() {
++ reader_->Lock();
++ reader_->Quit();
++ delete screen_;
++ delete bitmap_;
++}
++
++bool ScreenCapturerHaiku::Init(const DesktopCaptureOptions& options) {
++ options_ = options;
++ return true;
++}
++
++void ScreenCapturerHaiku::Start(Callback* callback) {
++ RTC_DCHECK(!callback_);
++ RTC_DCHECK(callback);
++ callback_ = callback;
++ lastShot_ = system_time();
++}
++
++void ScreenCapturerHaiku::CaptureFrame() {
++ int64_t capture_start_time_nanos = rtc::TimeNanos();
++ bigtime_t now_ = system_time();
++ if (now_ - lastShot_ > 1000000 / MAX_FPS) {
++ reader_->ReadBitmap(bitmap_, id_ == kDirectScreenId);
++ lastShot_ = now_;
++ }
++ DesktopRect r = DesktopRect::MakeXYWH(0, 0, bitmap_->Bounds().Width() + 1, bitmap_->Bounds().Height() + 1);
++ std::unique_ptr frame(new BasicDesktopFrame(r.size()));
++ frame->CopyPixelsFrom((const uint8_t*)bitmap_->Bits(), bitmap_->BytesPerRow(), r);
++ frame->set_capture_time_ms((rtc::TimeNanos() - capture_start_time_nanos) / rtc::kNumNanosecsPerMillisec);
++ callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
++}
++
++bool ScreenCapturerHaiku::GetSourceList(SourceList* sources) {
++ sources->push_back({kDirectScreenId, 0, std::string("Active Desktop (BDirectWindow)")});
++ sources->push_back({kGetBitmapScreenId, 1, std::string("Active Desktop (GetBitmap)")});
++ return true;
++}
++
++bool ScreenCapturerHaiku::SelectSource(SourceId id) {
++ if (id != kDirectScreenId && id != kGetBitmapScreenId)
++ return false;
++
++ id_ = id;
++
++ return true;
++}
++
++
++// static
++std::unique_ptr ScreenCapturerHaiku::CreateRawScreenCapturer(
++ const DesktopCaptureOptions& options) {
++ std::unique_ptr capturer(new ScreenCapturerHaiku());
++ if (!capturer.get()->Init(options)) {
++ return nullptr;
++ }
++
++ return std::move(capturer);
++}
++
++} // namespace webrtc
+diff --git a/third_party/libwebrtc/modules/desktop_capture/haiku/screen_capturer_haiku_impl.h b/third_party/libwebrtc/modules/desktop_capture/haiku/screen_capturer_haiku_impl.h
+new file mode 100644
+index 0000000..1f2dbd6
+--- /dev/null
++++ b/third_party/libwebrtc/modules/desktop_capture/haiku/screen_capturer_haiku_impl.h
+@@ -0,0 +1,96 @@
++/*
++ * Copyright 2025 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
++#define MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
++
++#include
++
++#include "modules/desktop_capture/desktop_capture_options.h"
++#include "modules/desktop_capture/desktop_capturer.h"
++#include "modules/desktop_capture/desktop_frame.h"
++#include "modules/desktop_capture/desktop_region.h"
++#include "modules/desktop_capture/screen_capture_frame_queue.h"
++#include "modules/desktop_capture/screen_capturer_helper.h"
++#include "modules/desktop_capture/shared_desktop_frame.h"
++
++#pragma GCC visibility push(default)
++#include
++#include
++#include
++#include
++#include
++#pragma GCC visibility pop
++
++namespace webrtc {
++
++class ScreenReader: public BDirectWindow {
++public:
++ ScreenReader(BScreen *screen) : BDirectWindow(BRect(-2, -2, -1, -1), "DirectWindow",
++ B_NO_BORDER_WINDOW_LOOK, window_feel(1025),
++ B_AVOID_FRONT | B_AVOID_FOCUS | B_NO_WORKSPACE_ACTIVATION,
++ B_ALL_WORKSPACES), fScreen(screen), fDirectAvailable(false) { };
++ virtual void DirectConnected(direct_buffer_info *info) {
++ switch (info->buffer_state & B_DIRECT_MODE_MASK) {
++ case B_DIRECT_START:
++ case B_DIRECT_MODIFY:
++ fDirectInfo = *info;
++ fDirectAvailable = true;
++ break;
++ case B_DIRECT_STOP:
++ fDirectAvailable = false;
++ break;
++ default:
++ break;
++ }
++ };
++ status_t ReadBitmap(BBitmap *bitmap, bool direct) {
++ if (direct && fDirectAvailable) {
++ memcpy(bitmap->Bits(), fDirectInfo.bits, bitmap->BitsLength());
++ return B_OK;
++ }
++ return fScreen->ReadBitmap(bitmap);
++};
++private:
++ BScreen* fScreen;
++ direct_buffer_info fDirectInfo;
++ bool fDirectAvailable;
++};
++
++class ScreenCapturerHaiku : public DesktopCapturer {
++ public:
++ ScreenCapturerHaiku();
++ ~ScreenCapturerHaiku() override;
++
++ static std::unique_ptr CreateRawScreenCapturer(
++ const DesktopCaptureOptions& options);
++
++ bool Init(const DesktopCaptureOptions& options);
++
++ void Start(Callback* delegate) override;
++ void CaptureFrame() override;
++ bool GetSourceList(SourceList* sources) override;
++ bool SelectSource(SourceId id) override;
++
++ private:
++ BScreen* screen_;
++ BBitmap* bitmap_;
++ ScreenReader *reader_;
++ bigtime_t lastShot_;
++
++ SourceId id_;
++
++ DesktopCaptureOptions options_;
++ Callback* callback_ = nullptr;
++};
++
++}
++
++#endif // MODULES_DESKTOP_CAPTURE_HAIKU_SCREEN_CAPTURER_HAIKU_H_
+diff --git a/third_party/libwebrtc/modules/desktop_capture/mouse_cursor_monitor_haiku.cc b/third_party/libwebrtc/modules/desktop_capture/mouse_cursor_monitor_haiku.cc
+new file mode 100644
+index 0000000..8ea2aa2
+--- /dev/null
++++ b/third_party/libwebrtc/modules/desktop_capture/mouse_cursor_monitor_haiku.cc
+@@ -0,0 +1,39 @@
++/*
++ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include
++
++#include "modules/desktop_capture/desktop_capture_types.h"
++#include "modules/desktop_capture/mouse_cursor_monitor.h"
++//#include "modules/desktop_capture/haiku/mouse_cursor_monitor.h"
++
++namespace webrtc {
++
++// static
++MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
++ const DesktopCaptureOptions& options,
++ WindowId window) {
++ return nullptr;
++}
++
++// static
++MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
++ const DesktopCaptureOptions& options,
++ ScreenId screen) {
++ return nullptr;
++}
++
++// static
++std::unique_ptr MouseCursorMonitor::Create(
++ const DesktopCaptureOptions& options) {
++ return nullptr;
++}
++
++} // namespace webrtc
+diff --git a/third_party/libwebrtc/modules/desktop_capture/screen_capturer_haiku.cc b/third_party/libwebrtc/modules/desktop_capture/screen_capturer_haiku.cc
+new file mode 100644
+index 0000000..e30fb04
+--- /dev/null
++++ b/third_party/libwebrtc/modules/desktop_capture/screen_capturer_haiku.cc
+@@ -0,0 +1,26 @@
++/*
++ * Copyright 2021 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include
++
++#include "modules/desktop_capture/desktop_capture_options.h"
++#include "modules/desktop_capture/desktop_capturer.h"
++
++#include "modules/desktop_capture/haiku/screen_capturer_haiku_impl.h"
++
++namespace webrtc {
++
++// static
++std::unique_ptr DesktopCapturer::CreateRawScreenCapturer(
++ const DesktopCaptureOptions& options) {
++ return ScreenCapturerHaiku::CreateRawScreenCapturer(options);
++}
++
++} // namespace webrtc
+diff --git a/third_party/libwebrtc/modules/desktop_capture/window_capturer_haiku.cc b/third_party/libwebrtc/modules/desktop_capture/window_capturer_haiku.cc
+new file mode 100644
+index 0000000..a89b4a1
+--- /dev/null
++++ b/third_party/libwebrtc/modules/desktop_capture/window_capturer_haiku.cc
+@@ -0,0 +1,64 @@
++/*
++ * Copyright 2021 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "modules/desktop_capture/desktop_capturer.h"
++#include "modules/desktop_capture/desktop_frame.h"
++
++#include
++
++namespace webrtc {
++
++namespace {
++
++class WindowCapturerHaiku : public DesktopCapturer {
++ public:
++ WindowCapturerHaiku();
++ ~WindowCapturerHaiku() override;
++
++ void Start(Callback* callback) override;
++ void CaptureFrame() override;
++ bool GetSourceList(SourceList* sources) override;
++ bool SelectSource(SourceId id) override;
++
++ private:
++ Callback* callback_ = nullptr;
++};
++
++WindowCapturerHaiku::WindowCapturerHaiku() {}
++WindowCapturerHaiku::~WindowCapturerHaiku() {}
++
++bool WindowCapturerHaiku::GetSourceList(SourceList* sources) {
++ return false;
++}
++
++bool WindowCapturerHaiku::SelectSource(SourceId id) {
++ return false;
++}
++
++void WindowCapturerHaiku::Start(Callback* callback) {
++ assert(!callback_);
++ assert(callback);
++
++ callback_ = callback;
++}
++
++void WindowCapturerHaiku::CaptureFrame() {
++ callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
++}
++
++} // namespace
++
++// static
++std::unique_ptr DesktopCapturer::CreateRawWindowCapturer(
++ const DesktopCaptureOptions& options) {
++ return std::unique_ptr(new WindowCapturerHaiku());
++}
++
++} // namespace webrtc
+diff --git a/third_party/libwebrtc/modules/video_capture/BUILD.gn b/third_party/libwebrtc/modules/video_capture/BUILD.gn
+index d500a92..43ac3d6 100644
+--- a/third_party/libwebrtc/modules/video_capture/BUILD.gn
++++ b/third_party/libwebrtc/modules/video_capture/BUILD.gn
+@@ -133,6 +133,20 @@ if (!build_with_chromium || is_linux || is_chromeos) {
+ if (is_fuchsia) {
+ sources += [ "video_capture_factory_null.cc" ]
+ }
++ if (is_haiku) {
++ sources += [
++ "haiku/video_capture_haiku.cc",
++ "haiku/video_capture_haiku.h",
++ "haiku/device_info_haiku.cc",
++ "haiku/device_info_haiku.h",
++ ]
++
++ libs = [
++ "be",
++ "media",
++ "mediahelpers",
++ ]
++ }
+
+ if (!build_with_mozilla && is_android) {
+ include_dirs = [
+diff --git a/third_party/libwebrtc/modules/video_capture/haiku/device_info_haiku.cc b/third_party/libwebrtc/modules/video_capture/haiku/device_info_haiku.cc
+new file mode 100644
+index 0000000..a9f55e1
+--- /dev/null
++++ b/third_party/libwebrtc/modules/video_capture/haiku/device_info_haiku.cc
+@@ -0,0 +1,157 @@
++/*
++ * Copyright 2021-2025 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "modules/video_capture/haiku/device_info_haiku.h"
++
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++
++#include
++
++#include "modules/video_capture/video_capture.h"
++#include "modules/video_capture/video_capture_defines.h"
++#include "modules/video_capture/video_capture_impl.h"
++#include "rtc_base/logging.h"
++
++#define MAX_DORMANT_NODES 32
++
++namespace webrtc {
++namespace videocapturemodule {
++VideoCaptureModule::DeviceInfo* VideoCaptureImpl::CreateDeviceInfo() {
++ return new videocapturemodule::DeviceInfoHaiku();
++}
++
++DeviceInfoHaiku::DeviceInfoHaiku() : DeviceInfoImpl() {}
++
++int32_t DeviceInfoHaiku::Init() {
++ return 0;
++}
++
++DeviceInfoHaiku::~DeviceInfoHaiku() {}
++
++uint32_t DeviceInfoHaiku::NumberOfDevices() {
++ status_t err = B_OK;
++
++ int32_t countDevices = 0;
++
++ dormant_node_info dni[MAX_DORMANT_NODES];
++ int32 ioCount = MAX_DORMANT_NODES;
++ media_format out;
++ out.type = B_MEDIA_RAW_VIDEO;
++ err = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
++ if (err < B_OK)
++ return countDevices;
++
++ for (int ix = 0; ix < ioCount; ix++) {
++ media_node_id running = -1;
++ if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
++ dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
++ media_node node;
++ BMediaRoster::CurrentRoster()->GetNodeFor(running, &node);
++ int32 count = 1;
++ media_output videoOutput;
++ BMediaRoster::CurrentRoster()->GetAllOutputsFor(node, &videoOutput, 1, &count);
++ if (count > 0)
++ countDevices++;
++ BMediaRoster::CurrentRoster()->ReleaseNode(node);
++ }
++ }
++
++ return countDevices;
++}
++
++int32_t DeviceInfoHaiku::GetDeviceName(uint32_t deviceNumber,
++ char* deviceNameUTF8,
++ uint32_t deviceNameLength,
++ char* deviceUniqueIdUTF8,
++ uint32_t deviceUniqueIdUTF8Length,
++ char* productUniqueIdUTF8,
++ uint32_t productUniqueIdUTF8Length,
++ pid_t* pid,
++ bool* deviceIsPlaceholder) {
++ if (deviceNumber >= NumberOfDevices())
++ return -1;
++
++ status_t err = B_OK;
++
++ int32_t countDevices = 0;
++
++ media_output videoOutput;
++
++ dormant_node_info dni[MAX_DORMANT_NODES];
++ int32 ioCount = MAX_DORMANT_NODES;
++ media_format out;
++ out.type = B_MEDIA_RAW_VIDEO;
++ err = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
++ if (err < B_OK)
++ return countDevices;
++
++ err = B_ERROR;
++
++ for (int ix = 0; ix < ioCount; ix++) {
++ media_node_id running = -1;
++ if ((B_OK == BMediaRoster::CurrentRoster()->GetInstancesFor(
++ dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
++ media_node node;
++ BMediaRoster::CurrentRoster()->GetNodeFor(running, &node);
++ int32 count = 1;
++ BMediaRoster::CurrentRoster()->GetAllOutputsFor(node, &videoOutput, 1, &count);
++ BMediaRoster::CurrentRoster()->ReleaseNode(node);
++ if (count > 0) {
++ if (countDevices == deviceNumber) {
++ if (deviceNameLength > strlen(videoOutput.name)) {
++ strncpy(deviceNameUTF8, videoOutput.name, deviceNameLength);
++ strncpy(deviceUniqueIdUTF8, videoOutput.name, deviceUniqueIdUTF8Length);
++ err = B_OK;
++ } else
++ err = B_ERROR;
++ break;
++ }
++ countDevices++;
++ }
++ BMediaRoster::CurrentRoster()->ReleaseNode(node);
++ }
++ }
++ return err == B_OK ? 0 : -1;
++}
++
++int32_t DeviceInfoHaiku::CreateCapabilityMap(const char* deviceUniqueIdUTF8) {
++ _captureCapabilities.clear();
++
++ unsigned int size[][2] = {{352, 288}, {640, 480}, {1280, 720}, {1920, 1080}, {0, 0}};
++
++ for (int i = 0; size[i][0] != 0; i++) {
++ VideoCaptureCapability cap;
++ cap.width = size[i][0];
++ cap.height = size[i][1];
++ cap.maxFPS = 30;
++ cap.videoType = VideoType::kARGB;
++ _captureCapabilities.push_back(cap);
++ }
++
++ return _captureCapabilities.size();
++}
++
++int32_t DeviceInfoHaiku::DisplayCaptureSettingsDialogBox(
++ const char* deviceUniqueIdUTF8,
++ const char* dialogTitleUTF8,
++ void* parentWindow,
++ uint32_t positionX,
++ uint32_t positionY) {
++ return -1;
++}
++
++} // namespace videocapturemodule
++} // namespace webrtc
+diff --git a/third_party/libwebrtc/modules/video_capture/haiku/device_info_haiku.h b/third_party/libwebrtc/modules/video_capture/haiku/device_info_haiku.h
+new file mode 100644
+index 0000000..cdf5adb
+--- /dev/null
++++ b/third_party/libwebrtc/modules/video_capture/haiku/device_info_haiku.h
+@@ -0,0 +1,63 @@
++/*
++ * Copyright 2021-2025 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
++#define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
++
++#include
++
++#pragma GCC visibility push(default)
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#pragma GCC visibility pop
++
++#include "modules/video_capture/device_info_impl.h"
++#include "rtc_base/logging.h"
++
++namespace webrtc {
++namespace videocapturemodule {
++
++class DeviceInfoHaiku : public DeviceInfoImpl {
++ public:
++ DeviceInfoHaiku();
++ ~DeviceInfoHaiku() override;
++ uint32_t NumberOfDevices() override;
++ int32_t GetDeviceName(uint32_t deviceNumber,
++ char* deviceNameUTF8,
++ uint32_t deviceNameLength,
++ char* deviceUniqueIdUTF8,
++ uint32_t deviceUniqueIdUTF8Length,
++ char* productUniqueIdUTF8 = 0,
++ uint32_t productUniqueIdUTF8Length = 0,
++ pid_t* pid = 0,
++ bool* deviceIsPlaceholder = 0) override;
++ int32_t CreateCapabilityMap(const char* deviceUniqueIdUTF8) override;
++ int32_t DisplayCaptureSettingsDialogBox(const char*,
++ const char*,
++ void*,
++ uint32_t,
++ uint32_t) override;
++ int32_t Init() override;
++};
++} // namespace videocapturemodule
++} // namespace webrtc
++#endif // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_DEVICE_INFO_HAIKU_H_
+diff --git a/third_party/libwebrtc/modules/video_capture/haiku/video_capture_haiku.cc b/third_party/libwebrtc/modules/video_capture/haiku/video_capture_haiku.cc
+new file mode 100644
+index 0000000..29b319d
+--- /dev/null
++++ b/third_party/libwebrtc/modules/video_capture/haiku/video_capture_haiku.cc
+@@ -0,0 +1,213 @@
++/*
++ * Copyright 2021-2025 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "modules/video_capture/haiku/video_capture_haiku.h"
++
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++
++#include
++#include
++
++#include "api/scoped_refptr.h"
++#include "media/base/video_common.h"
++#include "modules/video_capture/video_capture.h"
++#include "rtc_base/logging.h"
++#include "rtc_base/ref_counted_object.h"
++
++namespace webrtc {
++namespace videocapturemodule {
++rtc::scoped_refptr VideoCaptureImpl::Create(
++ const char* deviceUniqueId) {
++ rtc::scoped_refptr implementation(
++ new rtc::RefCountedObject());
++
++ if (implementation->Init(deviceUniqueId) != 0)
++ return nullptr;
++
++ return implementation;
++}
++
++VideoCaptureModuleHaiku::VideoCaptureModuleHaiku()
++ : VideoCaptureImpl(),
++ _currentWidth(-1),
++ _currentHeight(-1),
++ _currentFrameRate(-1),
++ _captureStarted(false),
++ _captureVideoType(VideoType::kARGB) {}
++
++int32_t VideoCaptureModuleHaiku::Init(const char* deviceUniqueIdUTF8) {
++ int len = strlen((const char*)deviceUniqueIdUTF8);
++ _deviceUniqueId = new (std::nothrow) char[len + 1];
++ if (_deviceUniqueId) {
++ memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1);
++ }
++
++ return 0;
++}
++
++VideoCaptureModuleHaiku::~VideoCaptureModuleHaiku() {
++ StopCapture();
++}
++
++
++void MyFrameCallback(BBitmap* frame, void* userData) {
++ webrtc::videocapturemodule::VideoCaptureImpl *fVideoCapture = (webrtc::videocapturemodule::VideoCaptureImpl*)userData;
++
++ webrtc::VideoCaptureCapability frameInfo;
++ frameInfo.width = frame->Bounds().Width() + 1;
++ frameInfo.height = frame->Bounds().Height() + 1;
++ frameInfo.videoType = webrtc::VideoType::kARGB;
++
++ fVideoCapture->IncomingFrame((unsigned char*)frame->Bits(), frame->BitsLength(), frameInfo);
++}
++
++int32_t VideoCaptureModuleHaiku::StartCapture(
++ const VideoCaptureCapability& capability) {
++ if (_captureStarted) {
++ if (capability.width == _currentWidth &&
++ capability.height == _currentHeight &&
++ _captureVideoType == capability.videoType) {
++ return 0;
++ } else {
++ StopCapture();
++ }
++ }
++
++ _currentWidth = capability.width;
++ _currentHeight = capability.height;
++ _currentFrameRate = 30;
++
++ status_t fStatus;
++ fMediaRoster = BMediaRoster::Roster(&fStatus);
++ if (fStatus != B_OK)
++ return -1;
++
++ media_node fTimeSource;
++ fStatus = fMediaRoster->GetTimeSource(&fTimeSource);
++ if (fStatus != B_OK)
++ return -1;
++
++ fVideoConsumer = new VideoConsumer("Floorp Browser", NULL, 0);
++ fVideoConsumer->SetFrameCallback(MyFrameCallback, (void*)this);
++
++ dormant_node_info dni[30];
++ int32 ioCount = 30;
++ media_format out;
++ out.type = B_MEDIA_RAW_VIDEO;
++ fStatus = BMediaRoster::Roster()->GetDormantNodes(dni, &ioCount, 0, &out, 0, B_BUFFER_PRODUCER);
++ if (fStatus < B_OK)
++ return -1;
++
++ fStatus = B_ERROR;
++ for (int ix=0; ixGetInstancesFor(
++ dni[ix].addon, dni[ix].flavor_id, &running)) && (running > -1)) {
++ BMediaRoster::CurrentRoster()->GetNodeFor(running, &fProducerNode);
++ int32 count = 1;
++ BMediaRoster::CurrentRoster()->GetFreeOutputsFor(
++ fProducerNode, &videoOutput, 1, &count, B_MEDIA_RAW_VIDEO);
++ if (count > 0) {
++ if (strcmp(videoOutput.name, _deviceUniqueId) == 0) {
++ fStatus = B_OK;
++ break;
++ }
++ }
++ BMediaRoster::CurrentRoster()->ReleaseNode(fProducerNode);
++ }
++ }
++ if (fStatus != B_OK)
++ return -1;
++
++ fStatus = fMediaRoster->RegisterNode(fVideoConsumer);
++ if (fStatus != B_OK)
++ return -1;
++ fConsumerNode = fVideoConsumer->Node();
++
++ int32 count = 1;
++ fStatus = fMediaRoster->GetFreeInputsFor(fConsumerNode, &videoInput, 1, &count, B_MEDIA_RAW_VIDEO);
++ if (fStatus != B_OK || count < 1)
++ return -1;
++
++ // connect the nodes
++ media_format format;
++ format.type = B_MEDIA_RAW_VIDEO;
++ media_raw_video_format videoFormat = {
++ 30.0f, 1, 0,
++ (uint32)(_currentWidth - 1),
++ B_VIDEO_TOP_LEFT_RIGHT, 1, 1,
++ {
++ B_RGB32,
++ (uint32)(_currentWidth),
++ (uint32)(_currentHeight),
++ 0, 0, 0
++ }
++ };
++ format.u.raw_video = videoFormat;
++
++ fStatus = fMediaRoster->Connect(videoOutput.source, videoInput.destination,
++ &format, &videoOutput, &videoInput);
++
++ if (fStatus != B_OK)
++ return -1;
++
++ timeSource = fMediaRoster->MakeTimeSourceFor(fTimeSource);
++ bigtime_t real = BTimeSource::RealTime();
++ bigtime_t perf = timeSource->PerformanceTimeFor(real) + 3000000;
++
++ fStatus = fMediaRoster->StartNode(fConsumerNode, perf);
++ if (fStatus != B_OK)
++ return -1;
++
++ fStatus = fMediaRoster->StopNode(fProducerNode, perf, true);
++ fStatus = fMediaRoster->StartNode(fProducerNode, perf);
++ if (fStatus != B_OK)
++ return -1;
++
++ _captureStarted = true;
++ return 0;
++}
++
++int32_t VideoCaptureModuleHaiku::StopCapture() {
++ if (_captureStarted) {
++ fMediaRoster->StopNode(fProducerNode, BTimeSource::RealTime(), true);
++ fMediaRoster->Disconnect(fProducerNode.node, videoOutput.source,
++ fConsumerNode.node, videoInput.destination);
++ fMediaRoster->UnregisterNode(fVideoConsumer);
++ delete fVideoConsumer;
++ _captureStarted = false;
++ }
++
++ return 0;
++}
++
++bool VideoCaptureModuleHaiku::CaptureStarted() {
++ return _captureStarted;
++}
++
++int32_t VideoCaptureModuleHaiku::CaptureSettings(
++ VideoCaptureCapability& settings) {
++ settings.width = _currentWidth;
++ settings.height = _currentHeight;
++ settings.maxFPS = _currentFrameRate;
++ settings.videoType = _captureVideoType;
++
++ return 0;
++}
++} // namespace videocapturemodule
++} // namespace webrtc
+diff --git a/third_party/libwebrtc/modules/video_capture/haiku/video_capture_haiku.h b/third_party/libwebrtc/modules/video_capture/haiku/video_capture_haiku.h
+new file mode 100644
+index 0000000..fe33782
+--- /dev/null
++++ b/third_party/libwebrtc/modules/video_capture/haiku/video_capture_haiku.h
+@@ -0,0 +1,73 @@
++/*
++ * Copyright 2021-2025 Gerasim Troeglazov
++ *
++ * Use of this source code is governed by a BSD-style license
++ * that can be found in the LICENSE file in the root of the source
++ * tree. An additional intellectual property rights grant can be found
++ * in the file PATENTS. All contributing project authors may
++ * be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
++#define MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
++
++#include
++#include
++
++#include
++
++#pragma GCC visibility push(default)
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++
++#include
++
++#pragma GCC visibility pop
++
++#include "modules/video_capture/video_capture_defines.h"
++#include "modules/video_capture/video_capture_impl.h"
++#include "rtc_base/platform_thread.h"
++#include "rtc_base/synchronization/mutex.h"
++
++namespace webrtc {
++namespace videocapturemodule {
++class VideoCaptureModuleHaiku : public VideoCaptureImpl {
++ public:
++ VideoCaptureModuleHaiku();
++ ~VideoCaptureModuleHaiku() override;
++ int32_t Init(const char* deviceUniqueId);
++ int32_t StartCapture(const VideoCaptureCapability& capability) override;
++ int32_t StopCapture() override;
++ bool CaptureStarted() override;
++ int32_t CaptureSettings(VideoCaptureCapability& settings) override;
++
++ private:
++ BMediaRoster *fMediaRoster;
++ VideoConsumer *fVideoConsumer;
++ BTimeSource* timeSource;
++ media_node fProducerNode;
++ media_node fConsumerNode;
++ media_input videoInput;
++ media_output videoOutput;
++
++ int32_t _currentWidth;
++ int32_t _currentHeight;
++ int32_t _currentFrameRate;
++ bool _captureStarted;
++ VideoType _captureVideoType;
++};
++} // namespace videocapturemodule
++} // namespace webrtc
++
++#endif // MODULES_VIDEO_CAPTURE_MAIN_SOURCE_HAIKU_VIDEO_CAPTURE_HAIKU_H_
+diff --git a/third_party/libwebrtc/modules/video_capture/video_capture_factory.cc b/third_party/libwebrtc/modules/video_capture/video_capture_factory.cc
+index 2790fbb..16f4d58 100644
+--- a/third_party/libwebrtc/modules/video_capture/video_capture_factory.cc
++++ b/third_party/libwebrtc/modules/video_capture/video_capture_factory.cc
+@@ -24,7 +24,7 @@ rtc::scoped_refptr VideoCaptureFactory::Create(
+ const char* deviceUniqueIdUTF8) {
+ // This is only implemented on pure Linux and WEBRTC_LINUX is defined for
+ // Android as well
+-#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD)) || defined(WEBRTC_ANDROID)
++#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD) && !defined(WEBRTC_HAIKU)) || defined(WEBRTC_ANDROID)
+ return nullptr;
+ #else
+ return videocapturemodule::VideoCaptureImpl::Create(options,
+@@ -40,7 +40,7 @@ VideoCaptureModule::DeviceInfo* VideoCaptureFactory::CreateDeviceInfo(
+ VideoCaptureOptions* options) {
+ // This is only implemented on pure Linux and WEBRTC_LINUX is defined for
+ // Android as well
+-#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD)) || defined(WEBRTC_ANDROID)
++#if (!defined(WEBRTC_LINUX) && !defined(WEBRTC_BSD) && !defined(WEBRTC_HAIKU)) || defined(WEBRTC_ANDROID)
+ return nullptr;
+ #else
+ return videocapturemodule::VideoCaptureImpl::CreateDeviceInfo(options);
+diff --git a/third_party/libwebrtc/rtc_base/BUILD.gn b/third_party/libwebrtc/rtc_base/BUILD.gn
+index 91ecb13..32523db 100644
+--- a/third_party/libwebrtc/rtc_base/BUILD.gn
++++ b/third_party/libwebrtc/rtc_base/BUILD.gn
+@@ -1192,6 +1192,10 @@ rtc_library("ifaddrs_converter") {
+ "ifaddrs_converter.h",
+ ]
+ }
++
++ if (is_haiku) {
++ defines = [ "_BSD_SOURCE" ]
++ }
+ }
+
+ rtc_library("rolling_accumulator") {
+diff --git a/third_party/libwebrtc/rtc_base/logging.cc b/third_party/libwebrtc/rtc_base/logging.cc
+index 9c2d3b0..f8689cc 100644
+--- a/third_party/libwebrtc/rtc_base/logging.cc
++++ b/third_party/libwebrtc/rtc_base/logging.cc
+@@ -116,7 +116,11 @@ std::string LogLineRef::DefaultLogLine() const {
+ log_output << timestamp;
+ }
+ if (thread_id_.has_value()) {
++#ifdef WEBRTC_HAIKU
++ log_output << "[" << (uint64_t)(*thread_id_) << "] ";
++#else
+ log_output << "[" << *thread_id_ << "] ";
++#endif
+ }
+ if (!filename_.empty()) {
+ #if defined(WEBRTC_ANDROID)
+diff --git a/third_party/libwebrtc/rtc_base/physical_socket_server.cc b/third_party/libwebrtc/rtc_base/physical_socket_server.cc
+index 8c2a961..0db37d3 100644
+--- a/third_party/libwebrtc/rtc_base/physical_socket_server.cc
++++ b/third_party/libwebrtc/rtc_base/physical_socket_server.cc
+@@ -74,7 +74,7 @@ typedef void* SockOptArg;
+
+ #endif // WEBRTC_POSIX
+
+-#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(WEBRTC_BSD) && !defined(__native_client__)
++#if defined(WEBRTC_POSIX) && !defined(WEBRTC_MAC) && !defined(WEBRTC_BSD) && !defined(__native_client__) && !defined(__HAIKU__)
+ #if defined(WEBRTC_LINUX)
+ #include
+ #endif
+@@ -380,7 +380,7 @@ int PhysicalSocket::SetOption(Option opt, int value) {
+ ecn_ = value;
+ value = dscp_ + (ecn_ & kEcnMask);
+ }
+-#if defined(WEBRTC_POSIX)
++#if defined(WEBRTC_POSIX) && !defined(__HAIKU__)
+ if (sopt == IPV6_TCLASS) {
+ // Set the IPv4 option in all cases to support dual-stack sockets.
+ // Don't bother checking the return code, as this is expected to fail if
+@@ -524,7 +524,7 @@ int PhysicalSocket::DoReadFromSocket(void* buffer,
+ socklen_t addr_len = sizeof(addr_storage);
+ sockaddr* addr = reinterpret_cast(&addr_storage);
+
+-#if defined(WEBRTC_POSIX)
++#if defined(WEBRTC_POSIX) && !defined(WEBRTC_HAIKU)
+ int received = 0;
+ if (read_scm_timestamp_experiment_) {
+ iovec iov = {.iov_base = buffer, .iov_len = length};
+@@ -724,7 +724,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
+ #elif defined(WEBRTC_MAC) || defined(WEBRTC_BSD) || defined(__native_client__)
+ RTC_LOG(LS_WARNING) << "Socket::OPT_DONTFRAGMENT not supported.";
+ return -1;
+-#elif defined(WEBRTC_POSIX)
++#elif defined(WEBRTC_POSIX) && !defined(__HAIKU__)
+ *slevel = IPPROTO_IP;
+ *sopt = IP_MTU_DISCOVER;
+ break;
+@@ -742,7 +742,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
+ *sopt = TCP_NODELAY;
+ break;
+ case OPT_DSCP:
+-#if defined(WEBRTC_POSIX)
++#if defined(WEBRTC_POSIX) && !defined(__HAIKU__)
+ if (family_ == AF_INET6) {
+ *slevel = IPPROTO_IPV6;
+ *sopt = IPV6_TCLASS;
+@@ -756,7 +756,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
+ return -1;
+ #endif
+ case OPT_SEND_ECN:
+-#if defined(WEBRTC_POSIX)
++#if defined(WEBRTC_POSIX) && !defined(__HAIKU__)
+ if (family_ == AF_INET6) {
+ *slevel = IPPROTO_IPV6;
+ *sopt = IPV6_TCLASS;
+@@ -770,7 +770,7 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
+ return -1;
+ #endif
+ case OPT_RECV_ECN:
+-#if defined(WEBRTC_POSIX)
++#if defined(WEBRTC_POSIX) && !defined(__HAIKU__)
+ if (family_ == AF_INET6) {
+ *slevel = IPPROTO_IPV6;
+ *sopt = IPV6_RECVTCLASS;
+@@ -789,22 +789,30 @@ int PhysicalSocket::TranslateOption(Option opt, int* slevel, int* sopt) {
+ *slevel = SOL_SOCKET;
+ *sopt = SO_KEEPALIVE;
+ break;
++#if !defined(WEBRTC_HAIKU)
+ case OPT_TCP_KEEPCNT:
+ *slevel = IPPROTO_TCP;
+ *sopt = TCP_KEEPCNT;
+ break;
++#endif
+ case OPT_TCP_KEEPIDLE:
+ *slevel = IPPROTO_TCP;
++#if defined(WEBRTC_HAIKU)
++ *sopt = SO_KEEPALIVE;
++#else
+ #if !defined(WEBRTC_MAC)
+ *sopt = TCP_KEEPIDLE;
+ #else
+ *sopt = TCP_KEEPALIVE;
++#endif
+ #endif
+ break;
++#if !defined(WEBRTC_HAIKU)
+ case OPT_TCP_KEEPINTVL:
+ *slevel = IPPROTO_TCP;
+ *sopt = TCP_KEEPINTVL;
+ break;
++#endif
+ case OPT_TCP_USER_TIMEOUT:
+ #if defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
+ *slevel = IPPROTO_TCP;
+@@ -853,7 +861,7 @@ bool SocketDispatcher::Initialize() {
+ #if defined(WEBRTC_WIN)
+ u_long argp = 1;
+ ioctlsocket(s_, FIONBIO, &argp);
+-#elif defined(WEBRTC_POSIX)
++#elif defined(WEBRTC_POSIX) && !defined(WEBRTC_HAIKU)
+ fcntl(s_, F_SETFL, fcntl(s_, F_GETFL, 0) | O_NONBLOCK);
+ if (!IsScmTimeStampExperimentDisabled()) {
+ int value = 1;
+diff --git a/third_party/libwebrtc/rtc_base/platform_thread_types.cc b/third_party/libwebrtc/rtc_base/platform_thread_types.cc
+index c3c6955..5449ead 100644
+--- a/third_party/libwebrtc/rtc_base/platform_thread_types.cc
++++ b/third_party/libwebrtc/rtc_base/platform_thread_types.cc
+@@ -15,6 +15,10 @@
+ #include
+ #endif
+
++#if defined(WEBRTC_HAIKU)
++#include
++#endif
++
+ #if defined(WEBRTC_WIN)
+ #include "rtc_base/arraysize.h"
+
+@@ -44,6 +48,8 @@ PlatformThreadId CurrentThreadId() {
+ return gettid();
+ #elif defined(WEBRTC_FUCHSIA)
+ return zx_thread_self();
++#elif defined(WEBRTC_HAIKU)
++ return find_thread(NULL);
+ #elif defined(WEBRTC_LINUX)
+ return syscall(__NR_gettid);
+ #elif defined(__EMSCRIPTEN__)
+@@ -118,6 +124,8 @@ void SetCurrentThreadName(const char* name) {
+ prctl(PR_SET_NAME, reinterpret_cast(name)); // NOLINT
+ #elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
+ pthread_setname_np(name);
++#elif defined(WEBRTC_HAIKU)
++ rename_thread(find_thread(NULL), name);
+ #elif defined(WEBRTC_FUCHSIA)
+ zx_status_t status = zx_object_set_property(zx_thread_self(), ZX_PROP_NAME,
+ name, strlen(name));
+diff --git a/third_party/libwebrtc/system_wrappers/BUILD.gn b/third_party/libwebrtc/system_wrappers/BUILD.gn
+index 2576d4e..5ff4cc1 100644
+--- a/third_party/libwebrtc/system_wrappers/BUILD.gn
++++ b/third_party/libwebrtc/system_wrappers/BUILD.gn
+@@ -65,7 +65,9 @@ rtc_library("system_wrappers") {
+ sources += [ "source/cpu_features_linux.cc" ]
+ }
+
+- libs += [ "rt" ]
++ if (!is_haiku) {
++ libs += [ "rt" ]
++ }
+ }
+
+ if (is_win) {
+diff --git a/third_party/libwebrtc/webrtc.gni b/third_party/libwebrtc/webrtc.gni
+index e127347..acf1396 100644
+--- a/third_party/libwebrtc/webrtc.gni
++++ b/third_party/libwebrtc/webrtc.gni
+@@ -151,7 +151,7 @@ declare_args() {
+ rtc_build_tools = false
+
+ # Set this to false to skip building code that requires X11.
+- rtc_use_x11 = use_x11
++ rtc_use_x11 = use_x11 && !is_haiku
+
+ # Set this to use PipeWire on the Wayland display server.
+ # By default it's only enabled on desktop Linux (excludes ChromeOS) and
+@@ -360,7 +360,7 @@ rtc_opus_dir = "//third_party/opus"
+
+ # Desktop capturer is supported only on Windows, OSX and Linux.
+ rtc_desktop_capture_supported =
+- (is_win && current_os != "winuwp") || is_mac || is_bsd ||
++ (is_win && current_os != "winuwp") || is_mac || is_bsd || is_haiku ||
+ ((is_linux || is_chromeos) && (rtc_use_x11_extensions || rtc_use_pipewire))
+
+ ###############################################################################
+diff --git a/third_party/pipewire/pipewire/utils.h b/third_party/pipewire/pipewire/utils.h
+index b320db2..7e60d6f 100644
+--- a/third_party/pipewire/pipewire/utils.h
++++ b/third_party/pipewire/pipewire/utils.h
+@@ -32,7 +32,7 @@ extern "C" {
+ #include
+ #include
+ #include
+-#ifndef _POSIX_C_SOURCE
++#if !defined(_POSIX_C_SOURCE) && !defined(__HAIKU__)
+ # include
+ #endif
+
diff --git a/third_party/rust/glslopt/.cargo-checksum.json b/third_party/rust/glslopt/.cargo-checksum.json
-index a09c03e66a..7004c708aa 100644
+index a09c03e..7004c70 100644
--- a/third_party/rust/glslopt/.cargo-checksum.json
+++ b/third_party/rust/glslopt/.cargo-checksum.json
@@ -1 +1 @@
@@ -1057,8 +3781,17 @@ index a09c03e66a..7004c708aa 100644
\ No newline at end of file
+{"files":{".gitmodules":"9fe653d32afe458d385779b50c197445c2c19e938336c2f0fccfef2d58217e69","Cargo.toml":"c1379265bcb595d9c4983d75deb582f0aa0e3715dfa4d89a819681107633e436","README.md":"4468e08c64c19977707d792bfab0080e35ff927b64990eab77873f8ba056ba1c","build.rs":"6a64610018701781af182c418a4355c9ac5d99d000be9457f0e38a7dadf7542a","glsl-optimizer/.editorconfig":"dca7ff05a95f608849c4dc640af7f83a0f415618e327a2ecb6a0afa0d9d2bacb","glsl-optimizer/.gitignore":"8ba554a4ca510ea7d9684475aa043edbeba7d15a5c9c4a04d8b1379a04ec6270","glsl-optimizer/CMakeLists.txt":"42ce94744e82ffa000da8b64d81fc140e293b9f5da7dd4cf6b49e7404a2448d9","glsl-optimizer/README.md":"b18eef11a92d267d88a937b1154f7670ee433c730b102fdf7e2da0b02722b146","glsl-optimizer/contrib/glslopt/Main.cpp":"14ba213210c62e234b8d9b0052105fed28eedd83d535ebe85acc10bda7322dd4","glsl-optimizer/contrib/glslopt/Readme":"65d2a6f1aa1dc61e903e090cdade027abad33e02e7c9c81e07dc80508acadec4","glsl-optimizer/generateParsers.sh":"878a97db5d3b69eb3b4c3a95780763b373cfcc0c02e0b28894f162dbbd1b8848","glsl-optimizer/include/GL/gl.h":"1989b51365b6d7d0c48ff6e8b181ef75e2cdf71bfb1626b1cc4362e2f54854a3","glsl-optimizer/include/GL/glext.h":"2ac3681045a35a2194a81a960cad395c04bef1c8a20ef46b799fb24af3ec5f70","glsl-optimizer/include/KHR/khrplatform.h":"1448141a0c054d7f46edfb63f4fe6c203acf9591974049481c32442fb03fd6ed","glsl-optimizer/include/c11/.editorconfig":"f96a2354e5f2b90367d643e6d9e980ce76278d4d47afd8b2713b595753aa8b4b","glsl-optimizer/include/c11/threads.h":"56e9e592b28df19f0db432125223cb3eb5c0c1f960c22db96a15692e14776337","glsl-optimizer/include/c11/threads_posix.h":"f8ad2b69fa472e332b50572c1b2dcc1c8a0fa783a1199aad245398d3df421b4b","glsl-optimizer/include/c11/threads_win32.h":"95bf19d7fc14d328a016889afd583e4c49c050a93bcfb114bd2e9130a4532488","glsl-optimizer/include/c11_compat.h":"103fedb48f658d36cb416c9c9e5ea4d70dff181aab551fcb1028107d098ffa3e","glsl-optimizer/include/c99_compat.h":"aafad02f1ea90a7857636913ea21617a0fcd6197256dcfc6dd97bb3410ba892e","glsl-optimizer/include/no_extern_c.h":"40069dbb6dd2843658d442f926e609c7799b9c296046a90b62b570774fd618f5","glsl-optimizer/license.txt":"e26a745226f4a46b3ca00ffbe8be18507362189a2863d04b4f563ba176a9a836","glsl-optimizer/src/compiler/builtin_type_macros.h":"5b4fc4d4da7b07f997b6eb569e37db79fa0735286575ef1fab08d419e76776ff","glsl-optimizer/src/compiler/glsl/README":"e7d408b621c1b605857c4cab63902f615edb06b530142b91ac040808df6e22f7","glsl-optimizer/src/compiler/glsl/TODO":"dd3b7a098e6f9c85ca8c99ce6dea49d65bb75d4cea243b917f29e4ad2c974603","glsl-optimizer/src/compiler/glsl/ast.h":"3e68ff374350c49211a9931f7f55a485d8d89fc4b21caaffbf6655009ad95bf8","glsl-optimizer/src/compiler/glsl/ast_array_index.cpp":"92b4d501f33e0544c00d14e4f8837753afd916c2b42e076ccc95c9e8fc37ba94","glsl-optimizer/src/compiler/glsl/ast_expr.cpp":"afd712a7b1beb2b633888f4a0911b0a8e4ae5eb5ab9c1e3f247d518cdaaa56d6","glsl-optimizer/src/compiler/glsl/ast_function.cpp":"74f4fbd490e366b37f4715168bb3465ecd9334d4130942f75dcc8e80e8e7f027","glsl-optimizer/src/compiler/glsl/ast_to_hir.cpp":"d0f798eb09271d41d068b9e7b18220d37f1ed0083300ab51eba30989698fe23d","glsl-optimizer/src/compiler/glsl/ast_type.cpp":"8eb790b24b26dfb72bdc333744b566c26d8464c5d47d20eae659461f5c4899f7","glsl-optimizer/src/compiler/glsl/builtin_functions.cpp":"4a76d998a4f1952085c3377a30c7944dbfc0422b5418a6a13e3280a497bc5f2f","glsl-optimizer/src/compiler/glsl/builtin_functions.h":"a37cad7ed09b522c5b8bec7b80115a36846e7ba6e0874a2a858e32f7f202c665","glsl-optimizer/src/compiler/glsl/builtin_int64.h":"619def6f3aebf180da3944ef08f159ab12a58b24767e41d8b985ac37ded54d62","glsl-optimizer/src/compiler/glsl/builtin_types.cpp":"afec060b62d6f3b00bfbf94e9fa5f96341ce096c128d1eef322791e6ed9cea4d","glsl-optimizer/src/compiler/glsl/builtin_variables.cpp":"6563bfb1345cbca4c77e00eef09ad152f3e1dc271d246a08c5ce9e1f4ce4250a","glsl-optimizer/src/compiler/glsl/float64.glsl":"1072fd888be48c2a7a5117cd2d92a65f034965a66375f598bb856bff5d7be766","glsl-optimizer/src/compiler/glsl/generate_ir.cpp":"e5f0175370a0d07f93c48d3f0f1b8233d12c64a7b02de02dcc753ef7b398ef0f","glsl-optimizer/src/compiler/glsl/glcpp/README":"a0332a1b221d047e9cce5181a64d4ac4056046fd878360ec8ae3a7b1e062bcff","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-lex.c":"2d179879b1ffe84f58875eee5b0c19b6bae9c973b0c48e6bcd99978f2f501c80","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-lex.l":"e4c5744c837200dafd7c15a912d13f650308ea552454d4fa67271bc0a5bde118","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.c":"03494f9ce1cb82260506e2559e73a3eeb622c4bd51b65eaa0a2c3351862bd4c8","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.h":"264d9a18421cde255ce34a0a62b3d8e73465359f0d167e64aa3973062aae5bdd","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.y":"fafb66e3a8f149d19e085f18a4273ba6d4c11af9e9a01d665cc784dddf97b79f","glsl-optimizer/src/compiler/glsl/glcpp/glcpp.c":"37ed294403c2abfd17fd999d1ae8d11b170e5e9c878979fefac74a31195c96b0","glsl-optimizer/src/compiler/glsl/glcpp/glcpp.h":"85ac8b444bcbd0822b66448a1da407b6ae5467b649f5afaf5c58325bd7569468","glsl-optimizer/src/compiler/glsl/glcpp/pp.c":"a52d94f1bcb3fb2747a95709c4a77c25de7eea8354d2b83bb18efd96976a4473","glsl-optimizer/src/compiler/glsl/glcpp/pp_standalone_scaffolding.c":"d11aeb3acfe966d1b78f1ee49804093f2434214c41391d139ffcb67b69dc9862","glsl-optimizer/src/compiler/glsl/glcpp/pp_standalone_scaffolding.h":"abbf1f36ec5a92d035bfbb841b9452287d147616e56373cdbee1c0e55af46406","glsl-optimizer/src/compiler/glsl/glsl_lexer.cpp":"272b9fc1383d72b81bfc03fa11fdf82270ed91a294e523f9ce2b4554bd3effa9","glsl-optimizer/src/compiler/glsl/glsl_lexer.ll":"2b57d9f9eb830c3d7961d4533048a158ee6f458c8d05c65bea7b7cfbc36e4458","glsl-optimizer/src/compiler/glsl/glsl_optimizer.cpp":"f8095d20629d0af70be930b0612e169edb274551a1d25a3cd1bf9995a11ce2e8","glsl-optimizer/src/compiler/glsl/glsl_optimizer.h":"22e843b4ec53ba5f6cd85ca5f7bad33922dca8061b19fb512d46f1caca8d4757","glsl-optimizer/src/compiler/glsl/glsl_parser.cpp":"126baf368d525aba301854e3d91ba60b5aee32e1102376af71416f32cb95ec48","glsl-optimizer/src/compiler/glsl/glsl_parser.h":"2ea9a50716098a8f7bef782d2a030d757b68da73afb01b4d4940d3e8381d44e8","glsl-optimizer/src/compiler/glsl/glsl_parser.yy":"6b1fd1576b29fce005dff744a6dbd0219e4c695c361d61864e1f3a8d6fa6b764","glsl-optimizer/src/compiler/glsl/glsl_parser_extras.cpp":"aad64b5b66467da650091430681e8c6a820cf3cadc4db3c160bf2f15875390ae","glsl-optimizer/src/compiler/glsl/glsl_parser_extras.h":"71fd0e92bbdb193dfb067d7bfdb1200d77392be2fbd0cbfc9ca89d1bb4c7e741","glsl-optimizer/src/compiler/glsl/glsl_symbol_table.cpp":"6660fb83c0ddddbbd64581d46ccfdb9c84bfaa99d13348c289e6442ab00df046","glsl-optimizer/src/compiler/glsl/glsl_symbol_table.h":"24682b8304e0ea3f6318ddb8c859686bd1faee23cd0511d1760977ae975d41bf","glsl-optimizer/src/compiler/glsl/hir_field_selection.cpp":"72a039b0fcab4161788def9e4bedac7ac06a20d8e13146529c6d246bd5202afd","glsl-optimizer/src/compiler/glsl/int64.glsl":"303dbe95dde44b91aee3e38b115b92028400d6a92f9268975d607471984e13eb","glsl-optimizer/src/compiler/glsl/ir.cpp":"2b4741cce90b5d4abff5d719c7324e2693c67294d4d99736cb241554adb281bc","glsl-optimizer/src/compiler/glsl/ir.h":"990b1c74447c4eb4835353ccb0ed9aea644f97fc1129ef1739cd935075d85d2e","glsl-optimizer/src/compiler/glsl/ir_array_refcount.cpp":"8cdc1cffe01e42e0566fa2193a75f789628e8025ad1b82f0ee6f204451b7f9f7","glsl-optimizer/src/compiler/glsl/ir_array_refcount.h":"75f06ec81342b379096ca52e1dc0fd5f19a11ff8e9b58203c20628179d644c12","glsl-optimizer/src/compiler/glsl/ir_basic_block.cpp":"1e2920b1c0ecb08424c745c558f84d0d7e44b74585cf2cc2265dc4dfede3fa2f","glsl-optimizer/src/compiler/glsl/ir_basic_block.h":"81be7da0fc0ee547cd13ec60c1fcd7d3ce3d70d7e5e988f01a3b43a827acdf05","glsl-optimizer/src/compiler/glsl/ir_builder.cpp":"daba29c5a1efdd5a9754f420eb3e2ebdf73485273497f40d4863dadeddb23c0d","glsl-optimizer/src/compiler/glsl/ir_builder.h":"2822e74dd3f6e3df8b300af27d5b11ea2dd99d0e5e7ca809b7bbcce9833c483c","glsl-optimizer/src/compiler/glsl/ir_builder_print_visitor.cpp":"8c6df5abf2fe313363f285f171c19ca6c8ee4f3bc2ed79d33c0c88cc8be45c48","glsl-optimizer/src/compiler/glsl/ir_builder_print_visitor.h":"799852adc3a0e54d04080655e7cebfa0d3bf5b6ffed5d8414f141380665d4db7","glsl-optimizer/src/compiler/glsl/ir_clone.cpp":"d897a4e1f5bbec4a6a2f15044c1be9a4d13899c73be77335b041049a4589aa5d","glsl-optimizer/src/compiler/glsl/ir_constant_expression.cpp":"78bd87ddb09db67f6c499067728d72aef4f16aa02721a99a4b769d1e0cfa9010","glsl-optimizer/src/compiler/glsl/ir_equals.cpp":"bca28533a6310b0fc152b56d80872368f1510dc62ed6e8ac199b9ffa7fac02e7","glsl-optimizer/src/compiler/glsl/ir_expression_flattening.cpp":"7e918d4e1f237eca01396004015865ce345afe32a876c9dbc6728576a1a7eae4","glsl-optimizer/src/compiler/glsl/ir_expression_flattening.h":"f45b66aa9497520e7e08e612d24b308477c34477fbd963ee9320eac664957f16","glsl-optimizer/src/compiler/glsl/ir_expression_operation.h":"cc9f10727dbd26cac506804f51456302c702650f9eeb59054a7e1575d5cf6687","glsl-optimizer/src/compiler/glsl/ir_expression_operation.py":"7b86c96021b9fbe165957f4ecb0b612fefcde1c2cf3c6d75e3cdb22e369216ba","glsl-optimizer/src/compiler/glsl/ir_expression_operation_constant.h":"9ad3346416392e3efa11e12ecf2feca7453c5253d241eb96c91dfb85d4f2b971","glsl-optimizer/src/compiler/glsl/ir_expression_operation_strings.h":"a6826daf496a8b9e89885bc2a161ac3445d501b23c6e0ac33e2c01b506b273c8","glsl-optimizer/src/compiler/glsl/ir_function.cpp":"7537365fc0fbe4b37a26b9a2146cc64d3e9a774d60eab63b65002ad165ae8fc7","glsl-optimizer/src/compiler/glsl/ir_function_can_inline.cpp":"faddbf112187a048d502716a3fb82570a322299ba2a3abd79388382c82040bfc","glsl-optimizer/src/compiler/glsl/ir_function_detect_recursion.cpp":"9176973eaf5c0a984701f953bb7a80f37dca43d59b5bce50fc69b3f02f2902d7","glsl-optimizer/src/compiler/glsl/ir_function_inlining.h":"9739493f99c489987d650762fccdd3fb3d432f6481d67f6c799176685bd59632","glsl-optimizer/src/compiler/glsl/ir_hierarchical_visitor.cpp":"3725861fbe2b98e0617f52d3b14cf6d3b25fb5ec00f5ef5d308b03642f592767","glsl-optimizer/src/compiler/glsl/ir_hierarchical_visitor.h":"e0560210e966c0c31e4ca843e80ea154e64db5a444b8c2df845b6ba5b3a43fc1","glsl-optimizer/src/compiler/glsl/ir_hv_accept.cpp":"caf7ce2cd9494aadd3c58bcf77f29de58368dc9e347a362bbf37f8bda9509b80","glsl-optimizer/src/compiler/glsl/ir_optimization.h":"8b3dcfc7f9e96b21a8dd47a0040d90be483a9e67a2cdce3a697188fb758d4630","glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.cpp":"f8e34a983452be0dcb5a695e9c8e895eead24f9e540992a8afe510ae85da4c4c","glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.h":"1ad1bd3efd1ace39051c13f904c05fd80425d329444f9a8d47fd6d948faf46e0","glsl-optimizer/src/compiler/glsl/ir_print_visitor.cpp":"643f5a68aae3fb37267fd793f1216d1cfdeb2c09338c26b1f30e4c6deaef4de5","glsl-optimizer/src/compiler/glsl/ir_print_visitor.h":"4573eb93268a2654c14b505253dd651e2695d43dc745904d824da18305269b95","glsl-optimizer/src/compiler/glsl/ir_reader.cpp":"06bfba802c8354e5a8b2334b6d78d6297de18235bedd3f8fbb382c89870b02f2","glsl-optimizer/src/compiler/glsl/ir_reader.h":"63e3f7f1597936a7011d5b520e171b197bf82bee6c1560d822c3edf5aaa6f9e9","glsl-optimizer/src/compiler/glsl/ir_rvalue_visitor.cpp":"84b5c5d746555adca85759c2912fe48010232b7c1c0bd2cf03bd04067a85e66f","glsl-optimizer/src/compiler/glsl/ir_rvalue_visitor.h":"fd8c561b71085d3211fff85ed514fecb299d8ce19a04bc063419a55b6d840525","glsl-optimizer/src/compiler/glsl/ir_set_program_inouts.cpp":"ab9f115ce9e7f312d9c7978340ced0dc4ae6d13a80e08442ba9709d11d50cae5","glsl-optimizer/src/compiler/glsl/ir_uniform.h":"683ae6896b1a08470c090be5f822fc31cd434eab9216e954b9bba24a46975109","glsl-optimizer/src/compiler/glsl/ir_unused_structs.cpp":"9c1620c45f2fc071fe5ed828472040b14c5f42effe06aa0e3b8352c95ef78786","glsl-optimizer/src/compiler/glsl/ir_unused_structs.h":"13387b49c23093575276b25b9dfd31fedd8f131c5c4f3128ab04cf03e15b5295","glsl-optimizer/src/compiler/glsl/ir_validate.cpp":"6b232be5999a86ea278f4f15b2832d76843246509118d924243055a3b9b0299f","glsl-optimizer/src/compiler/glsl/ir_variable_refcount.cpp":"2764a3cad937d53f36db7447c3a5b98b04bf153acf81074d971857fc5bca460d","glsl-optimizer/src/compiler/glsl/ir_variable_refcount.h":"b0668e3eb1501ef65e38fe12830742ecb3d28e6039f30e366c8924efc29b4a39","glsl-optimizer/src/compiler/glsl/ir_visitor.h":"f21b3534c3d66d5fb707d1581fece7e1eb043523afbaedf89918cfb031c6df94","glsl-optimizer/src/compiler/glsl/link_atomics.cpp":"360f0209e11f367ba358223597b0a118bae095bff16337cf03f1fb89c5b80ca6","glsl-optimizer/src/compiler/glsl/link_functions.cpp":"de7895da8aa33a1e3c2c1eb2fdaf267ab5d1fbfdb79ae2e67f95211e946e294c","glsl-optimizer/src/compiler/glsl/link_interface_blocks.cpp":"1926cfa73810704eb19b916c1b2cdb9321155e2f98b2a0a57c7c3c6e960540cd","glsl-optimizer/src/compiler/glsl/link_uniform_block_active_visitor.cpp":"1e14e06ca3b2c1089cfba2e8eaf0c1f373d9d6374b6082f320962dd71ae09611","glsl-optimizer/src/compiler/glsl/link_uniform_block_active_visitor.h":"fd58c155af645295bb6aec08797889de586f4d919731de2bce57e8dce59bb048","glsl-optimizer/src/compiler/glsl/link_uniform_blocks.cpp":"09589f49776dce32e6c4044937de7e0c839a9754ad31960148f8f9e010658997","glsl-optimizer/src/compiler/glsl/link_uniform_initializers.cpp":"bf98e08c12db466acf9623cbeb8fa8e3b4002512722e7a6521287f558a099f37","glsl-optimizer/src/compiler/glsl/link_uniforms.cpp":"84bad5b1377362cecf259b05124239be5220b03ce1c0c61b59bd9a47e4379af2","glsl-optimizer/src/compiler/glsl/link_varyings.cpp":"a5f1a53e7c80d635515fe808ff223d89fef1767abb0f2b7aa28fa6773dca353f","glsl-optimizer/src/compiler/glsl/link_varyings.h":"b9dbe018f038df69763df2e928742ce81bbc6e3aaba26f50621e30a6d9aa6220","glsl-optimizer/src/compiler/glsl/linker.cpp":"40b1ecd5d4f6c7f13d5a87ce390561a51fdf6f3fcd9b2197b9c88b03a773ba94","glsl-optimizer/src/compiler/glsl/linker.h":"ecf94b4ad75ef461c27c557fda4bd25f34c91930822b8e1d729ec84520d4a049","glsl-optimizer/src/compiler/glsl/linker_util.cpp":"1663ad88e2a369305659aeeffaedb5bd752cf76340a2ba5797fc0bf600633cf9","glsl-optimizer/src/compiler/glsl/linker_util.h":"6db788daf9c8e87ae2764b61a8b37ebe419e69c1b82ddee01986e37c978c6993","glsl-optimizer/src/compiler/glsl/list.h":"b1f46ce0e552fe7c45b2a19408a9d97662e23e4b182ab335491c26f8cf25886f","glsl-optimizer/src/compiler/glsl/loop_analysis.cpp":"57ecd573477c68091c7cc99537faa7139a8f395935e3d4f10144cefdefb5a611","glsl-optimizer/src/compiler/glsl/loop_analysis.h":"a85f045a038ee5b5176063e85d7988865862c44ab0580f771b993a042d0b69cc","glsl-optimizer/src/compiler/glsl/loop_unroll.cpp":"bd4292ea2809f5a669bcb76ceaa1ac365772dcd638c579c3ed10275214901a54","glsl-optimizer/src/compiler/glsl/lower_blend_equation_advanced.cpp":"8cfbef140d9c4b4d2f57bfa05c9c374d31a121d0f87afce94333f049023b654a","glsl-optimizer/src/compiler/glsl/lower_buffer_access.cpp":"1ae221c3c7a95aeb867207e7a742be635f91b406c157747bfd6ddf10274d97fb","glsl-optimizer/src/compiler/glsl/lower_buffer_access.h":"807886953a576a323591798cbca5e2df24295ea893b28affd8ffb5926cebaa04","glsl-optimizer/src/compiler/glsl/lower_builtins.cpp":"4d81afc32cf58e1481fcb5e42888ab93dbe6820310a20ff7a9982b77b2152d9b","glsl-optimizer/src/compiler/glsl/lower_const_arrays_to_uniforms.cpp":"608403f0eeeedf21cfcd3014116e0f44e28cbdf6c4c32aac7e613e64e30205e1","glsl-optimizer/src/compiler/glsl/lower_cs_derived.cpp":"179905cd47a294122adeb5b0abfed6f2f67782dcde21b544d1ee2c1985154e66","glsl-optimizer/src/compiler/glsl/lower_discard.cpp":"3b361b2db0004d544d64611cb50d5a6e364cf6c5f2e60c449085d7d753dd7fb0","glsl-optimizer/src/compiler/glsl/lower_discard_flow.cpp":"f5c29b6a27690bb5c91f196d1a1cf9f6be4f1025292311fe2dac561ce6774dee","glsl-optimizer/src/compiler/glsl/lower_distance.cpp":"a118c85493d5d22b2c059a930c51a5854896d4b1dade76598eaa985e5a3dff8c","glsl-optimizer/src/compiler/glsl/lower_if_to_cond_assign.cpp":"469e617757fd1728709cce021aac5c8da05ee503bf5366977bdc4ef7a6d83950","glsl-optimizer/src/compiler/glsl/lower_instructions.cpp":"6ff5c396abe40d8a2145d571e99e2bbe9143393e15aafc28adc2803a01d821b6","glsl-optimizer/src/compiler/glsl/lower_int64.cpp":"d1ed41196880dd53c7b13e2782f9423f8442bf1d46186e8be92b1b66218a83ee","glsl-optimizer/src/compiler/glsl/lower_jumps.cpp":"34de7b493f281589fb0c2c0f6e885d0a0fabbe7a4e97a73de374dd714777a58c","glsl-optimizer/src/compiler/glsl/lower_mat_op_to_vec.cpp":"dff7a308edc4846c348ed4225c6699a9c75abac68d88f41f85954276552779f4","glsl-optimizer/src/compiler/glsl/lower_named_interface_blocks.cpp":"16063ac127bff75a68272070ab11c21c25101edbff62b4c68f4983b4cd941af0","glsl-optimizer/src/compiler/glsl/lower_offset_array.cpp":"3b00773399135aea85746a5a68b96ef000bc6841be1a2c8e6f25c516628b0949","glsl-optimizer/src/compiler/glsl/lower_output_reads.cpp":"a0fc9975d5aa1617e21fc6c353659a9802da9e83779a3eef4ec584f74b4dadc5","glsl-optimizer/src/compiler/glsl/lower_packed_varyings.cpp":"7550099d4ae123d71541c2fc88bc04fbfe9271ec75d7e210987d1c8cac3cf3ea","glsl-optimizer/src/compiler/glsl/lower_packing_builtins.cpp":"79a13d161fe505a410ab948d92769395708693ec888153630fa240e5b97e356f","glsl-optimizer/src/compiler/glsl/lower_precision.cpp":"f82a185b879872b977a1787d8061b9a80bc4cf8db1b970db6efba2ad9cc20fa2","glsl-optimizer/src/compiler/glsl/lower_shared_reference.cpp":"ea2dccf50a83bc19391bf6b7ab6aa53c0005f427af4066d25140340af9a4beef","glsl-optimizer/src/compiler/glsl/lower_subroutine.cpp":"f69fa53650eeb6f2944fce4d36a6e0a423e6705f3a3bd3389c7fadb83cfc8802","glsl-optimizer/src/compiler/glsl/lower_tess_level.cpp":"b196c9d424c0569f3e85d75c2d125af21566cb113d69036db87c0990703e0fa7","glsl-optimizer/src/compiler/glsl/lower_texture_projection.cpp":"4d247f244272adc8250fd888d8d932a140dd5de4d1efc7a58492c3c2b8291527","glsl-optimizer/src/compiler/glsl/lower_ubo_reference.cpp":"89bdbc6c1669230c644c0857db1ce2781ec61d349ecd08c7914146e1f4750a4a","glsl-optimizer/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp":"fce930f29ac9405b297d1f749d68f59506b89c70b4ee1b1ab8cf49a34cc71ecf","glsl-optimizer/src/compiler/glsl/lower_vec_index_to_cond_assign.cpp":"3c67d851a11a55fad1c49a550f3a0cfe50892d33a3f238ce266cd829eba510a8","glsl-optimizer/src/compiler/glsl/lower_vec_index_to_swizzle.cpp":"f5ec666b73e1415cbab32519a53605ed385f3b03e889560373dbce69dda5000e","glsl-optimizer/src/compiler/glsl/lower_vector.cpp":"f7c13f5572ebe09b6a71553133b2cf003cd4b77b9657600672ee3b21bf890725","glsl-optimizer/src/compiler/glsl/lower_vector_derefs.cpp":"b05793da6dd620a531b43df5af8b2ecbc37b9db0c88910f5724ea10bcd057e19","glsl-optimizer/src/compiler/glsl/lower_vector_insert.cpp":"fee772ec17eea5e86a529bf9c5fa2ee0d29a5982bb75ebc6d68ed36cd19aa299","glsl-optimizer/src/compiler/glsl/lower_vertex_id.cpp":"690e8715182e03fead5cc5a35251fb4f41b357e4c71a1dfbc4bd7be19862b56d","glsl-optimizer/src/compiler/glsl/lower_xfb_varying.cpp":"58c0e8b270e4bbde54250be03cdb2f36966bcafb785372ad2e2b786835df7f9f","glsl-optimizer/src/compiler/glsl/main.cpp":"ae5e88abbbc8a12f769e1296bad938b9d7398cc6da0d3d0caeceeeb876536850","glsl-optimizer/src/compiler/glsl/opt_add_neg_to_sub.h":"f5054944bfd068810629080d0ea11df78b3f57a8f86df75e13ca50157ad1964d","glsl-optimizer/src/compiler/glsl/opt_algebraic.cpp":"25f45b20e1972ee8c789177a1aeda6e4286c25db2eae3a43ff83029ae64969c0","glsl-optimizer/src/compiler/glsl/opt_array_splitting.cpp":"19d3ce0e815438f4df9ab2890e767b03a4f3f191b53bb30c0217cf2ae6a95430","glsl-optimizer/src/compiler/glsl/opt_conditional_discard.cpp":"0e44e0e126711a3725c1f3a2aa65ff03c381fed08680ffc30101aae60f716c4e","glsl-optimizer/src/compiler/glsl/opt_constant_folding.cpp":"a088d04d9b45f9e55e235835648f614c89b7803c03a6d4f6a6d1a6bc1f0228bd","glsl-optimizer/src/compiler/glsl/opt_constant_propagation.cpp":"8a9440d77ecd6dcf13e683cbb99943aab6311c8fd4b5f6a9189a8d4f270746f4","glsl-optimizer/src/compiler/glsl/opt_constant_variable.cpp":"63d3ccd4dd09f19c9cf1a2f51592111bed41284504f29f3c0de4cadebc439a37","glsl-optimizer/src/compiler/glsl/opt_copy_propagation_elements.cpp":"ffa0f50863995e0d2e31f55a52e82319edc71e520987bebd7f7e561ea331c64b","glsl-optimizer/src/compiler/glsl/opt_dead_builtin_variables.cpp":"84e8747b948232f01dd56b428b9315f96f9511f605f240119fc446fae28981a9","glsl-optimizer/src/compiler/glsl/opt_dead_builtin_varyings.cpp":"761523e88f5b3ba785170f4d7205e94fa99acb7e74d29efbe40e1c010e1dbdb3","glsl-optimizer/src/compiler/glsl/opt_dead_code.cpp":"fd1ba2da7337d4e5dad17f5c2d73d9cc8880305f423e85d64cf94553588fa401","glsl-optimizer/src/compiler/glsl/opt_dead_code_local.cpp":"969a598b4df322baf222258a66cd64a326ea20e5b3125be9d8d1771f522c69e0","glsl-optimizer/src/compiler/glsl/opt_dead_functions.cpp":"774cae6536d02edf26e996a2a895e1f62d5098f16dc96b44798b4fc731a9a95f","glsl-optimizer/src/compiler/glsl/opt_flatten_nested_if_blocks.cpp":"3696a5c55f02e20056e085bc2714f73ac992f221b6f3387d655068e86b512046","glsl-optimizer/src/compiler/glsl/opt_flip_matrices.cpp":"44f0fe05b49329667671f88c96dc86ab3fe1459ff7b87f2b2d88de2d49829f9f","glsl-optimizer/src/compiler/glsl/opt_function_inlining.cpp":"fb56a33c90419a01676b57cbd91d0674a54cca40e6defaacc88dd33facebc131","glsl-optimizer/src/compiler/glsl/opt_if_simplification.cpp":"ac406eb35e379c357641d6c5749f50c65961455924d3dc884e2b90046fa92c5c","glsl-optimizer/src/compiler/glsl/opt_minmax.cpp":"8abd59d3b14ef60ff14a9c69660e6945f5cf10b97edb4afebe56be3f81d96316","glsl-optimizer/src/compiler/glsl/opt_rebalance_tree.cpp":"8bb6329dc0f299042368fc81934c2df019b45ab9f7aa0415d4e57b8d1ff98c9f","glsl-optimizer/src/compiler/glsl/opt_redundant_jumps.cpp":"222c73e2ac7a938ebb6428cc6c780c908ff6156d8ff935b04fed93a48fc10496","glsl-optimizer/src/compiler/glsl/opt_structure_splitting.cpp":"2edc79cc13f3177934e0443ad62f5976a1991f01f86ea303a803434849b13a47","glsl-optimizer/src/compiler/glsl/opt_swizzle.cpp":"015d0abddfe507f67c4b96c82988d861d018ededf7bf055e2bcbe9ea92da694e","glsl-optimizer/src/compiler/glsl/opt_tree_grafting.cpp":"46d28ac983ea244a4315bdc0e8892979ec4d1f9b9a96ac8a8a08006d9bc5e878","glsl-optimizer/src/compiler/glsl/opt_vectorize.cpp":"d80ee43bb97d9f016fb9c5e1e06f5b2afa569811f368ba067be794ec11d085fb","glsl-optimizer/src/compiler/glsl/program.h":"2982447e2abd35371e273ad87951722782a8b21c08294f67c39d987da1e1c55f","glsl-optimizer/src/compiler/glsl/propagate_invariance.cpp":"080943e21baa32494723a2eefb185915d2daae1f46d6df420145c5ad6857e119","glsl-optimizer/src/compiler/glsl/s_expression.cpp":"1ced972bc6ecc8eab4116ea71fb0212ab9ae5bcc0be3b47aa5d9d903566b3af1","glsl-optimizer/src/compiler/glsl/s_expression.h":"65b847e30e22a809b57d0bc70243049c99d9c6318803c5b8d0826aba55dc217e","glsl-optimizer/src/compiler/glsl/serialize.cpp":"be0eb4251348a9d921acb839a5c48c6023a2e9d116d602bb0432787ab623655d","glsl-optimizer/src/compiler/glsl/serialize.h":"57425732eba1233d928e5f07f88b623ce65af46b3bb034bf147f0a4b7f94f9a1","glsl-optimizer/src/compiler/glsl/shader_cache.cpp":"e0c5c433f2df3fccdf1d61281bfcb0ee5633433339b97c697d64db99611cbaaf","glsl-optimizer/src/compiler/glsl/shader_cache.h":"9217164d8d7f54aca0fe5922c7187095a6ae0cb703b196b79805aeef07a7e697","glsl-optimizer/src/compiler/glsl/standalone.cpp":"8e6c416a14d631261917a5fe4cc91880c287b22b2dfd70eb22028289a8fa5364","glsl-optimizer/src/compiler/glsl/standalone.h":"a7c397d1dfdd1e7fb2cfe99db35cd9df93251e642059208533202b7f20497f83","glsl-optimizer/src/compiler/glsl/standalone_scaffolding.cpp":"970d14b7a9d58e5270321f97bf5d57795558b1c570a56678e04a65b26c60bf4f","glsl-optimizer/src/compiler/glsl/standalone_scaffolding.h":"d921a617ea82b9e49413314492a645c44356de503581b1be3f1b57de236e480d","glsl-optimizer/src/compiler/glsl/string_to_uint_map.cpp":"d824bf5b839bd39498dc9e457103cdbe3e5289ddf7564107c27b1505948dd31f","glsl-optimizer/src/compiler/glsl/string_to_uint_map.h":"e2f18e66359c9d620e085de7f4a334a47df9c66e65a5bfe8b734c627bec04104","glsl-optimizer/src/compiler/glsl/test_optpass.h":"b27b8f35f5387e7ce4982bb51c7b63ccf14f91757f3108a5d02ed006925bb8a0","glsl-optimizer/src/compiler/glsl/xxd.py":"376484142f27f45090ea8203ae2621abf73f06175cb0ee8d96f44a3b9327f4bd","glsl-optimizer/src/compiler/glsl_types.cpp":"044bb6754f45419a3151e7a25c39202a82009ae3c6bc54ff7f0bb4258a5deefe","glsl-optimizer/src/compiler/glsl_types.h":"fd899a42f34ddeb8601bc3cd6c5e3aed82fc8aef4042dde1b39b3c01e1dcc219","glsl-optimizer/src/compiler/shader_enums.c":"436bff5216b11b0980bdfada5885fc6ac9afa2037a3027fcd6eea2a8635597ac","glsl-optimizer/src/compiler/shader_enums.h":"13220442a5c02e83540cf2c0ad4f8417b2fbda5f2586dec4e92082544c937cdd","glsl-optimizer/src/compiler/shader_info.h":"4c5453e81197ca83593ee4f365074b23530f2ab21c78e1733b63dec6f344c12a","glsl-optimizer/src/gallium/auxiliary/util/u_half.h":"3c2b37bda3ccb64387e44b723d29cf9046decab1a893bf42d842e9603398bdee","glsl-optimizer/src/gallium/include/pipe/p_compiler.h":"c75620096ce8523dae90599e50aa2ef6468d3b0e368a77795edeb20dd1abfc0c","glsl-optimizer/src/gallium/include/pipe/p_config.h":"a27692fc35f9e55df3224b7529e66b3001e911e94e6bc5f8f569e493e1ee3fb7","glsl-optimizer/src/gallium/include/pipe/p_defines.h":"be26d68c0acc67c5e44788c6299716a9eee415fd81d7d747e3738a829e3b6b38","glsl-optimizer/src/gallium/include/pipe/p_format.h":"5674215fc41d27496f037cf837717daefbf23ebb38d40ace7c0c414bc08182b0","glsl-optimizer/src/gallium/include/pipe/p_state.h":"d600593aba5f5a17072a6c38f6baa81e01c7994b0174250f7e433bb41684b702","glsl-optimizer/src/mapi/glapi/glapi.h":"73632a625c0ddabc401205e8b5a81eb8af8506868efe4b170d7979ec3619e9c5","glsl-optimizer/src/mesa/main/config.h":"5800259373099e5405de2eb52619f9de242552a479902a3a642a333c8cb3c1e7","glsl-optimizer/src/mesa/main/context.c":"2f3208473d99c94f734b1137ba91889d4a1babb9e7534bf1dc85d851ee98274e","glsl-optimizer/src/mesa/main/context.h":"cc7e4194797db9d007f01884e23d786c453b3860821f7f2ddcdf0f1bf3f8ffb1","glsl-optimizer/src/mesa/main/dd.h":"6a964acd06b6c2d88700e69fb75fe3c6b3b3d45bbc41db24f3f897a29695fe0c","glsl-optimizer/src/mesa/main/debug_output.h":"7312422e90b8c0e34028ac27280e438139b5cba525c99deb3ac883cd3d87e452","glsl-optimizer/src/mesa/main/draw.h":"7eaef3a9e27a60ea6f7937109bf3a6190b831162fde0479abb12077ce27c353d","glsl-optimizer/src/mesa/main/enums.h":"87d562a6764f51c014a2274fa7c3aca17c04441537ddd56b2554f13c6fffea92","glsl-optimizer/src/mesa/main/errors.h":"c79444b5df289c90fbb22a33b2d0c23917d9fc4510960088f0b79e53bb56b1b2","glsl-optimizer/src/mesa/main/extensions.h":"a38b2f87cc93c513994281350d69e06c84ff8eded5313ec0a1be33f375e0ebbd","glsl-optimizer/src/mesa/main/extensions_table.c":"17642d1a8c9a0bf2bd61060052d33ff14a005d2b962e6cf91465797a50851e85","glsl-optimizer/src/mesa/main/extensions_table.h":"2c879571c238d2e14461031ac740372fd0f9ac3a34c0d5541bb9b7ed4c0376c8","glsl-optimizer/src/mesa/main/formats.h":"02e2f7ec3e39286cf9f27e2641043e6df8ecb1dfde9e643313210e214af2a929","glsl-optimizer/src/mesa/main/glheader.h":"58217b33eead6aa6b23cd4a291cefeaa6cb84e465f4960daffca97c44d6d1c35","glsl-optimizer/src/mesa/main/glthread.h":"51fb2711f77e7eafcfc52d29d5b844978832b24c930d88accd48d143a6eb9c6f","glsl-optimizer/src/mesa/main/hash.h":"7e7f782034c16a8e693de48e00c31d4a90b0129f4029fd074033d7d16ccbe718","glsl-optimizer/src/mesa/main/macros.h":"73d15ddfd64f2b57b9b2ffeeb993b9c2c0899a80563e9d6ff337b11ccbe6eee5","glsl-optimizer/src/mesa/main/menums.h":"5dfac0e2279d60b0cd0c7b9fc2a5021620d0f6282ed2e738c420214e3af152d3","glsl-optimizer/src/mesa/main/mesa_private.h":"edda678b93438944279a551f663b8858ad84814a9fc88ba9672ef195599c24ae","glsl-optimizer/src/mesa/main/mtypes.h":"6efddefa099e4d2e3fdd97f0055644f47aba21711385edfeabc2d9b0676f2eec","glsl-optimizer/src/mesa/main/shaderobj.h":"9f0dfe96d0c2154201adef942bd36053533ac7b2492fb3786acda5bea514c75e","glsl-optimizer/src/mesa/main/uniforms.h":"4e331e6ad6e9cbded978b4082dbe0a57c1f8f01327446bb6892bfc179976c38b","glsl-optimizer/src/mesa/main/version.h":"9d0a13a758099302dc55cf7d045791834a89b0f9d4cf17b2692259b369a8a9a1","glsl-optimizer/src/mesa/math/m_matrix.h":"a37b19f182e070db3df93b0ede43c22fb8be8c2906504133ee6dbd7db1185d8b","glsl-optimizer/src/mesa/program/dummy_errors.c":"1820e305515b4c5e041f5e1623266a48ec8f076a155310be7d60637101f593e4","glsl-optimizer/src/mesa/program/ir_to_mesa.h":"b47f58d22e3ca2ae42d52501ea769d15c4476834944fa97eeccd3a3439211d00","glsl-optimizer/src/mesa/program/prog_instruction.h":"ab3832152a7e144b59e5a2264b2c29db56d93be31e76bbd958527a56771b40eb","glsl-optimizer/src/mesa/program/prog_parameter.h":"ba18c743284eadbc837c2c364c73e5d372321a7637a76e589d8d39fe8b5de225","glsl-optimizer/src/mesa/program/prog_statevars.h":"fc413698f84bc52d45fdeae0471934ee9904bfb7eac1a2b5f70446e54bcbbdca","glsl-optimizer/src/mesa/program/program.h":"1f01026a4eff440a3f122fd9b519d03546fe7f7d8be60dca834e95a2f8fbbfd2","glsl-optimizer/src/mesa/program/symbol_table.c":"6611cb9f078035bf5ff8c9112093a6c7d99f8af99a3931d0c07f227cc72283ea","glsl-optimizer/src/mesa/program/symbol_table.h":"631dc35ac48d5e87962d45507461920f6575610960ffcc42a08cefeb43300cda","glsl-optimizer/src/mesa/vbo/vbo.h":"6eb1dcd9a08c92f276c5fe08da184ff9d455d1be421913b8ad732a7b65e858fb","glsl-optimizer/src/util/bitscan.h":"d4fcb47b57a50d70cb97f99ca3e619bc06282a877768a435e009775ce8d77f36","glsl-optimizer/src/util/bitset.h":"c40f78515c6230fed18345c6751ce33833a49da7a27901c7e6d7340cbdcbc5e7","glsl-optimizer/src/util/blob.c":"8f729846f66efc9c15485cc5fc24c6ec861fc1fecb2f652573f2a237d481b791","glsl-optimizer/src/util/blob.h":"93e1eaac866b9a7cd6fc03b533c18fb2edf0e97f03395eff4f3a605c4fc14d0c","glsl-optimizer/src/util/compiler.h":"79e3bf40a5bab704e6c949f23a1352759607bb57d80e5d8df2ef159755f10b68","glsl-optimizer/src/util/crc32.c":"2f3467a046b3a76784ecb9aa55d527698c8607fd0b12c622f6691aaa77b58505","glsl-optimizer/src/util/crc32.h":"59bd81865e51042b73a86f8fb117c312418df095fed2d828c5c1d1c8b6fc6cd4","glsl-optimizer/src/util/debug.c":"c3d68e9752ccc19e66c669562cd113cf1d0ac83cbb30174789e7fb8d1df58f9c","glsl-optimizer/src/util/debug.h":"50068d745c4199ccbd33d68dd4c8a36d2b5179c7869a21e75906ddd0718ca456","glsl-optimizer/src/util/detect_os.h":"343a8790d17a3710c6dd015ee367f84e3902ff3f2e36faca2bf93f9d725d3574","glsl-optimizer/src/util/disk_cache.c":"f533937e5a4fffe76e2739ef4b6b1e1da097d96d63eb808e68ebbc7027641c23","glsl-optimizer/src/util/disk_cache.h":"e83314fb14134a8e079b15e470a6376ba5a8253701f048c890a62b7e55d64bc8","glsl-optimizer/src/util/fast_urem_by_const.h":"e108fce804616c47d071dfe4a04163eec1126e448ed1aa89abb6b3a6d772bd5b","glsl-optimizer/src/util/fnv1a.h":"ab2596f19c6adf431ae27618f62c5743e24ad23ef83bb359a4c4c218245ab459","glsl-optimizer/src/util/format/u_format.h":"4cdfc0c59cbc99a092e5ec5a396910f2d93b9643e5d8141050b011e66f11e45b","glsl-optimizer/src/util/futex.h":"26f7c9d86e9ffef4c0fa2761f1aaa1918337302e20bd6ca10e61dc3c47356deb","glsl-optimizer/src/util/half_float.c":"11bc2584493d5d9d46e8c8a619a0307cf150bf5ab5d0f96bb764b061dc37a00e","glsl-optimizer/src/util/half_float.h":"7f7c380f126da1400a91758cc0392f24bf967bce1672890b62be26fe9fbd922b","glsl-optimizer/src/util/hash_table.c":"0ca40352e35dedab0a84c64c903f1b16d47e950bb5f43b4d22bb57d499bfea6e","glsl-optimizer/src/util/hash_table.h":"217191bb360592e2232f187473c10287d2cda8ae6fa5c53d0ef74c8c206118b4","glsl-optimizer/src/util/list.h":"9fab03c6a78186bb5f173269f825f6ce976b409d931852e3d93bac632e07989a","glsl-optimizer/src/util/macros.h":"63faf65b51058c483b17f1f77da51d1c53c8beab52678cb6bd01f1228a63b6b0","glsl-optimizer/src/util/mesa-sha1.c":"00c692ec353ebc02c06c57c5a71de0ab7a119f86a4146f452e65ec87e4944417","glsl-optimizer/src/util/mesa-sha1.h":"bff4c29f4bf7cdbcefb30fa0c996a7604a380eba8976467c2a60e7cd328f7e26","glsl-optimizer/src/util/mesa-sha1_test.c":"25da89a59d51469f77b4c468ca23ffdce0a7a1166a70b6cc23026a6800b0143c","glsl-optimizer/src/util/os_memory.h":"64555faf1760ae6954f42c83727c38dfc4c278e9152115779ffaad58b42adacf","glsl-optimizer/src/util/os_memory_aligned.h":"12d86fa94be38c13f7eeebdf313795e1267dd5a7187d2f0072e0e896f41702f6","glsl-optimizer/src/util/os_memory_stdc.h":"07360363b88c927065e10df71bebf6c8a0cc3b9167c9dfce55f2d65f11e6f787","glsl-optimizer/src/util/os_misc.c":"a9936e613ec84803abd59ad47c192c8e3939993c950ac91973fdc4cec1801bb8","glsl-optimizer/src/util/os_misc.h":"cc68eb12e05b5e749c54298cb4a6f4cd20cc5af7db3403e70b3c27b56090c740","glsl-optimizer/src/util/os_time.h":"73e775f7335244ff5964c678c27eedf1aea6abea44c4169d327ea8c7ce4a3a88","glsl-optimizer/src/util/ralloc.c":"4b51189595ef67bcef52c40cbf654d969041dbd15e15d4a893ad494ac060aeca","glsl-optimizer/src/util/ralloc.h":"e573c45875ff1530f0dbee9a93ae55535fdac8d5cc88a79ebc327c688824bde5","glsl-optimizer/src/util/rounding.h":"0450722353caf83de07e67f335949dbe95fe53b534052d4ee9d28d2781387614","glsl-optimizer/src/util/set.c":"86f8c9a830bead5a5a79bc970b0ff97809312af07b3beb39ef9d90af04d40a1b","glsl-optimizer/src/util/set.h":"3e39ca161e7ed4ec7c436cc9c7919ed9a55ed1b71edbf2caf6f9bcfd9bc578ed","glsl-optimizer/src/util/sha1/README":"00af7419af05247081858acb2902efd99fcda2ce16e331079f701645bb3729c0","glsl-optimizer/src/util/sha1/sha1.c":"1403bbe0aad42ba3e6be7e09f7cad87a6a8c4ad5b63962f7b92b9f37d8133b04","glsl-optimizer/src/util/sha1/sha1.h":"68d9f240eab2918026ecdf22be36811abbd4f1389f6c36e31258041aeaedd247","glsl-optimizer/src/util/simple_mtx.h":"12c6c3c4b7db9168bc656d5b3c65912075084d2b388c415d5c3d3f5953a9d6c7","glsl-optimizer/src/util/softfloat.c":"a97e51a96fe5e6a052c02aa6bbec683fe73fb88a8c087d9c930503e2120d8a2e","glsl-optimizer/src/util/softfloat.h":"66664b0250e83bf5dd4cc743acd119d076efcea624a0eab3d6b60718e6ee8811","glsl-optimizer/src/util/string_buffer.c":"63a1d1b1e34926c88ea00159cafbcd56568b805c4f64d1e8c97169fe313921fc","glsl-optimizer/src/util/string_buffer.h":"7b88d1b1d9c6cfb8e93331813535c127289437c75f822029e9a3bca8ea6b52ee","glsl-optimizer/src/util/strndup.h":"0273c4fdb7482cd7746881a63d3998648c6d63415ba85af1d1860f0e0dc504c6","glsl-optimizer/src/util/strtod.c":"5cf610d8a37373cf37cfb7aae903525d943b2674b1f32594c70b0eb19a8c9697","glsl-optimizer/src/util/strtod.h":"237396def4e264d35ed4bedea00ef9a4ceab6d7a11a18c770d9747d22c69ed2d","glsl-optimizer/src/util/u_atomic.h":"c02e809526c6c09ba8fe51f50b2490d1b6c8e5c7f3c4031ae958250d098fc3bb","glsl-optimizer/src/util/u_debug.c":"8c060e379b816618f3dd22c9ea523c68b9425c76c36a7dfe5d6d375b337f5f4a","glsl-optimizer/src/util/u_debug.h":"e11e26edd9b9e4e6f8e6a435e69f4d9edda27e9a379f68f4c82ea2525aaaea68","glsl-optimizer/src/util/u_dynarray.h":"853d0fa6ff2261614488be624deb8a2b01e57c2c8eabc28578cbeed4ccc95694","glsl-optimizer/src/util/u_endian.h":"420a4320adfc37f89cfbf761f289651600b773468f2f881a1f7e9afa377987f5","glsl-optimizer/src/util/u_math.c":"c868a8c0886dc78f1b06b13404ba8b253090449045774dd56893ac9d75795184","glsl-optimizer/src/util/u_math.h":"4f334f6cd005b5703e41fa145f761f882b7f3a15e61c3234773af4f4adde1036","glsl-optimizer/src/util/u_memory.h":"c5db17c724c70283ddbe04165722f6988d4e0eb9aa3602ae472feff016649af9","glsl-optimizer/src/util/u_queue.h":"92930ce236c0528a98b695f5cea8c5c6aa9683beaf71a2227bdc5d33d1b21506","glsl-optimizer/src/util/u_string.h":"c5a2f4ef576d1547bda12c4ea219179fefa54414977743ac094abcaf696ef6ca","glsl-optimizer/src/util/u_thread.h":"00b708459b27f9910d18db92c18cc65cfc618ac2b3cd144e45f8640057b10d58","glsl-optimizer/src/util/xxhash.h":"2f2aff2fc6c0c929f52cf6ae7314122124c5be026d41ad1c357608383c4a37ad","src/bindings.rs":"79993db2058bde39f99ef483d02560d33b1cb882f6a552319e8b86eb6f9021e1","src/lib.rs":"04be1554cd829eb40864b06d80b491dd48117a4e3a601c7d482117f7a0391e67","wrapper.hpp":"f3ea34cc496f7d90b9bfcada3250b37b314c3524dac693b2ece9517bc7d274ac"},"package":null}
\ No newline at end of file
+diff --git a/third_party/rust/glslopt/.gitmodules b/third_party/rust/glslopt/.gitmodules
+new file mode 100644
+index 0000000..dd75612
+--- /dev/null
++++ b/third_party/rust/glslopt/.gitmodules
+@@ -0,0 +1,3 @@
++[submodule "glsl-optimizer"]
++ path = glsl-optimizer
++ url = https://github.com/kenz-gelsoft/glsl-optimizer
diff --git a/third_party/rust/glslopt/Cargo.toml b/third_party/rust/glslopt/Cargo.toml
-index 206ad8f149..edf6a513f9 100644
+index 206ad8f..edf6a51 100644
--- a/third_party/rust/glslopt/Cargo.toml
+++ b/third_party/rust/glslopt/Cargo.toml
@@ -9,11 +9,21 @@
@@ -1095,8 +3828,77 @@ index 206ad8f149..edf6a513f9 100644
+
+[build-dependencies]
+cc = "1.0"
+diff --git a/third_party/rust/glslopt/glsl-optimizer/.editorconfig b/third_party/rust/glslopt/glsl-optimizer/.editorconfig
+new file mode 100644
+index 0000000..3f9e475
+--- /dev/null
++++ b/third_party/rust/glslopt/glsl-optimizer/.editorconfig
+@@ -0,0 +1,44 @@
++# To use this config on you editor, follow the instructions at:
++# http://editorconfig.org
++
++root = true
++
++[*]
++charset = utf-8
++insert_final_newline = true
++tab_width = 8
++
++[*.{c,h,cpp,hpp,cc,hh}]
++indent_style = space
++indent_size = 3
++max_line_length = 78
++
++[{Makefile*,*.mk}]
++indent_style = tab
++
++[{*.py,SCons*}]
++indent_style = space
++indent_size = 4
++
++[*.pl]
++indent_style = space
++indent_size = 4
++
++[*.m4]
++indent_style = space
++indent_size = 2
++
++[*.yml]
++indent_style = space
++indent_size = 2
++
++[*.html]
++indent_style = space
++indent_size = 2
++
++[*.patch]
++trim_trailing_whitespace = false
++
++[{meson.build,meson_options.txt}]
++indent_style = space
++indent_size = 2
+diff --git a/third_party/rust/glslopt/glsl-optimizer/.gitignore b/third_party/rust/glslopt/glsl-optimizer/.gitignore
+new file mode 100644
+index 0000000..825ad5f
+--- /dev/null
++++ b/third_party/rust/glslopt/glsl-optimizer/.gitignore
+@@ -0,0 +1,4 @@
++*.pyc
++*.pyo
++*.out
++build
+diff --git a/third_party/rust/glslopt/glsl-optimizer/include/c11/.editorconfig b/third_party/rust/glslopt/glsl-optimizer/include/c11/.editorconfig
+new file mode 100644
+index 0000000..bdbea00
+--- /dev/null
++++ b/third_party/rust/glslopt/glsl-optimizer/include/c11/.editorconfig
+@@ -0,0 +1,3 @@
++[*.h]
++indent_style = space
++indent_size = 4
diff --git a/third_party/rust/glslopt/glsl-optimizer/src/compiler/glsl/builtin_functions.cpp b/third_party/rust/glslopt/glsl-optimizer/src/compiler/glsl/builtin_functions.cpp
-index 3dafcf0c77..cc6fe4b64a 100644
+index 3dafcf0..cc6fe4b 100644
--- a/third_party/rust/glslopt/glsl-optimizer/src/compiler/glsl/builtin_functions.cpp
+++ b/third_party/rust/glslopt/glsl-optimizer/src/compiler/glsl/builtin_functions.cpp
@@ -735,7 +735,7 @@ fp64(const _mesa_glsl_parse_state *state)
@@ -1244,7 +4046,7 @@ index 3dafcf0c77..cc6fe4b64a 100644
FD(length)
FD(distance)
diff --git a/third_party/rust/glslopt/glsl-optimizer/src/util/u_endian.h b/third_party/rust/glslopt/glsl-optimizer/src/util/u_endian.h
-index 6bbae3c444..d1540e9769 100644
+index 6bbae3c..d1540e9 100644
--- a/third_party/rust/glslopt/glsl-optimizer/src/util/u_endian.h
+++ b/third_party/rust/glslopt/glsl-optimizer/src/util/u_endian.h
@@ -27,7 +27,7 @@
@@ -1257,7 +4059,7 @@ index 6bbae3c444..d1540e9769 100644
#if __BYTE_ORDER == __LITTLE_ENDIAN
diff --git a/third_party/rust/glslopt/glsl-optimizer/src/util/u_math.h b/third_party/rust/glslopt/glsl-optimizer/src/util/u_math.h
-index 42d9e348ec..240bd41d8c 100644
+index 42d9e34..240bd41 100644
--- a/third_party/rust/glslopt/glsl-optimizer/src/util/u_math.h
+++ b/third_party/rust/glslopt/glsl-optimizer/src/util/u_math.h
@@ -676,6 +676,9 @@ util_memcpy_cpu_to_le32(void * restrict dest, const void * restrict src, size_t
@@ -1271,7 +4073,7 @@ index 42d9e348ec..240bd41d8c 100644
* Align a value up to an alignment value
*
diff --git a/third_party/rust/lmdb-rkv-sys/.cargo-checksum.json b/third_party/rust/lmdb-rkv-sys/.cargo-checksum.json
-index 6ae8903fcf..9da8f7d189 100644
+index 6ae8903..9da8f7d 100644
--- a/third_party/rust/lmdb-rkv-sys/.cargo-checksum.json
+++ b/third_party/rust/lmdb-rkv-sys/.cargo-checksum.json
@@ -1 +1 @@
@@ -1279,8 +4081,18 @@ index 6ae8903fcf..9da8f7d189 100644
\ No newline at end of file
+{"files":{".rustfmt.toml":"fbef9d8f2ff25a0b6c6f032f2b066aedfd7b1d34d8f75e0be811bc087bff5469","Cargo.toml":"a111b0e819d64bea0f117d2f1f25c58692b2cc2e70859881bf4cdf89817d9af3","bindgen.rs":"4579cf8b217b9673fd08f8306bfe1b4bbac1b31cf11b2a395f81ddac04dfc10e","build.rs":"54abc550db966ce0479e1cf54ed992e3eca7e947357c54bf937b6048f0813c95","lmdb/libraries/liblmdb/.gitignore":"49e1a82819dab072b1c80d4570f817d6e2c6625d574df871f7a065ab44944727","lmdb/libraries/liblmdb/CHANGES":"ba14b94dda8670db454275d2f5fb83510f810ccb3ccfca642176a0efef245e08","lmdb/libraries/liblmdb/COPYRIGHT":"fae797823b892c4b59913256b4d10b17d71f57d4bc45e46d901b84fd6dfc3d13","lmdb/libraries/liblmdb/Doxyfile":"5545f6b049040ce58e6d1a603eaea6b7fb8ae92459f2ab8d3bcbacabcce1014d","lmdb/libraries/liblmdb/LICENSE":"310fe25c858a9515fc8c8d7d1f24a67c9496f84a91e0a0e41ea9975b1371e569","lmdb/libraries/liblmdb/Makefile":"60b5f574e6642602f692a95956da61c588a265ad50b8059960c230b9e6aaf4fd","lmdb/libraries/liblmdb/intro.doc":"9442e0db4fc9c70f058c43545e710476d8d5a80b959d20f4381240fd50c6b843","lmdb/libraries/liblmdb/lmdb.h":"05abf244b621b2d14e838b0643e72d5075ce77d8df856b6dccde74ee51c9cf22","lmdb/libraries/liblmdb/mdb.c":"3b23059962db42311f6811f60ce19730da5b51e1d263fa2f63d1be6f6b5ff490","lmdb/libraries/liblmdb/mdb_copy.1":"3a6a8a7a91e1bd42dc4d2a0188ff62d699ff2b3b097a670f30681decf63f22f3","lmdb/libraries/liblmdb/mdb_copy.c":"d3d412a770a5c3afeb88c44b4acdde0f0b985cde22497198e8f38296281cdddd","lmdb/libraries/liblmdb/mdb_dump.1":"9257be883c7fcfcbd61003cc730f7c0900fa8f6feba074c8c1e46634a257b13a","lmdb/libraries/liblmdb/mdb_dump.c":"b046cffcd997254e6daea47a2d7fb74f9d23282174cbb1e3bf9f5fb51a90fe64","lmdb/libraries/liblmdb/mdb_load.1":"ea927473245a4a7777ba687aa26baf7f0951fb620daf82b8d730a090185b2bbc","lmdb/libraries/liblmdb/mdb_load.c":"4f722613c65350315db23060be98584fb572978108885dab271101ba7187dca4","lmdb/libraries/liblmdb/mdb_stat.1":"c0a70d96b4b2d32e73301383d9d5620bc0bbbefb019bfd54f32088dfd4bc921a","lmdb/libraries/liblmdb/mdb_stat.c":"e6405fa191d784ecfa8eb8d1f153a58facc49a8f5a2c891a93802e67acc4861e","lmdb/libraries/liblmdb/midl.c":"e19143db51dd606396c7eba765832e4b66167c0975614e576b950349f8f6cdfd","lmdb/libraries/liblmdb/midl.h":"52066a085aa0fc90799113fb1cc60ca78a5e35ca6191f5f5cb29488d4bd66dba","lmdb/libraries/liblmdb/mtest.c":"89ab9ac8bf1e14a9f32a33757c4b3254e4984e0f24e5a302e2d126eb2c86f6db","lmdb/libraries/liblmdb/mtest2.c":"076b00395fe1461dd9577f7bb5567908ce50cf470efbf652787e6fe1dc2fb68c","lmdb/libraries/liblmdb/mtest3.c":"51b9a055e123bd0757ee3082cc6864c836969cf630e646a9cc34e01398c20634","lmdb/libraries/liblmdb/mtest4.c":"b0a725405d80bda6ab95b3ecf410ae330ab8df7a081ca81dd6ea1f8db87642e9","lmdb/libraries/liblmdb/mtest5.c":"7f3b06ca3833315ea4c70d5e91feb1b677f6949f105f4f89d96c3ac35e104f2f","lmdb/libraries/liblmdb/mtest6.c":"e4d7880c36547ebf33bc020046730bf2c075c53aaacd5c876152cc5ae7ab5e6c","lmdb/libraries/liblmdb/sample-bdb.txt":"153d84f8fc49a3abba53ed52d5a41c8d6d4698753a10bbe0689a9e65d3513513","lmdb/libraries/liblmdb/sample-mdb.txt":"1f77385786cffdf72b33da06a91a444fe2827673c3627f89110903a8fe012795","lmdb/libraries/liblmdb/tooltag":"4734c6dc1fa7aec8c2e9646bd04bc5218ef6a03ad83a3b18de2ac4069eb94120","src/bindings.rs":"ab64073ce4ec64282e8f67cd8f148c83661810a662cb804813b3add0d92a4bf6","src/lib.rs":"e0cf0afbab6dfded166e11d492b66d5701efe07ef978c386060054bd09f7e0c8","tests/fixtures/testdb-32/data.mdb":"74d09a30a020789631ef5c64d60d34f6913cf63ad73c82327bd605c5a37849bb","tests/fixtures/testdb-32/lock.mdb":"bbfd0f5aa3eea8421b0a2c277de69b105789dbc744391d9a08d0d3332ae91f70","tests/fixtures/testdb/data.mdb":"8a0cf8ad63473ae63d437a646042b0d64c112a8fa33d5c916f0678ce4d23189b","tests/fixtures/testdb/lock.mdb":"6ef7eea0c15b42835891c2d1d62905cfca7ae018572971610600196714858f53","tests/lmdb.rs":"5086cb43f3a7b6a8aaa257084c1e0bea664f279ff260b99a8ad0d3c598867a45","tests/simple.rs":"774a3edf589dd5fab3b90d5faabb8b8e06e51ec231a795ba17b1e35e65490848"},"package":null}
\ No newline at end of file
+diff --git a/third_party/rust/lmdb-rkv-sys/.rustfmt.toml b/third_party/rust/lmdb-rkv-sys/.rustfmt.toml
+new file mode 100644
+index 0000000..fc441bb
+--- /dev/null
++++ b/third_party/rust/lmdb-rkv-sys/.rustfmt.toml
+@@ -0,0 +1,3 @@
++ignore = [
++ "src/bindings.rs"
++]
+\ No newline at end of file
diff --git a/third_party/rust/lmdb-rkv-sys/Cargo.toml b/third_party/rust/lmdb-rkv-sys/Cargo.toml
-index e8f59d983f..6843f92136 100644
+index e8f59d9..6843f92 100644
--- a/third_party/rust/lmdb-rkv-sys/Cargo.toml
+++ b/third_party/rust/lmdb-rkv-sys/Cargo.toml
@@ -9,36 +9,65 @@
@@ -1368,1195 +4180,9 @@ index e8f59d983f..6843f92136 100644
[badges.appveyor]
repository = "mozilla/lmdb-rs"
-diff --git a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
-index 01741d0755..ad4f34dba1 100644
---- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
-+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
-@@ -123,7 +123,7 @@ typedef SSIZE_T ssize_t;
- #include /* defines BYTE_ORDER on HPUX and Solaris */
- #endif
-
--#if defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__)
-+#if defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
- # define MDB_USE_POSIX_SEM 1
- # define MDB_FDATASYNC fsync
- #elif defined(__ANDROID__)
-@@ -256,7 +256,7 @@ typedef SSIZE_T ssize_t;
- */
- #ifndef MDB_USE_ROBUST
- /* Android currently lacks Robust Mutex support. So does glibc < 2.4. */
--# if defined(MDB_USE_POSIX_MUTEX) && (defined(__ANDROID__) || \
-+# if defined(MDB_USE_POSIX_MUTEX) && (defined(__ANDROID__) || defined(__HAIKU__) || \
- (defined(__GLIBC__) && GLIBC_VER < 0x020004))
- # define MDB_USE_ROBUST 0
- # else
-diff --git a/toolkit/components/processtools/moz.build b/toolkit/components/processtools/moz.build
-index ee9d07cd6d..0b44d4c271 100644
---- a/toolkit/components/processtools/moz.build
-+++ b/toolkit/components/processtools/moz.build
-@@ -43,6 +43,8 @@ if toolkit == "gtk" or toolkit == "android":
- UNIFIED_SOURCES += ["ProcInfo_bsd.cpp"]
- elif CONFIG["OS_TARGET"] == "SunOS":
- UNIFIED_SOURCES += ["ProcInfo_solaris.cpp"]
-+ elif CONFIG["OS_TARGET"] == "Haiku":
-+ UNIFIED_SOURCES += ["ProcInfo_haiku.cpp"]
- else:
- UNIFIED_SOURCES += ["ProcInfo_linux.cpp"]
- elif toolkit == "windows":
-diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build
-index f6d0df2e56..eb6ac51621 100644
---- a/toolkit/library/moz.build
-+++ b/toolkit/library/moz.build
-@@ -340,6 +340,10 @@ if CONFIG["OS_ARCH"] == "Darwin":
- "-weak_framework MediaPlayer",
- ]
-
-+if CONFIG["OS_ARCH"] == "Haiku":
-+ OS_LIBS += [
-+ "be",
-+ ]
-
- if CONFIG["OS_ARCH"] == "WINNT":
- OS_LIBS += [
-diff --git a/toolkit/library/rust/moz.build b/toolkit/library/rust/moz.build
-index 0926e21a5b..da8ff80633 100644
---- a/toolkit/library/rust/moz.build
-+++ b/toolkit/library/rust/moz.build
-@@ -8,6 +8,12 @@ include("gkrust-features.mozbuild")
-
- RustLibrary("gkrust", gkrust_features, is_gkrust=True)
-
-+if CONFIG["OS_ARCH"] == "Haiku":
-+ # Rust 1.83+ requires arc4random_buf()
-+ OS_LIBS += [
-+ "bsd"
-+ ]
-+
- for feature in gkrust_features:
- # We don't want to enable refcount logging during rusttests, since the
- # relevant FFI symbols wouldn't be found.
-diff --git a/toolkit/modules/ShortcutUtils.sys.mjs b/toolkit/modules/ShortcutUtils.sys.mjs
-index 3632c52e69..5b56b1998c 100644
---- a/toolkit/modules/ShortcutUtils.sys.mjs
-+++ b/toolkit/modules/ShortcutUtils.sys.mjs
-@@ -63,7 +63,7 @@ export var ShortcutUtils = {
- let elemString = "";
- let haveCloverLeaf = false;
- if (elemMod.match("accel")) {
-- if (Services.appinfo.OS == "Darwin") {
-+ if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Haiku") {
- haveCloverLeaf = true;
- } else {
- elemString +=
-@@ -72,7 +72,7 @@ export var ShortcutUtils = {
- }
- }
- if (elemMod.match("access")) {
-- if (Services.appinfo.OS == "Darwin") {
-+ if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Haiku") {
- elemString +=
- lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-@@ -93,14 +93,26 @@ export var ShortcutUtils = {
- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
- }
- if (elemMod.match("alt")) {
-- elemString +=
-- lazy.PlatformKeys.GetStringFromName("VK_ALT") +
-- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ if (Services.appinfo.OS == "Haiku") {
-+ elemString +=
-+ lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
-+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ } else {
-+ elemString +=
-+ lazy.PlatformKeys.GetStringFromName("VK_ALT") +
-+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ }
- }
- if (elemMod.match("ctrl") || elemMod.match("control")) {
-- elemString +=
-- lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
-- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ if (Services.appinfo.OS == "Haiku") {
-+ elemString +=
-+ lazy.PlatformKeys.GetStringFromName("VK_ALT") +
-+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ } else {
-+ elemString +=
-+ lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
-+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ }
- }
- if (elemMod.match("meta") && this.metaKeyIsCommandKey()) {
- elemString +=
-@@ -109,9 +121,15 @@ export var ShortcutUtils = {
- }
-
- if (haveCloverLeaf) {
-- elemString +=
-- lazy.PlatformKeys.GetStringFromName("VK_COMMAND_OR_WIN") +
-- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ if (Services.appinfo.OS == "Haiku") {
-+ elemString +=
-+ lazy.PlatformKeys.GetStringFromName("VK_ALT") +
-+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ } else {
-+ elemString +=
-+ lazy.PlatformKeys.GetStringFromName("VK_COMMAND_OR_WIN") +
-+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
-+ }
- }
-
- return elemString;
-diff --git a/toolkit/moz.configure b/toolkit/moz.configure
-index 9e191e0c30..cc77fab25c 100644
---- a/toolkit/moz.configure
-+++ b/toolkit/moz.configure
-@@ -217,6 +217,8 @@ def audio_backends_default(target):
- return ("sndio",)
- elif target.kernel == "Darwin":
- return ("audiounit",)
-+ elif target.os == "Haiku":
-+ return ("haiku",)
- elif target.os == "NetBSD":
- return ("sunaudio",)
- elif target.os == "SunOS":
-@@ -234,6 +236,7 @@ option(
- "aaudio",
- "alsa",
- "audiounit",
-+ "haiku",
- "jack",
- "opensl",
- "oss",
-@@ -272,6 +275,11 @@ def imply_audiounit(values, target):
- return any("audiounit" in value for value in values) or None
-
-
-+@depends("--enable-audio-backends")
-+def imply_haiku(values):
-+ return any("haiku" in value for value in values) or None
-+
-+
- @depends("--enable-audio-backends")
- def imply_jack(values):
- return any("jack" in value for value in values) or None
-@@ -335,6 +343,8 @@ imply_option(
-
- set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
-
-+set_config("MOZ_HAIKU", imply_haiku, when="--enable-audio-backends")
-+
- imply_option(
- "--enable-jack", imply_jack, reason="--enable-audio-backends", when=use_pkg_config
- )
-@@ -2940,6 +2950,7 @@ def forkserver_default(target, build_project):
- (target.os == "GNU" and target.kernel == "Linux")
- or target.os == "FreeBSD"
- or target.os == "OpenBSD"
-+ or target.os == "Haiku"
- )
-
-
-@@ -3434,7 +3445,7 @@ with only_when(compile_environment):
-
- @depends(target)
- def default_user_appdir(target):
-- if target.kernel in ("WINNT", "Darwin"):
-+ if target.kernel in ("WINNT", "Darwin", "Haiku"):
- return "Mozilla"
- return ".mozilla"
-
-diff --git a/toolkit/system/gnome/nsGIOService.cpp b/toolkit/system/gnome/nsGIOService.cpp
-index d02560b68f..d8363556ad 100644
---- a/toolkit/system/gnome/nsGIOService.cpp
-+++ b/toolkit/system/gnome/nsGIOService.cpp
-@@ -300,6 +300,32 @@ gboolean g_app_info_launch_default_for_uri_openbsd(const char* uri,
- }
- #endif
-
-+#ifdef __HAIKU__
-+
-+gboolean g_app_info_launch_uris_haiku(GAppInfo* mApp, const char* uri,
-+ GAppLaunchContext* context,
-+ GError** error) {
-+ gchar* command = g_strdup_printf("open '%s'", uri);
-+ auto releaseCommand = MakeScopeExit([&] { g_free(command); });
-+
-+ int result = system(command);
-+
-+ if (result != 0) {
-+ g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
-+ "Failed to open URI '%s' using 'open' utility", uri);
-+ return FALSE;
-+ }
-+ return TRUE;
-+}
-+
-+gboolean g_app_info_launch_default_for_uri_haiku(const char* uri,
-+ GAppLaunchContext* context,
-+ GError** error) {
-+ return g_app_info_launch_uris_haiku(NULL, uri, context, error);
-+}
-+
-+#endif // __HAIKU__
-+
- static NS_IMETHODIMP LaunchWithURIImpl(RefPtr aInfo, nsIURI* aUri,
- const char* aXDGToken = nullptr) {
- GList uris = {0};
-@@ -313,6 +339,10 @@ static NS_IMETHODIMP LaunchWithURIImpl(RefPtr aInfo, nsIURI* aUri,
- gboolean result = g_app_info_launch_uris_openbsd(
- aInfo, spec.get(), GetLaunchContext(aXDGToken).get(),
- getter_Transfers(error));
-+#elif defined(__HAIKU__)
-+ gboolean result = g_app_info_launch_uris_haiku(
-+ aInfo, spec.get(), GetLaunchContext(aXDGToken).get(),
-+ getter_Transfers(error));
- #else
- gboolean result = g_app_info_launch_uris(
- aInfo, &uris, GetLaunchContext(aXDGToken).get(), getter_Transfers(error));
-@@ -640,6 +670,9 @@ static nsresult ShowURIImpl(nsIURI* aURI, const char* aXDGToken = nullptr) {
- #ifdef __OpenBSD__
- if (!g_app_info_launch_default_for_uri_openbsd(
- spec.get(), GetLaunchContext(aXDGToken).get(),
-+#elif defined(__HAIKU__)
-+ if (!g_app_info_launch_default_for_uri_haiku(
-+ spec.get(), GetLaunchContext(aXDGToken).get(),
- #else
- if (!g_app_info_launch_default_for_uri(spec.get(),
- GetLaunchContext(aXDGToken).get(),
-@@ -675,6 +708,9 @@ static nsresult LaunchPathImpl(const nsACString& aPath,
- #ifdef __OpenBSD__
- g_app_info_launch_default_for_uri_openbsd(spec.get(),
- GetLaunchContext(aXDGToken).get(),
-+#elif defined(__HAIKU__)
-+ g_app_info_launch_default_for_uri_haiku(spec.get(),
-+ GetLaunchContext(aXDGToken).get(),
- #else
- g_app_info_launch_default_for_uri(spec.get(),
- GetLaunchContext(aXDGToken).get(),
-diff --git a/toolkit/themes/shared/popup.css b/toolkit/themes/shared/popup.css
-index ed23086021..f10ce891bc 100644
---- a/toolkit/themes/shared/popup.css
-+++ b/toolkit/themes/shared/popup.css
-@@ -43,6 +43,12 @@ panel {
- --panel-shadow-margin: 4px;
- }
-
-+ /* Disable border-radius and shadow for Haiku popups */
-+ @media (-moz-platform: linux) {
-+ --panel-border-radius: 0px;
-+ --panel-shadow-margin: 0px;
-+ }
-+
- @media (-moz-platform: macos) {
- appearance: auto;
- -moz-default-appearance: menupopup;
-diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
-index eb1781b1e7..4776195b19 100644
---- a/toolkit/xre/nsAppRunner.cpp
-+++ b/toolkit/xre/nsAppRunner.cpp
-@@ -347,14 +347,16 @@ nsString gProcessStartupShortcut;
- # ifdef MOZ_WAYLAND
- # include
- # include "mozilla/widget/nsWaylandDisplay.h"
--# include "wayland-proxy.h"
-+# ifndef XP_HAIKU
-+# include "wayland-proxy.h"
-+# endif /* !XP_HAIKU */
- # endif
- # ifdef MOZ_X11
- # include
- # endif /* MOZ_X11 */
- #endif
-
--#if defined(MOZ_WAYLAND)
-+#if defined(MOZ_WAYLAND) && !defined(XP_HAIKU)
- std::unique_ptr gWaylandProxy;
- #endif
-
-@@ -439,6 +441,9 @@ static void UnexpectedExit() {
-
- #if defined(MOZ_WAYLAND)
- bool IsWaylandEnabled() {
-+#ifdef XP_HAIKU
-+ return true;
-+#else
- static bool isWaylandEnabled = []() {
- const char* waylandDisplay = PR_GetEnv("WAYLAND_DISPLAY");
- if (!waylandDisplay) {
-@@ -469,6 +474,7 @@ bool IsWaylandEnabled() {
- return !gtk_check_version(3, 24, 30);
- }();
- return isWaylandEnabled;
-+#endif // !XP_HAIKU
- }
- #else
- bool IsWaylandEnabled() { return false; }
-@@ -3726,7 +3732,7 @@ class XREMain {
- #endif
- };
-
--#if defined(XP_UNIX) && !defined(ANDROID)
-+#if defined(XP_UNIX) && !defined(ANDROID) && !defined(XP_HAIKU)
- static SmprintfPointer FormatUid(uid_t aId) {
- if (const auto pw = getpwuid(aId)) {
- return mozilla::Smprintf("%s", pw->pw_name);
-@@ -3775,7 +3781,7 @@ static bool CheckForUserMismatch() {
- }
- return false;
- }
--#else // !XP_UNIX || ANDROID
-+#else // !XP_UNIX || ANDROID || XP_HAIKU
- static bool CheckForUserMismatch() { return false; }
- #endif
-
-@@ -4765,7 +4771,7 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
- // display_name is owned by gdk.
- display_name = gdk_get_display_arg_name();
- bool waylandEnabled = IsWaylandEnabled();
--# ifdef MOZ_WAYLAND
-+# if defined(MOZ_WAYLAND) && !defined(XP_HAIKU)
- if (!display_name) {
- auto* proxyEnv = getenv("MOZ_DISABLE_WAYLAND_PROXY");
- bool disableWaylandProxy = proxyEnv && *proxyEnv;
-@@ -4817,7 +4823,7 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
- } else {
- gdk_display_manager_open_display(gdk_display_manager_get(), nullptr);
- }
--# if defined(MOZ_WAYLAND)
-+# if defined(MOZ_WAYLAND) && !defined(XP_HAIKU)
- // We want to use proxy for main connection only so
- // restore original Wayland display for next potential Wayland connections
- // from gfx probe code and so on.
-@@ -6052,7 +6058,9 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
- if (!gfxPlatform::IsHeadless()) {
- # ifdef MOZ_WAYLAND
- WaylandDisplayRelease();
-+# ifndef XP_HAIKU
- gWaylandProxy = nullptr;
-+# endif // !XP_HAIKU
- # endif
- }
- #endif
-diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
-index d3af49b495..1713fe1ad2 100644
---- a/toolkit/xre/nsXREDirProvider.cpp
-+++ b/toolkit/xre/nsXREDirProvider.cpp
-@@ -79,6 +79,10 @@
- #ifdef XP_IOS
- # include "UIKitDirProvider.h"
- #endif
-+#ifdef XP_HAIKU
-+# include
-+# include
-+#endif
-
- #if defined(MOZ_CONTENT_TEMP_DIR)
- # include "mozilla/SandboxSettings.h"
-@@ -380,7 +384,7 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
- } else if (!strcmp(aProperty, XRE_USER_NATIVE_MANIFESTS)) {
- rv = GetUserDataDirectoryHome(getter_AddRefs(file), false);
- NS_ENSURE_SUCCESS(rv, rv);
--# if defined(XP_MACOSX)
-+# if defined(XP_MACOSX) || defined(XP_HAIKU)
- rv = file->AppendNative("Mozilla"_ns);
- # else // defined(XP_MACOSX)
- rv = file->AppendNative(".mozilla"_ns);
-@@ -1287,6 +1291,12 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
-+#elif defined(XP_HAIKU)
-+ BPath settingsDir;
-+ status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &settingsDir);
-+ if (status != B_OK) return NS_ERROR_FAILURE;
-+ rv = NS_NewNativeLocalFile(nsDependentCString(settingsDir.Path()), true,
-+ getter_AddRefs(localDir));
- #elif defined(XP_UNIX)
- const char* homeDir = getenv("HOME");
- if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
-@@ -1396,7 +1406,7 @@ nsresult nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile) {
-
- nsresult rv;
-
--#if defined(XP_MACOSX) || defined(XP_WIN)
-+#if defined(XP_MACOSX) || defined(XP_WIN) || defined(XP_HAIKU)
-
- static const char* const sXR = "Mozilla";
- rv = aFile->AppendNative(nsDependentCString(sXR));
-@@ -1455,7 +1465,7 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
- }
- NS_ENSURE_SUCCESS(rv, rv);
-
--#elif defined(XP_WIN)
-+#elif defined(XP_WIN) || defined(XP_HAIKU)
- if (!profile.IsEmpty()) {
- rv = AppendProfileString(aFile, profile.get());
- } else {
-diff --git a/tools/profiler/core/ProfilerUtils.cpp b/tools/profiler/core/ProfilerUtils.cpp
-index 4c5306114f..76d3561dab 100644
---- a/tools/profiler/core/ProfilerUtils.cpp
-+++ b/tools/profiler/core/ProfilerUtils.cpp
-@@ -88,6 +88,15 @@ ProfilerThreadId profiler_current_thread_id() {
- return ProfilerThreadId::FromNativeId(id);
- }
-
-+// ------------------------------------------------------- Haiku
-+# elif defined(XP_HAIKU)
-+
-+# include
-+
-+ProfilerThreadId profiler_current_thread_id() {
-+ return ProfilerThreadId::FromNativeId(find_thread(NULL));
-+}
-+
- // ------------------------------------------------------- Others
- # else
-
-diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build
-index 6ced9be06e..24bcf547f8 100644
---- a/widget/gtk/moz.build
-+++ b/widget/gtk/moz.build
-@@ -23,7 +23,9 @@ if CONFIG["COMPILE_ENVIRONMENT"]:
- DIRS += ["mozgtk"]
-
- if CONFIG["MOZ_WAYLAND"]:
-- DIRS += ["wayland", "mozwayland", "../../third_party/wayland-proxy"]
-+ DIRS += ["wayland", "mozwayland"]
-+ if CONFIG["OS_ARCH"] != "Haiku":
-+ DIRS += ["../../third_party/wayland-proxy"]
-
- if CONFIG["MOZ_ENABLE_VAAPI"]:
- DIRS += ["vaapitest"]
-diff --git a/xpcom/base/nsSystemInfo.cpp b/xpcom/base/nsSystemInfo.cpp
-index 8bfd6577b3..093a6e3a5d 100644
---- a/xpcom/base/nsSystemInfo.cpp
-+++ b/xpcom/base/nsSystemInfo.cpp
-@@ -80,6 +80,10 @@
- # include "mozilla/SandboxInfo.h"
- #endif
-
-+#ifdef XP_HAIKU
-+# include
-+#endif
-+
- // Slot for NS_InitXPCOM to pass information to nsSystemInfo::Init.
- // Only set to nonzero (potentially) if XP_UNIX. On such systems, the
- // system call to discover the appropriate value is not thread-safe,
-@@ -1355,7 +1359,15 @@ nsresult nsSystemInfo::Init() {
- SetInt32Property(u"pagesize"_ns, PR_GetPageSize());
- SetInt32Property(u"pageshift"_ns, PR_GetPageShift());
- SetInt32Property(u"memmapalign"_ns, PR_GetMemMapAlignment());
-+#ifdef XP_HAIKU
-+ { // workaround
-+ system_info info;
-+ get_system_info(&info);
-+ SetUint64Property(u"memsize"_ns, info.max_pages * B_PAGE_SIZE);
-+ }
-+#else
- SetUint64Property(u"memsize"_ns, PR_GetPhysicalMemorySize());
-+#endif
- SetUint32Property(u"umask"_ns, nsSystemInfo::gUserUmask);
-
- #ifdef HAVE_64BIT_BUILD
-diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h
-index 47bd6940cb..8adc538b3e 100644
---- a/xpcom/build/BinaryPath.h
-+++ b/xpcom/build/BinaryPath.h
-@@ -24,6 +24,10 @@
- #if defined(__OpenBSD__)
- # include
- #endif
-+#if defined(XP_HAIKU)
-+# include
-+# include
-+#endif
- #include "mozilla/UniquePtr.h"
- #include "mozilla/UniquePtrExtensions.h"
-
-@@ -273,6 +277,21 @@ class BinaryPath {
- return NS_ERROR_FAILURE;
- }
-
-+#elif defined(XP_HAIKU)
-+ static nsresult Get(char aResult[MAXPATHLEN]) {
-+ image_info info;
-+ int32 cookie = 0;
-+
-+ while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) >= B_OK) {
-+ if (info.type == B_APP_IMAGE) {
-+ strlcpy(aResult, info.name, MAXPATHLEN - 1);
-+ return NS_OK;
-+ }
-+ }
-+
-+ return NS_ERROR_FAILURE;
-+ }
-+
- #else
- # error Oops, you need platform-specific code here
- #endif
-diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build
-index 6b566f9fdc..2895ad9d1d 100644
---- a/xpcom/reflect/xptcall/md/unix/moz.build
-+++ b/xpcom/reflect/xptcall/md/unix/moz.build
-@@ -33,6 +33,7 @@ if CONFIG["OS_ARCH"] in (
- "Bitrig",
- "DragonFly",
- "FreeBSD",
-+ "Haiku",
- "NetBSD",
- "OpenBSD",
- "SunOS",
-diff --git a/xpcom/threads/nsProcessCommon.cpp b/xpcom/threads/nsProcessCommon.cpp
-index dbd9993f54..1431340cb7 100644
---- a/xpcom/threads/nsProcessCommon.cpp
-+++ b/xpcom/threads/nsProcessCommon.cpp
-@@ -43,7 +43,11 @@
- # include "base/process_util.h"
- # endif
- # include
--# include
-+# ifdef XP_HAIKU
-+# include
-+# else
-+# include
-+# endif
- # endif
- # include
- # include
-diff --git a/media/libcubeb/src/cubeb_haiku.cpp b/media/libcubeb/src/cubeb_haiku.cpp
-new file mode 100644
-index 0000000000..700f826bc7
---- /dev/null
-+++ b/media/libcubeb/src/cubeb_haiku.cpp
-@@ -0,0 +1,468 @@
-+/*
-+ * Copyright © 2024 Troeglazov Gerasim
-+ *
-+ * This program is made available under an ISC-style license. See the
-+ * accompanying file LICENSE for details.
-+ */
-+
-+#include "cubeb-internal.h"
-+#include "cubeb/cubeb.h"
-+#include "cubeb_utils.h"
-+#include
-+#include
-+#include
-+
-+// Workaround for gcc_hidden.h hack of libxul.so
-+#pragma GCC visibility push(default)
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#pragma GCC visibility pop
-+
-+static const int MAX_CHANNELS = 2;
-+static const char DEFAULT_CONTEXT_NAME[] = "Cubeb";
-+
-+extern "C" {
-+int haiku_init(cubeb ** context, char const * context_name);
-+}
-+static void haiku_destroy(cubeb* context);
-+static char const* haiku_get_backend_id(cubeb* context);
-+static int haiku_get_max_channel_count(cubeb* ctx, uint32_t* max_channels);
-+static int haiku_get_min_latency(cubeb* ctx, cubeb_stream_params params, uint32_t* latency_frames);
-+static int haiku_get_preferred_sample_rate(cubeb* ctx, uint32_t* rate);
-+static int haiku_stream_init(cubeb* context,
-+ cubeb_stream** stream,
-+ char const* stream_name,
-+ cubeb_devid input_device,
-+ cubeb_stream_params* input_stream_params,
-+ cubeb_devid output_device,
-+ cubeb_stream_params* output_stream_params,
-+ unsigned int latency_frames,
-+ cubeb_data_callback data_callback,
-+ cubeb_state_callback state_callback,
-+ void* user_ptr);
-+static void haiku_stream_destroy(cubeb_stream* stream);
-+static int haiku_stream_start(cubeb_stream* stream);
-+static int haiku_stream_stop(cubeb_stream* stream);
-+static int haiku_stream_get_position(cubeb_stream* stream, uint64_t* position);
-+static int haiku_stream_get_latency(cubeb_stream* stream, uint32_t* latency_frames);
-+static int haiku_stream_set_volume(cubeb_stream* stream, float volume);
-+static int haiku_stream_get_current_device(cubeb_stream* stream, cubeb_device** const device);
-+static int haiku_stream_device_destroy(cubeb_stream* stream, cubeb_device* device);
-+static int haiku_enumerate_devices(cubeb* context, cubeb_device_type type, cubeb_device_collection* collection);
-+static int haiku_device_collection_destroy(cubeb* context, cubeb_device_collection* collection);
-+
-+static struct cubeb_ops const cubeb_haiku_ops = {
-+ .init = haiku_init,
-+ .get_backend_id = haiku_get_backend_id,
-+ .get_max_channel_count = haiku_get_max_channel_count,
-+ .get_min_latency = haiku_get_min_latency,
-+ .get_preferred_sample_rate = haiku_get_preferred_sample_rate,
-+ .get_supported_input_processing_params = NULL,
-+ .enumerate_devices = haiku_enumerate_devices,
-+ .device_collection_destroy = haiku_device_collection_destroy,
-+ .destroy = haiku_destroy,
-+ .stream_init = haiku_stream_init,
-+ .stream_destroy = haiku_stream_destroy,
-+ .stream_start = haiku_stream_start,
-+ .stream_stop = haiku_stream_stop,
-+ .stream_get_position = haiku_stream_get_position,
-+ .stream_get_latency = haiku_stream_get_latency,
-+ .stream_get_input_latency = NULL,
-+ .stream_set_volume = haiku_stream_set_volume,
-+ .stream_set_name = NULL,
-+ .stream_get_current_device = haiku_stream_get_current_device,
-+ .stream_set_input_mute = NULL,
-+ .stream_set_input_processing_params = NULL,
-+ .stream_device_destroy = haiku_stream_device_destroy,
-+ .stream_register_device_changed_callback = NULL,
-+ .register_device_collection_changed = NULL,
-+};
-+
-+struct cubeb_stream {
-+ /* Note: Must match cubeb_stream layout in cubeb.c. */
-+ cubeb* context;
-+ void* user_ptr;
-+ /**/
-+
-+ pthread_mutex_t mutex;
-+
-+ cubeb_data_callback data_callback;
-+ cubeb_state_callback state_callback;
-+ cubeb_stream_params params;
-+
-+ uint64_t position;
-+ bool pause;
-+
-+ float volume;
-+
-+ BSoundPlayer* sound_player;
-+ media_raw_audio_format format;
-+
-+ char stream_name[256];
-+};
-+
-+struct cubeb {
-+ struct cubeb_ops const* ops;
-+ pthread_mutex_t mutex;
-+
-+ bool active;
-+ uint32_t sample_rate;
-+ uint32_t latency;
-+
-+ char context_name[256];
-+};
-+
-+static void
-+haiku_audio_callback(void* cookie, void* buffer, size_t size, const media_raw_audio_format& format)
-+{
-+ cubeb_stream* stm = static_cast(cookie);
-+
-+ if (buffer == nullptr || cookie == nullptr)
-+ return;
-+
-+ if (stm->pause) {
-+ memset(buffer, 0, size);
-+ return;
-+ }
-+
-+ if (pthread_mutex_trylock(&stm->mutex) != 0) {
-+ memset(buffer, 0, size);
-+ return;
-+ }
-+
-+ long frames = size / format.channel_count;
-+ switch (format.format) {
-+ case media_raw_audio_format::B_AUDIO_FLOAT:
-+ frames /= sizeof(float);
-+ break;
-+ case media_raw_audio_format::B_AUDIO_SHORT:
-+ frames /= sizeof(int16_t);
-+ break;
-+ }
-+
-+ long got = stm->data_callback(stm, stm->user_ptr, nullptr, buffer, frames);
-+
-+ if (got < 0) {
-+ memset(buffer, 0, size);
-+ pthread_mutex_unlock(&stm->mutex);
-+ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
-+ return;
-+ }
-+
-+ stm->position += got;
-+ pthread_mutex_unlock(&stm->mutex);
-+}
-+
-+static media_raw_audio_format
-+cubeb_format_to_haiku(cubeb_stream_params *params)
-+{
-+ media_raw_audio_format format;
-+
-+ format.frame_rate = params->rate;
-+ format.channel_count = params->channels;
-+ format.buffer_size = 2048;
-+ format.byte_order = B_MEDIA_HOST_ENDIAN;
-+
-+ switch (params->format) {
-+ case CUBEB_SAMPLE_FLOAT32NE:
-+ format.format = media_raw_audio_format::B_AUDIO_FLOAT;
-+ break;
-+ case CUBEB_SAMPLE_S16NE:
-+ format.format = media_raw_audio_format::B_AUDIO_SHORT;
-+ break;
-+ default:
-+ format.format = media_raw_audio_format::B_AUDIO_FLOAT;
-+ break;
-+ }
-+
-+ return format;
-+}
-+
-+int
-+haiku_init(cubeb** context, char const* context_name)
-+{
-+ *context = NULL;
-+
-+ cubeb* ctx = (cubeb*)calloc(1, sizeof(*ctx));
-+ if (!ctx) {
-+ return CUBEB_ERROR;
-+ }
-+
-+ ctx->ops = &cubeb_haiku_ops;
-+ ctx->mutex = PTHREAD_MUTEX_INITIALIZER;
-+
-+ ctx->active = true;
-+ ctx->sample_rate = 48000;
-+ ctx->latency = 128;
-+ if (context_name)
-+ snprintf(ctx->context_name, 255, "%s", context_name);
-+ else
-+ snprintf(ctx->context_name, 255, "%s", DEFAULT_CONTEXT_NAME);
-+
-+ *context = ctx;
-+ return CUBEB_OK;
-+}
-+
-+static void
-+haiku_destroy(cubeb* context)
-+{
-+ context->active = false;
-+ free(context);
-+}
-+
-+static char const*
-+haiku_get_backend_id(cubeb* context)
-+{
-+ return "haiku";
-+}
-+
-+static int
-+haiku_get_max_channel_count(cubeb* ctx, uint32_t* max_channels)
-+{
-+ *max_channels = MAX_CHANNELS;
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_get_min_latency(cubeb* ctx, cubeb_stream_params params, uint32_t* latency_frames)
-+{
-+ *latency_frames = 128;
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_get_preferred_sample_rate(cubeb* ctx, uint32_t* rate)
-+{
-+ *rate = 48000;
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_stream_init(cubeb* context,
-+ cubeb_stream** stream,
-+ char const* stream_name,
-+ cubeb_devid input_device,
-+ cubeb_stream_params* input_stream_params,
-+ cubeb_devid output_device,
-+ cubeb_stream_params* output_stream_params,
-+ unsigned int latency_frames,
-+ cubeb_data_callback data_callback,
-+ cubeb_state_callback state_callback,
-+ void* user_ptr)
-+{
-+ if (!output_stream_params) {
-+ return CUBEB_ERROR_INVALID_PARAMETER;
-+ }
-+
-+ *stream = NULL;
-+
-+ pthread_mutex_lock(&context->mutex);
-+
-+ cubeb_stream* stm = reinterpret_cast(calloc(1, sizeof(*stm)));
-+
-+ if (!stm) {
-+ pthread_mutex_unlock(&context->mutex);
-+ return CUBEB_ERROR;
-+ }
-+
-+ stm->mutex = PTHREAD_MUTEX_INITIALIZER;
-+ if (stream_name) {
-+ if (strcmp(stream_name, "AudioStream") == 0) {
-+ snprintf(stm->stream_name, 255, "%s", context->context_name);
-+ } else {
-+ snprintf(stm->stream_name, 255, "%s", stream_name);
-+ }
-+ } else {
-+ snprintf(stm->stream_name, 255, "%s", context->context_name);
-+ }
-+
-+ pthread_mutex_unlock(&context->mutex);
-+
-+ pthread_mutex_lock(&stm->mutex);
-+
-+ stm->context = context;
-+ stm->user_ptr = user_ptr;
-+ stm->params = *output_stream_params;
-+ stm->data_callback = data_callback;
-+ stm->state_callback = state_callback;
-+ stm->position = 0;
-+ stm->volume = 1.0f;
-+ stm->format = cubeb_format_to_haiku(output_stream_params);
-+ stm->sound_player = nullptr;
-+
-+ *stream = stm;
-+ pthread_mutex_unlock(&stm->mutex);
-+
-+ return CUBEB_OK;
-+}
-+
-+static void
-+haiku_stream_destroy(cubeb_stream* stream)
-+{
-+ if (!stream)
-+ return;
-+
-+ haiku_stream_stop(stream);
-+}
-+
-+static int
-+haiku_stream_start(cubeb_stream* stream)
-+{
-+ if (!stream->sound_player) {
-+ stream->sound_player = new BSoundPlayer(&stream->format,
-+ stream->stream_name,
-+ haiku_audio_callback,
-+ nullptr,
-+ stream);
-+
-+ if (stream->sound_player->InitCheck() != B_OK)
-+ return CUBEB_ERROR;
-+
-+ stream->pause = false;
-+
-+ haiku_stream_set_volume(stream, stream->volume);
-+
-+ stream->sound_player->Start();
-+ stream->sound_player->SetHasData(true);
-+ }
-+
-+ stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_STARTED);
-+
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_stream_stop(cubeb_stream* stream)
-+{
-+ if (stream->sound_player) {
-+ stream->pause = true;
-+ stream->sound_player->SetHasData(false);
-+ stream->sound_player->Stop();
-+
-+ delete stream->sound_player;
-+ stream->sound_player = nullptr;
-+ }
-+
-+ stream->state_callback(stream, stream->user_ptr, CUBEB_STATE_STOPPED);
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_stream_get_position(cubeb_stream* stream, uint64_t* position)
-+{
-+ *position = stream->position;
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_stream_get_latency(cubeb_stream* stream, uint32_t* latency_frames)
-+{
-+ if (!stream) {
-+ return CUBEB_ERROR;
-+ }
-+
-+ *latency_frames = stream->format.buffer_size /
-+ (stream->format.channel_count *
-+ (stream->format.format == media_raw_audio_format::B_AUDIO_FLOAT ?
-+ sizeof(float) : sizeof(int16_t)));
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_stream_set_volume(cubeb_stream* stream, float volume)
-+{
-+ if (!stream) {
-+ return CUBEB_ERROR;
-+ }
-+
-+ stream->volume = volume;
-+
-+ if (!stream->sound_player)
-+ return CUBEB_ERROR;
-+
-+ stream->sound_player->SetVolume(volume);
-+
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_stream_get_current_device(cubeb_stream* stream, cubeb_device** const device)
-+{
-+ *device = (cubeb_device*)calloc(1, sizeof(cubeb_device));
-+ if (!*device) {
-+ return CUBEB_ERROR;
-+ }
-+
-+ (*device)->output_name = strdup("Haiku Audio Output");
-+ (*device)->input_name = strdup("");
-+
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_stream_device_destroy(cubeb_stream* stream, cubeb_device* device)
-+{
-+ if (device->input_name) {
-+ free(device->input_name);
-+ }
-+ if (device->output_name) {
-+ free(device->output_name);
-+ }
-+ free(device);
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_enumerate_devices(cubeb* context, cubeb_device_type type,
-+ cubeb_device_collection* collection)
-+{
-+ if (!context || type != CUBEB_DEVICE_TYPE_OUTPUT) {
-+ return CUBEB_ERROR;
-+ }
-+
-+ uint32_t rate;
-+ haiku_get_preferred_sample_rate(context, &rate);
-+
-+ collection->count = 1;
-+ collection->device = new cubeb_device_info[1];
-+
-+ cubeb_device_info* dev = &collection->device[0];
-+ memset(dev, 0, sizeof(cubeb_device_info));
-+
-+ char const * a_name = "default";
-+
-+ dev->device_id = a_name;
-+ dev->devid = (cubeb_devid)dev->device_id;
-+ dev->friendly_name = a_name;
-+ dev->group_id = a_name;
-+ dev->vendor_name = a_name;
-+ dev->type = CUBEB_DEVICE_TYPE_OUTPUT;
-+ dev->state = CUBEB_DEVICE_STATE_ENABLED;
-+ dev->preferred = CUBEB_DEVICE_PREF_ALL;
-+ dev->format = CUBEB_DEVICE_FMT_F32NE;
-+ dev->default_format = CUBEB_DEVICE_FMT_F32NE;
-+ dev->max_channels = MAX_CHANNELS;
-+ dev->min_rate = rate;
-+ dev->max_rate = rate;
-+ dev->default_rate = rate;
-+ dev->latency_lo = 0;
-+ dev->latency_hi = 0;
-+
-+ return CUBEB_OK;
-+}
-+
-+static int
-+haiku_device_collection_destroy(cubeb* context,
-+ cubeb_device_collection* collection)
-+{
-+ delete[] collection->device;
-+ collection->device = nullptr;
-+ collection->count = 0;
-+ return CUBEB_OK;
-+}
-+
-diff --git a/python/mozboot/mozboot/haiku.py b/python/mozboot/mozboot/haiku.py
-new file mode 100644
-index 0000000000..bf8f9fcf54
---- /dev/null
-+++ b/python/mozboot/mozboot/haiku.py
-@@ -0,0 +1,59 @@
-+# This Source Code Form is subject to the terms of the Mozilla Public
-+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-+# You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+from mozboot.base import BaseBootstrapper
-+
-+
-+class HaikuBootstrapper(BaseBootstrapper):
-+ def __init__(self, version, **kwargs):
-+ BaseBootstrapper.__init__(self, **kwargs)
-+
-+ self.packages = [
-+ "make",
-+ "pkgconfig",
-+ "rust_bin",
-+ ]
-+
-+ self.browser_packages = [
-+ "dbus_devel",
-+ "dbus_glib_devel",
-+ "gtk3_devel",
-+ "libevent_devel",
-+ "libvpx_devel",
-+ "nasm",
-+ "nodejs20",
-+ "nspr_devel",
-+ ]
-+
-+ def pkgman_install(self, *packages):
-+ command = ["pkgman", "install"]
-+ if self.no_interactive:
-+ command.append("-y")
-+
-+ command.extend(packages)
-+ self.run_as_root(command)
-+
-+ def install_system_packages(self):
-+ self.pkgman_install(*self.packages)
-+
-+ def install_browser_packages(self, mozconfig_builder, artifact_mode=False):
-+ self.pkgman_install(*self.browser_packages)
-+
-+ def install_browser_artifact_mode_packages(self, mozconfig_builder):
-+ self.install_browser_packages(mozconfig_builder, artifact_mode=True)
-+
-+ def ensure_clang_static_analysis_package(self):
-+ # TODO: we don't ship clang base static analysis for this platform
-+ pass
-+
-+ def ensure_stylo_packages(self):
-+ # Clang / llvm already installed as browser package
-+ self.pkgman_install("cbindgen")
-+
-+ def ensure_nasm_packages(self):
-+ # installed via install_browser_packages
-+ pass
-+
-+ def ensure_node_packages(self):
-+ self.pkgman_install("npm")
-diff --git a/third_party/rust/glslopt/.gitmodules b/third_party/rust/glslopt/.gitmodules
-new file mode 100644
-index 0000000000..dd75612faa
---- /dev/null
-+++ b/third_party/rust/glslopt/.gitmodules
-@@ -0,0 +1,3 @@
-+[submodule "glsl-optimizer"]
-+ path = glsl-optimizer
-+ url = https://github.com/kenz-gelsoft/glsl-optimizer
-diff --git a/third_party/rust/glslopt/glsl-optimizer/.editorconfig b/third_party/rust/glslopt/glsl-optimizer/.editorconfig
-new file mode 100644
-index 0000000000..3f9e475a6a
---- /dev/null
-+++ b/third_party/rust/glslopt/glsl-optimizer/.editorconfig
-@@ -0,0 +1,44 @@
-+# To use this config on you editor, follow the instructions at:
-+# http://editorconfig.org
-+
-+root = true
-+
-+[*]
-+charset = utf-8
-+insert_final_newline = true
-+tab_width = 8
-+
-+[*.{c,h,cpp,hpp,cc,hh}]
-+indent_style = space
-+indent_size = 3
-+max_line_length = 78
-+
-+[{Makefile*,*.mk}]
-+indent_style = tab
-+
-+[{*.py,SCons*}]
-+indent_style = space
-+indent_size = 4
-+
-+[*.pl]
-+indent_style = space
-+indent_size = 4
-+
-+[*.m4]
-+indent_style = space
-+indent_size = 2
-+
-+[*.yml]
-+indent_style = space
-+indent_size = 2
-+
-+[*.html]
-+indent_style = space
-+indent_size = 2
-+
-+[*.patch]
-+trim_trailing_whitespace = false
-+
-+[{meson.build,meson_options.txt}]
-+indent_style = space
-+indent_size = 2
-diff --git a/third_party/rust/glslopt/glsl-optimizer/.gitignore b/third_party/rust/glslopt/glsl-optimizer/.gitignore
-new file mode 100644
-index 0000000000..825ad5fd16
---- /dev/null
-+++ b/third_party/rust/glslopt/glsl-optimizer/.gitignore
-@@ -0,0 +1,4 @@
-+*.pyc
-+*.pyo
-+*.out
-+build
-diff --git a/third_party/rust/glslopt/glsl-optimizer/include/c11/.editorconfig b/third_party/rust/glslopt/glsl-optimizer/include/c11/.editorconfig
-new file mode 100644
-index 0000000000..bdbea000b5
---- /dev/null
-+++ b/third_party/rust/glslopt/glsl-optimizer/include/c11/.editorconfig
-@@ -0,0 +1,3 @@
-+[*.h]
-+indent_style = space
-+indent_size = 4
-diff --git a/third_party/rust/lmdb-rkv-sys/.rustfmt.toml b/third_party/rust/lmdb-rkv-sys/.rustfmt.toml
-new file mode 100644
-index 0000000000..fc441bbad4
---- /dev/null
-+++ b/third_party/rust/lmdb-rkv-sys/.rustfmt.toml
-@@ -0,0 +1,3 @@
-+ignore = [
-+ "src/bindings.rs"
-+]
-\ No newline at end of file
diff --git a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/.gitignore b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/.gitignore
new file mode 100644
-index 0000000000..d5102a87c0
+index 0000000..d5102a8
--- /dev/null
+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/.gitignore
@@ -0,0 +1,23 @@
@@ -2583,9 +4209,31 @@ index 0000000000..d5102a87c0
+valgrind.*
+man/
+html/
+diff --git a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
+index 01741d0..ad4f34d 100644
+--- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
++++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
+@@ -123,7 +123,7 @@ typedef SSIZE_T ssize_t;
+ #include /* defines BYTE_ORDER on HPUX and Solaris */
+ #endif
+
+-#if defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__)
++#if defined(__APPLE__) || defined (BSD) || defined(__FreeBSD_kernel__) || defined(__HAIKU__)
+ # define MDB_USE_POSIX_SEM 1
+ # define MDB_FDATASYNC fsync
+ #elif defined(__ANDROID__)
+@@ -256,7 +256,7 @@ typedef SSIZE_T ssize_t;
+ */
+ #ifndef MDB_USE_ROBUST
+ /* Android currently lacks Robust Mutex support. So does glibc < 2.4. */
+-# if defined(MDB_USE_POSIX_MUTEX) && (defined(__ANDROID__) || \
++# if defined(MDB_USE_POSIX_MUTEX) && (defined(__ANDROID__) || defined(__HAIKU__) || \
+ (defined(__GLIBC__) && GLIBC_VER < 0x020004))
+ # define MDB_USE_ROBUST 0
+ # else
diff --git a/toolkit/components/processtools/ProcInfo_haiku.cpp b/toolkit/components/processtools/ProcInfo_haiku.cpp
new file mode 100644
-index 0000000000..ad41c23fbb
+index 0000000..ad41c23
--- /dev/null
+++ b/toolkit/components/processtools/ProcInfo_haiku.cpp
@@ -0,0 +1,86 @@
@@ -2675,16 +4323,1018 @@ index 0000000000..ad41c23fbb
+}
+
+} // namespace mozilla
-diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
-index 264027e..f1ce6c7 100644
---- a/build/moz.configure/toolchain.configure
-+++ b/build/moz.configure/toolchain.configure
-@@ -2693,7 +2693,7 @@ def security_hardening_cflags(
- if (
- c_compiler.type == "clang"
- and c_compiler.version >= "11.0.1"
-- and target.os not in ("WINNT", "OSX", "OpenBSD")
-+ and target.os not in ("WINNT", "OSX", "OpenBSD", "Haiku")
- and target.cpu in ("x86", "x86_64", "ppc64", "s390x")
- ):
- flags.append("-fstack-clash-protection")
+diff --git a/toolkit/components/processtools/moz.build b/toolkit/components/processtools/moz.build
+index ee9d07c..0b44d4c 100644
+--- a/toolkit/components/processtools/moz.build
++++ b/toolkit/components/processtools/moz.build
+@@ -43,6 +43,8 @@ if toolkit == "gtk" or toolkit == "android":
+ UNIFIED_SOURCES += ["ProcInfo_bsd.cpp"]
+ elif CONFIG["OS_TARGET"] == "SunOS":
+ UNIFIED_SOURCES += ["ProcInfo_solaris.cpp"]
++ elif CONFIG["OS_TARGET"] == "Haiku":
++ UNIFIED_SOURCES += ["ProcInfo_haiku.cpp"]
+ else:
+ UNIFIED_SOURCES += ["ProcInfo_linux.cpp"]
+ elif toolkit == "windows":
+diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build
+index c33d81a..e58f269 100644
+--- a/toolkit/library/moz.build
++++ b/toolkit/library/moz.build
+@@ -340,6 +340,10 @@ if CONFIG["OS_ARCH"] == "Darwin":
+ "-weak_framework MediaPlayer",
+ ]
+
++if CONFIG["OS_ARCH"] == "Haiku":
++ OS_LIBS += [
++ "be",
++ ]
+
+ if CONFIG["OS_ARCH"] == "WINNT":
+ OS_LIBS += [
+diff --git a/toolkit/library/rust/moz.build b/toolkit/library/rust/moz.build
+index 0926e21..da8ff80 100644
+--- a/toolkit/library/rust/moz.build
++++ b/toolkit/library/rust/moz.build
+@@ -8,6 +8,12 @@ include("gkrust-features.mozbuild")
+
+ RustLibrary("gkrust", gkrust_features, is_gkrust=True)
+
++if CONFIG["OS_ARCH"] == "Haiku":
++ # Rust 1.83+ requires arc4random_buf()
++ OS_LIBS += [
++ "bsd"
++ ]
++
+ for feature in gkrust_features:
+ # We don't want to enable refcount logging during rusttests, since the
+ # relevant FFI symbols wouldn't be found.
+diff --git a/toolkit/modules/ShortcutUtils.sys.mjs b/toolkit/modules/ShortcutUtils.sys.mjs
+index 3632c52..5b56b19 100644
+--- a/toolkit/modules/ShortcutUtils.sys.mjs
++++ b/toolkit/modules/ShortcutUtils.sys.mjs
+@@ -63,7 +63,7 @@ export var ShortcutUtils = {
+ let elemString = "";
+ let haveCloverLeaf = false;
+ if (elemMod.match("accel")) {
+- if (Services.appinfo.OS == "Darwin") {
++ if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Haiku") {
+ haveCloverLeaf = true;
+ } else {
+ elemString +=
+@@ -72,7 +72,7 @@ export var ShortcutUtils = {
+ }
+ }
+ if (elemMod.match("access")) {
+- if (Services.appinfo.OS == "Darwin") {
++ if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Haiku") {
+ elemString +=
+ lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
+@@ -93,14 +93,26 @@ export var ShortcutUtils = {
+ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
+ }
+ if (elemMod.match("alt")) {
+- elemString +=
+- lazy.PlatformKeys.GetStringFromName("VK_ALT") +
+- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ if (Services.appinfo.OS == "Haiku") {
++ elemString +=
++ lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
++ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ } else {
++ elemString +=
++ lazy.PlatformKeys.GetStringFromName("VK_ALT") +
++ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ }
+ }
+ if (elemMod.match("ctrl") || elemMod.match("control")) {
+- elemString +=
+- lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
+- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ if (Services.appinfo.OS == "Haiku") {
++ elemString +=
++ lazy.PlatformKeys.GetStringFromName("VK_ALT") +
++ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ } else {
++ elemString +=
++ lazy.PlatformKeys.GetStringFromName("VK_CONTROL") +
++ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ }
+ }
+ if (elemMod.match("meta") && this.metaKeyIsCommandKey()) {
+ elemString +=
+@@ -109,9 +121,15 @@ export var ShortcutUtils = {
+ }
+
+ if (haveCloverLeaf) {
+- elemString +=
+- lazy.PlatformKeys.GetStringFromName("VK_COMMAND_OR_WIN") +
+- lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ if (Services.appinfo.OS == "Haiku") {
++ elemString +=
++ lazy.PlatformKeys.GetStringFromName("VK_ALT") +
++ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ } else {
++ elemString +=
++ lazy.PlatformKeys.GetStringFromName("VK_COMMAND_OR_WIN") +
++ lazy.PlatformKeys.GetStringFromName("MODIFIER_SEPARATOR");
++ }
+ }
+
+ return elemString;
+diff --git a/toolkit/moz.configure b/toolkit/moz.configure
+index 9e191e0..cc77fab 100644
+--- a/toolkit/moz.configure
++++ b/toolkit/moz.configure
+@@ -217,6 +217,8 @@ def audio_backends_default(target):
+ return ("sndio",)
+ elif target.kernel == "Darwin":
+ return ("audiounit",)
++ elif target.os == "Haiku":
++ return ("haiku",)
+ elif target.os == "NetBSD":
+ return ("sunaudio",)
+ elif target.os == "SunOS":
+@@ -234,6 +236,7 @@ option(
+ "aaudio",
+ "alsa",
+ "audiounit",
++ "haiku",
+ "jack",
+ "opensl",
+ "oss",
+@@ -272,6 +275,11 @@ def imply_audiounit(values, target):
+ return any("audiounit" in value for value in values) or None
+
+
++@depends("--enable-audio-backends")
++def imply_haiku(values):
++ return any("haiku" in value for value in values) or None
++
++
+ @depends("--enable-audio-backends")
+ def imply_jack(values):
+ return any("jack" in value for value in values) or None
+@@ -335,6 +343,8 @@ imply_option(
+
+ set_config("MOZ_AUDIOUNIT_RUST", imply_audiounit, when="--enable-audio-backends")
+
++set_config("MOZ_HAIKU", imply_haiku, when="--enable-audio-backends")
++
+ imply_option(
+ "--enable-jack", imply_jack, reason="--enable-audio-backends", when=use_pkg_config
+ )
+@@ -2940,6 +2950,7 @@ def forkserver_default(target, build_project):
+ (target.os == "GNU" and target.kernel == "Linux")
+ or target.os == "FreeBSD"
+ or target.os == "OpenBSD"
++ or target.os == "Haiku"
+ )
+
+
+@@ -3434,7 +3445,7 @@ with only_when(compile_environment):
+
+ @depends(target)
+ def default_user_appdir(target):
+- if target.kernel in ("WINNT", "Darwin"):
++ if target.kernel in ("WINNT", "Darwin", "Haiku"):
+ return "Mozilla"
+ return ".mozilla"
+
+diff --git a/toolkit/system/gnome/moz.build b/toolkit/system/gnome/moz.build
+index aa2df2b..a42f897 100644
+--- a/toolkit/system/gnome/moz.build
++++ b/toolkit/system/gnome/moz.build
+@@ -7,8 +7,12 @@
+ with Files("**"):
+ BUG_COMPONENT = ("Firefox", "Shell Integration")
+
++if CONFIG["OS_ARCH"] != "Haiku":
++ SOURCES += [
++ "nsAlertsIconListener.cpp",
++ ]
++
+ SOURCES += [
+- "nsAlertsIconListener.cpp",
+ "nsSystemAlertsService.cpp",
+ ]
+
+diff --git a/toolkit/system/gnome/nsGIOService.cpp b/toolkit/system/gnome/nsGIOService.cpp
+index d02560b..d836355 100644
+--- a/toolkit/system/gnome/nsGIOService.cpp
++++ b/toolkit/system/gnome/nsGIOService.cpp
+@@ -300,6 +300,32 @@ gboolean g_app_info_launch_default_for_uri_openbsd(const char* uri,
+ }
+ #endif
+
++#ifdef __HAIKU__
++
++gboolean g_app_info_launch_uris_haiku(GAppInfo* mApp, const char* uri,
++ GAppLaunchContext* context,
++ GError** error) {
++ gchar* command = g_strdup_printf("open '%s'", uri);
++ auto releaseCommand = MakeScopeExit([&] { g_free(command); });
++
++ int result = system(command);
++
++ if (result != 0) {
++ g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ "Failed to open URI '%s' using 'open' utility", uri);
++ return FALSE;
++ }
++ return TRUE;
++}
++
++gboolean g_app_info_launch_default_for_uri_haiku(const char* uri,
++ GAppLaunchContext* context,
++ GError** error) {
++ return g_app_info_launch_uris_haiku(NULL, uri, context, error);
++}
++
++#endif // __HAIKU__
++
+ static NS_IMETHODIMP LaunchWithURIImpl(RefPtr aInfo, nsIURI* aUri,
+ const char* aXDGToken = nullptr) {
+ GList uris = {0};
+@@ -313,6 +339,10 @@ static NS_IMETHODIMP LaunchWithURIImpl(RefPtr aInfo, nsIURI* aUri,
+ gboolean result = g_app_info_launch_uris_openbsd(
+ aInfo, spec.get(), GetLaunchContext(aXDGToken).get(),
+ getter_Transfers(error));
++#elif defined(__HAIKU__)
++ gboolean result = g_app_info_launch_uris_haiku(
++ aInfo, spec.get(), GetLaunchContext(aXDGToken).get(),
++ getter_Transfers(error));
+ #else
+ gboolean result = g_app_info_launch_uris(
+ aInfo, &uris, GetLaunchContext(aXDGToken).get(), getter_Transfers(error));
+@@ -640,6 +670,9 @@ static nsresult ShowURIImpl(nsIURI* aURI, const char* aXDGToken = nullptr) {
+ #ifdef __OpenBSD__
+ if (!g_app_info_launch_default_for_uri_openbsd(
+ spec.get(), GetLaunchContext(aXDGToken).get(),
++#elif defined(__HAIKU__)
++ if (!g_app_info_launch_default_for_uri_haiku(
++ spec.get(), GetLaunchContext(aXDGToken).get(),
+ #else
+ if (!g_app_info_launch_default_for_uri(spec.get(),
+ GetLaunchContext(aXDGToken).get(),
+@@ -675,6 +708,9 @@ static nsresult LaunchPathImpl(const nsACString& aPath,
+ #ifdef __OpenBSD__
+ g_app_info_launch_default_for_uri_openbsd(spec.get(),
+ GetLaunchContext(aXDGToken).get(),
++#elif defined(__HAIKU__)
++ g_app_info_launch_default_for_uri_haiku(spec.get(),
++ GetLaunchContext(aXDGToken).get(),
+ #else
+ g_app_info_launch_default_for_uri(spec.get(),
+ GetLaunchContext(aXDGToken).get(),
+diff --git a/toolkit/system/haiku/moz.build b/toolkit/system/haiku/moz.build
+new file mode 100644
+index 0000000..8c3bf79
+--- /dev/null
++++ b/toolkit/system/haiku/moz.build
+@@ -0,0 +1,26 @@
++# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
++# vim: set filetype=python:
++# This Source Code Form is subject to the terms of the Mozilla Public
++# License, v. 2.0. If a copy of the MPL was not distributed with this
++# file, You can obtain one at http://mozilla.org/MPL/2.0/.
++
++with Files("**"):
++ BUG_COMPONENT = ("Firefox", "Shell Integration")
++
++if CONFIG["OS_ARCH"] == "Haiku":
++ SOURCES += [
++ "nsAlertsIconListener.cpp",
++ ]
++ OS_LIBS += [
++ 'be',
++ ]
++
++
++FINAL_LIBRARY = "xul"
++
++LOCAL_INCLUDES += [
++ "/toolkit/components/build/",
++]
++
++CXXFLAGS += CONFIG["GLIB_CFLAGS"]
++CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"]
+diff --git a/toolkit/system/haiku/nsAlertsIconListener.cpp b/toolkit/system/haiku/nsAlertsIconListener.cpp
+new file mode 100644
+index 0000000..f556f6b
+--- /dev/null
++++ b/toolkit/system/haiku/nsAlertsIconListener.cpp
+@@ -0,0 +1,299 @@
++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#include "../gnome/nsSystemAlertsService.h"
++
++#include "nsAlertsIconListener.h"
++#include "imgIContainer.h"
++#include "imgIRequest.h"
++#include "nsServiceManagerUtils.h"
++#include "nsIAlertsService.h"
++#include "nsICancelable.h"
++#include "nsImageToPixbuf.h"
++#include "nsIStringBundle.h"
++#include "nsIObserverService.h"
++#include "nsCRT.h"
++#include "mozilla/XREAppData.h"
++#include "mozilla/GRefPtr.h"
++#include "mozilla/GUniquePtr.h"
++#include "mozilla/UniquePtrExtensions.h"
++
++#include
++#include
++#include
++
++#include "mozilla/UniquePtr.h"
++
++using namespace mozilla;
++extern const StaticXREAppData* gAppData;
++
++NS_IMPL_ISUPPORTS(nsAlertsIconListener, nsIAlertNotificationImageListener,
++ nsIObserver, nsISupportsWeakReference)
++
++GdkPixbuf* nsAlertsIconListener::GetPixbufFromImgRequest(imgIRequest* aRequest) {
++ nsCOMPtr image;
++ nsresult rv = aRequest->GetImage(getter_AddRefs(image));
++ if (NS_FAILED(rv) || !image) {
++ return nullptr;
++ }
++
++ RefPtr pixbuf = nsImageToPixbuf::ImageToPixbuf(image);
++ if (!pixbuf) {
++ return nullptr;
++ }
++
++ return pixbuf.forget().take();
++}
++
++
++BBitmap* nsAlertsIconListener::PixbufToBitmap(GdkPixbuf* aPixbuf) {
++ if (!aPixbuf) {
++ return nullptr;
++ }
++
++ GdkPixbuf* pixbufToUse = aPixbuf;
++ RefPtr scaledPixbuf;
++
++ int width = gdk_pixbuf_get_width(aPixbuf);
++ int height = gdk_pixbuf_get_height(aPixbuf);
++
++ const int maxWidth = 64;
++ const int maxHeight = 64;
++
++ if (width > maxWidth || height > maxHeight) {
++ double ratio = std::min(static_cast(maxWidth) / width,
++ static_cast(maxHeight) / height);
++ int newWidth = std::max(1, static_cast(std::round(width * ratio)));
++ int newHeight = std::max(1, static_cast(std::round(height * ratio)));
++
++ scaledPixbuf = gdk_pixbuf_scale_simple(
++ aPixbuf, newWidth, newHeight, GDK_INTERP_BILINEAR);
++
++ if (!scaledPixbuf) {
++ fprintf(stderr, "PixbufToBitmap: Failed to scale pixbuf\n");
++ return nullptr;
++ }
++ pixbufToUse = scaledPixbuf.get();
++ width = newWidth;
++ height = newHeight;
++ }
++
++ int n_channels = gdk_pixbuf_get_n_channels(pixbufToUse);
++ bool has_alpha = gdk_pixbuf_get_has_alpha(pixbufToUse);
++
++ if (width <= 0 || height <= 0) {
++ return nullptr;
++ }
++
++ if (n_channels != 4 || !has_alpha) {
++ fprintf(stderr, "PixbufToBitmap: Expected 4 channels (RGBA) after potential scaling, got %d\n", n_channels);
++ return nullptr;
++ }
++
++ BRect bounds(0, 0, width - 1, height - 1);
++ BBitmap* bitmap = new BBitmap(bounds, B_RGBA32);
++
++ if (!bitmap || bitmap->InitCheck() != B_OK) {
++ delete bitmap;
++ return nullptr;
++ }
++
++ guchar* pixbufPixels = gdk_pixbuf_get_pixels(pixbufToUse);
++ int pixbufRowstride = gdk_pixbuf_get_rowstride(pixbufToUse);
++ uint8* bitmapPixels = (uint8*)bitmap->Bits();
++ uint32 bitmapRowstride = bitmap->BytesPerRow();
++
++ for (int y = 0; y < height; ++y) {
++ guchar* p = pixbufPixels + y * pixbufRowstride;
++ uint8* b = bitmapPixels + y * bitmapRowstride;
++ for (int x = 0; x < width; ++x) {
++ uint8 r = p[0];
++ uint8 g = p[1];
++ uint8 b_ = p[2];
++ uint8 a = p[3];
++
++ b[0] = b_;
++ b[1] = g;
++ b[2] = r;
++ b[3] = a;
++
++ p += 4;
++ b += 4;
++ }
++ }
++
++ return bitmap;
++}
++
++
++nsAlertsIconListener::nsAlertsIconListener(nsSystemAlertsService* aBackend,
++ const nsAString& aAlertName)
++ : mAlertName(aAlertName), mBackend(aBackend) {
++}
++
++nsAlertsIconListener::~nsAlertsIconListener() {
++ mBackend->RemoveListener(mAlertName, this);
++}
++
++NS_IMETHODIMP
++nsAlertsIconListener::OnImageMissing(nsISupports*) {
++ return ShowAlert(nullptr);
++}
++
++NS_IMETHODIMP
++nsAlertsIconListener::OnImageReady(nsISupports*, imgIRequest* aRequest) {
++ GdkPixbuf* pixbuf = GetPixbufFromImgRequest(aRequest);
++ if (!pixbuf) {
++ fprintf(stderr, "Failed to get GdkPixbuf from image request\n");
++ return ShowAlert(nullptr);
++ }
++
++ BBitmap* iconBitmap = PixbufToBitmap(pixbuf);
++
++ g_object_unref(pixbuf);
++
++ if (!iconBitmap) {
++ fprintf(stderr, "Failed to convert GdkPixbuf to BBitmap (possibly after scaling)\n");
++ }
++
++ nsresult rv = ShowAlert(iconBitmap);
++ return rv;
++}
++
++nsresult nsAlertsIconListener::ShowAlert(BBitmap* aIconBitmap) {
++ mozilla::UniquePtr iconBitmap(aIconBitmap);
++
++ if (!mBackend->IsActiveListener(mAlertName, this)) return NS_OK;
++
++ notification_type type = B_INFORMATION_NOTIFICATION;
++
++ BNotification notification(type);
++ if (notification.InitCheck() != B_OK) {
++ fprintf(stderr, "Failed to initialize BNotification\n");
++ return NS_ERROR_FAILURE;
++ }
++
++ nsCOMPtr bundleService =
++ do_GetService(NS_STRINGBUNDLE_CONTRACTID);
++
++ nsAutoCString appShortName;
++ if (bundleService) {
++ nsCOMPtr bundle;
++ bundleService->CreateBundle("chrome://branding/locale/brand.properties",
++ getter_AddRefs(bundle));
++ nsAutoString appName;
++
++ if (bundle) {
++ bundle->GetStringFromName("brandShortName", appName);
++ CopyUTF16toUTF8(appName, appShortName);
++ } else {
++ NS_WARNING(
++ "brand.properties not present, using default application name");
++ appShortName.AssignLiteral("Mozilla");
++ }
++ } else {
++ appShortName.AssignLiteral("Mozilla");
++ }
++
++ notification.SetGroup(appShortName.get());
++
++ if (!mAlertTitle.IsEmpty()) {
++ notification.SetTitle(mAlertTitle.get());
++ } else {
++ notification.SetTitle("Notification");
++ }
++
++ if (!mAlertText.IsEmpty()) {
++ notification.SetContent(mAlertText.get());
++ }
++
++ if (!mAlertCookie.IsEmpty()) {
++ nsCString cookieStr = NS_ConvertUTF16toUTF8(mAlertCookie);
++ if (!cookieStr.IsEmpty()) {
++ notification.SetMessageID(cookieStr.get());
++ }
++ }
++
++ if (iconBitmap) {
++ notification.SetIcon(iconBitmap.get());
++ }
++
++ bigtime_t timeout = mAlertRequiresInteraction ? 15000000 : -1;
++
++ status_t sendStatus = notification.Send(timeout);
++ if (sendStatus != B_OK) {
++ fprintf(stderr, "Failed to send BNotification: %s\n", strerror(sendStatus));
++ }
++
++ nsCOMPtr obsServ =
++ do_GetService("@mozilla.org/observer-service;1");
++ if (obsServ) obsServ->AddObserver(this, "quit-application", true);
++
++ if (mAlertListener)
++ mAlertListener->Observe(nullptr, "alertshow", mAlertCookie.get());
++
++ return NS_OK;
++}
++
++void nsAlertsIconListener::SendCallback() {
++ if (mAlertListener)
++ mAlertListener->Observe(nullptr, "alertclickcallback", mAlertCookie.get());
++}
++
++void nsAlertsIconListener::SendClosed() {
++ NotifyFinished();
++}
++
++NS_IMETHODIMP
++nsAlertsIconListener::Observe(nsISupports* aSubject, const char* aTopic,
++ const char16_t* aData) {
++ if (!nsCRT::strcmp(aTopic, "quit-application")) {
++ Release();
++ }
++ return NS_OK;
++}
++
++nsresult nsAlertsIconListener::Close() {
++ if (mIconRequest) {
++ mIconRequest->Cancel(NS_BINDING_ABORTED);
++ mIconRequest = nullptr;
++ }
++ NotifyFinished();
++ return NS_OK;
++}
++
++nsresult nsAlertsIconListener::InitAlertAsync(nsIAlertNotification* aAlert,
++ nsIObserver* aAlertListener) {
++ nsresult rv = aAlert->GetTextClickable(&mAlertHasAction);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = aAlert->GetSilent(&mAlertIsSilent);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ rv = aAlert->GetRequireInteraction(&mAlertRequiresInteraction);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ nsAutoString title;
++ rv = aAlert->GetTitle(title);
++ NS_ENSURE_SUCCESS(rv, rv);
++ CopyUTF16toUTF8(title, mAlertTitle);
++
++ nsAutoString text;
++ rv = aAlert->GetText(text);
++ NS_ENSURE_SUCCESS(rv, rv);
++ CopyUTF16toUTF8(text, mAlertText);
++
++ mAlertListener = aAlertListener;
++
++ rv = aAlert->GetCookie(mAlertCookie);
++ NS_ENSURE_SUCCESS(rv, rv);
++
++ return aAlert->LoadImage(0, this, nullptr, getter_AddRefs(mIconRequest));
++}
++
++void nsAlertsIconListener::NotifyFinished() {
++ if (mAlertListener)
++ mAlertListener->Observe(nullptr, "alertfinished", mAlertCookie.get());
++}
+diff --git a/toolkit/system/haiku/nsAlertsIconListener.h b/toolkit/system/haiku/nsAlertsIconListener.h
+new file mode 100644
+index 0000000..983e5a5
+--- /dev/null
++++ b/toolkit/system/haiku/nsAlertsIconListener.h
+@@ -0,0 +1,72 @@
++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef nsAlertsIconListener_h__
++#define nsAlertsIconListener_h__
++
++#include "nsCOMPtr.h"
++#include "nsIAlertsService.h"
++#include "nsString.h"
++#include "nsIObserver.h"
++#include "nsWeakReference.h"
++
++#include
++
++#pragma GCC visibility push(default)
++#include
++#include
++#include
++#include
++#pragma GCC visibility pop
++
++class nsIAlertNotification;
++class nsICancelable;
++class nsSystemAlertsService;
++class imgIRequest;
++
++class nsAlertsIconListener : public nsIAlertNotificationImageListener,
++ public nsIObserver,
++ public nsSupportsWeakReference {
++ public:
++ NS_DECL_ISUPPORTS
++ NS_DECL_NSIALERTNOTIFICATIONIMAGELISTENER
++ NS_DECL_NSIOBSERVER
++
++ nsAlertsIconListener(nsSystemAlertsService* aBackend,
++ const nsAString& aAlertName);
++
++ nsresult InitAlertAsync(nsIAlertNotification* aAlert,
++ nsIObserver* aAlertListener);
++ nsresult Close();
++
++ void SendCallback();
++ void SendClosed();
++
++ protected:
++ virtual ~nsAlertsIconListener();
++
++ static BBitmap* PixbufToBitmap(GdkPixbuf* aPixbuf);
++ static GdkPixbuf* GetPixbufFromImgRequest(imgIRequest* aRequest);
++
++ nsCOMPtr mIconRequest;
++ nsCString mAlertTitle;
++ nsCString mAlertText;
++
++ nsCOMPtr mAlertListener;
++ nsString mAlertCookie;
++ nsString mAlertName;
++
++ RefPtr mBackend;
++
++ bool mAlertHasAction;
++ bool mAlertIsSilent;
++ bool mAlertRequiresInteraction;
++
++ nsresult ShowAlert(BBitmap* aIconBitmap = nullptr);
++
++ void NotifyFinished();
++};
++
++#endif
+diff --git a/toolkit/themes/shared/popup.css b/toolkit/themes/shared/popup.css
+index ed23086..f10ce89 100644
+--- a/toolkit/themes/shared/popup.css
++++ b/toolkit/themes/shared/popup.css
+@@ -43,6 +43,12 @@ panel {
+ --panel-shadow-margin: 4px;
+ }
+
++ /* Disable border-radius and shadow for Haiku popups */
++ @media (-moz-platform: linux) {
++ --panel-border-radius: 0px;
++ --panel-shadow-margin: 0px;
++ }
++
+ @media (-moz-platform: macos) {
+ appearance: auto;
+ -moz-default-appearance: menupopup;
+diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
+index 8c2b2bf..cc28d36 100644
+--- a/toolkit/toolkit.mozbuild
++++ b/toolkit/toolkit.mozbuild
+@@ -148,6 +148,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
+ DIRS += [
+ "/media/mozva",
+ "/toolkit/system/gnome",
++ "/toolkit/system/haiku",
+ ]
+
+ if CONFIG["ENABLE_WEBDRIVER"]:
+diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
+index eb1781b..4776195 100644
+--- a/toolkit/xre/nsAppRunner.cpp
++++ b/toolkit/xre/nsAppRunner.cpp
+@@ -347,14 +347,16 @@ nsString gProcessStartupShortcut;
+ # ifdef MOZ_WAYLAND
+ # include
+ # include "mozilla/widget/nsWaylandDisplay.h"
+-# include "wayland-proxy.h"
++# ifndef XP_HAIKU
++# include "wayland-proxy.h"
++# endif /* !XP_HAIKU */
+ # endif
+ # ifdef MOZ_X11
+ # include
+ # endif /* MOZ_X11 */
+ #endif
+
+-#if defined(MOZ_WAYLAND)
++#if defined(MOZ_WAYLAND) && !defined(XP_HAIKU)
+ std::unique_ptr gWaylandProxy;
+ #endif
+
+@@ -439,6 +441,9 @@ static void UnexpectedExit() {
+
+ #if defined(MOZ_WAYLAND)
+ bool IsWaylandEnabled() {
++#ifdef XP_HAIKU
++ return true;
++#else
+ static bool isWaylandEnabled = []() {
+ const char* waylandDisplay = PR_GetEnv("WAYLAND_DISPLAY");
+ if (!waylandDisplay) {
+@@ -469,6 +474,7 @@ bool IsWaylandEnabled() {
+ return !gtk_check_version(3, 24, 30);
+ }();
+ return isWaylandEnabled;
++#endif // !XP_HAIKU
+ }
+ #else
+ bool IsWaylandEnabled() { return false; }
+@@ -3726,7 +3732,7 @@ class XREMain {
+ #endif
+ };
+
+-#if defined(XP_UNIX) && !defined(ANDROID)
++#if defined(XP_UNIX) && !defined(ANDROID) && !defined(XP_HAIKU)
+ static SmprintfPointer FormatUid(uid_t aId) {
+ if (const auto pw = getpwuid(aId)) {
+ return mozilla::Smprintf("%s", pw->pw_name);
+@@ -3775,7 +3781,7 @@ static bool CheckForUserMismatch() {
+ }
+ return false;
+ }
+-#else // !XP_UNIX || ANDROID
++#else // !XP_UNIX || ANDROID || XP_HAIKU
+ static bool CheckForUserMismatch() { return false; }
+ #endif
+
+@@ -4765,7 +4771,7 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
+ // display_name is owned by gdk.
+ display_name = gdk_get_display_arg_name();
+ bool waylandEnabled = IsWaylandEnabled();
+-# ifdef MOZ_WAYLAND
++# if defined(MOZ_WAYLAND) && !defined(XP_HAIKU)
+ if (!display_name) {
+ auto* proxyEnv = getenv("MOZ_DISABLE_WAYLAND_PROXY");
+ bool disableWaylandProxy = proxyEnv && *proxyEnv;
+@@ -4817,7 +4823,7 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
+ } else {
+ gdk_display_manager_open_display(gdk_display_manager_get(), nullptr);
+ }
+-# if defined(MOZ_WAYLAND)
++# if defined(MOZ_WAYLAND) && !defined(XP_HAIKU)
+ // We want to use proxy for main connection only so
+ // restore original Wayland display for next potential Wayland connections
+ // from gfx probe code and so on.
+@@ -6052,7 +6058,9 @@ int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
+ if (!gfxPlatform::IsHeadless()) {
+ # ifdef MOZ_WAYLAND
+ WaylandDisplayRelease();
++# ifndef XP_HAIKU
+ gWaylandProxy = nullptr;
++# endif // !XP_HAIKU
+ # endif
+ }
+ #endif
+diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
+index d3af49b..1713fe1 100644
+--- a/toolkit/xre/nsXREDirProvider.cpp
++++ b/toolkit/xre/nsXREDirProvider.cpp
+@@ -79,6 +79,10 @@
+ #ifdef XP_IOS
+ # include "UIKitDirProvider.h"
+ #endif
++#ifdef XP_HAIKU
++# include
++# include
++#endif
+
+ #if defined(MOZ_CONTENT_TEMP_DIR)
+ # include "mozilla/SandboxSettings.h"
+@@ -380,7 +384,7 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
+ } else if (!strcmp(aProperty, XRE_USER_NATIVE_MANIFESTS)) {
+ rv = GetUserDataDirectoryHome(getter_AddRefs(file), false);
+ NS_ENSURE_SUCCESS(rv, rv);
+-# if defined(XP_MACOSX)
++# if defined(XP_MACOSX) || defined(XP_HAIKU)
+ rv = file->AppendNative("Mozilla"_ns);
+ # else // defined(XP_MACOSX)
+ rv = file->AppendNative(".mozilla"_ns);
+@@ -1287,6 +1291,12 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
++#elif defined(XP_HAIKU)
++ BPath settingsDir;
++ status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &settingsDir);
++ if (status != B_OK) return NS_ERROR_FAILURE;
++ rv = NS_NewNativeLocalFile(nsDependentCString(settingsDir.Path()), true,
++ getter_AddRefs(localDir));
+ #elif defined(XP_UNIX)
+ const char* homeDir = getenv("HOME");
+ if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
+@@ -1396,7 +1406,7 @@ nsresult nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile) {
+
+ nsresult rv;
+
+-#if defined(XP_MACOSX) || defined(XP_WIN)
++#if defined(XP_MACOSX) || defined(XP_WIN) || defined(XP_HAIKU)
+
+ static const char* const sXR = "Mozilla";
+ rv = aFile->AppendNative(nsDependentCString(sXR));
+@@ -1455,7 +1465,7 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+-#elif defined(XP_WIN)
++#elif defined(XP_WIN) || defined(XP_HAIKU)
+ if (!profile.IsEmpty()) {
+ rv = AppendProfileString(aFile, profile.get());
+ } else {
+diff --git a/tools/profiler/core/ProfilerUtils.cpp b/tools/profiler/core/ProfilerUtils.cpp
+index 4c53061..76d3561 100644
+--- a/tools/profiler/core/ProfilerUtils.cpp
++++ b/tools/profiler/core/ProfilerUtils.cpp
+@@ -88,6 +88,15 @@ ProfilerThreadId profiler_current_thread_id() {
+ return ProfilerThreadId::FromNativeId(id);
+ }
+
++// ------------------------------------------------------- Haiku
++# elif defined(XP_HAIKU)
++
++# include
++
++ProfilerThreadId profiler_current_thread_id() {
++ return ProfilerThreadId::FromNativeId(find_thread(NULL));
++}
++
+ // ------------------------------------------------------- Others
+ # else
+
+diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build
+index 6ced9be..24bcf54 100644
+--- a/widget/gtk/moz.build
++++ b/widget/gtk/moz.build
+@@ -23,7 +23,9 @@ if CONFIG["COMPILE_ENVIRONMENT"]:
+ DIRS += ["mozgtk"]
+
+ if CONFIG["MOZ_WAYLAND"]:
+- DIRS += ["wayland", "mozwayland", "../../third_party/wayland-proxy"]
++ DIRS += ["wayland", "mozwayland"]
++ if CONFIG["OS_ARCH"] != "Haiku":
++ DIRS += ["../../third_party/wayland-proxy"]
+
+ if CONFIG["MOZ_ENABLE_VAAPI"]:
+ DIRS += ["vaapitest"]
+diff --git a/xpcom/base/nsSystemInfo.cpp b/xpcom/base/nsSystemInfo.cpp
+index 8bfd657..093a6e3 100644
+--- a/xpcom/base/nsSystemInfo.cpp
++++ b/xpcom/base/nsSystemInfo.cpp
+@@ -80,6 +80,10 @@
+ # include "mozilla/SandboxInfo.h"
+ #endif
+
++#ifdef XP_HAIKU
++# include
++#endif
++
+ // Slot for NS_InitXPCOM to pass information to nsSystemInfo::Init.
+ // Only set to nonzero (potentially) if XP_UNIX. On such systems, the
+ // system call to discover the appropriate value is not thread-safe,
+@@ -1355,7 +1359,15 @@ nsresult nsSystemInfo::Init() {
+ SetInt32Property(u"pagesize"_ns, PR_GetPageSize());
+ SetInt32Property(u"pageshift"_ns, PR_GetPageShift());
+ SetInt32Property(u"memmapalign"_ns, PR_GetMemMapAlignment());
++#ifdef XP_HAIKU
++ { // workaround
++ system_info info;
++ get_system_info(&info);
++ SetUint64Property(u"memsize"_ns, info.max_pages * B_PAGE_SIZE);
++ }
++#else
+ SetUint64Property(u"memsize"_ns, PR_GetPhysicalMemorySize());
++#endif
+ SetUint32Property(u"umask"_ns, nsSystemInfo::gUserUmask);
+
+ #ifdef HAVE_64BIT_BUILD
+diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h
+index 47bd694..8adc538 100644
+--- a/xpcom/build/BinaryPath.h
++++ b/xpcom/build/BinaryPath.h
+@@ -24,6 +24,10 @@
+ #if defined(__OpenBSD__)
+ # include
+ #endif
++#if defined(XP_HAIKU)
++# include
++# include
++#endif
+ #include "mozilla/UniquePtr.h"
+ #include "mozilla/UniquePtrExtensions.h"
+
+@@ -273,6 +277,21 @@ class BinaryPath {
+ return NS_ERROR_FAILURE;
+ }
+
++#elif defined(XP_HAIKU)
++ static nsresult Get(char aResult[MAXPATHLEN]) {
++ image_info info;
++ int32 cookie = 0;
++
++ while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) >= B_OK) {
++ if (info.type == B_APP_IMAGE) {
++ strlcpy(aResult, info.name, MAXPATHLEN - 1);
++ return NS_OK;
++ }
++ }
++
++ return NS_ERROR_FAILURE;
++ }
++
+ #else
+ # error Oops, you need platform-specific code here
+ #endif
+diff --git a/xpcom/reflect/xptcall/md/unix/moz.build b/xpcom/reflect/xptcall/md/unix/moz.build
+index 6b566f9..2895ad9 100644
+--- a/xpcom/reflect/xptcall/md/unix/moz.build
++++ b/xpcom/reflect/xptcall/md/unix/moz.build
+@@ -33,6 +33,7 @@ if CONFIG["OS_ARCH"] in (
+ "Bitrig",
+ "DragonFly",
+ "FreeBSD",
++ "Haiku",
+ "NetBSD",
+ "OpenBSD",
+ "SunOS",
+diff --git a/xpcom/threads/nsProcessCommon.cpp b/xpcom/threads/nsProcessCommon.cpp
+index dbd9993..1431340 100644
+--- a/xpcom/threads/nsProcessCommon.cpp
++++ b/xpcom/threads/nsProcessCommon.cpp
+@@ -43,7 +43,11 @@
+ # include "base/process_util.h"
+ # endif
+ # include
+-# include
++# ifdef XP_HAIKU
++# include
++# else
++# include
++# endif
+ # endif
+ # include
+ # include
+diff --git a/third_party/libwebrtc/build/config/BUILDCONFIG.gn b/third_party/libwebrtc/build/config/BUILDCONFIG.gn
+index 571ae5f..595c93b 100644
+--- a/third_party/libwebrtc/build/config/BUILDCONFIG.gn
++++ b/third_party/libwebrtc/build/config/BUILDCONFIG.gn
+@@ -184,7 +184,7 @@ if (host_toolchain == "") {
+ # TODO(dpranke): Add some sort of assert here that verifies that
+ # no toolchain omitted host_toolchain from its toolchain_args().
+
+- if (host_os == "linux" || host_os == "openbsd") {
++ if (host_os == "linux" || host_os == "openbsd" || host_os == "haiku") {
+ if (target_os != "linux") {
+ host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
+ } else if (is_clang) {
+@@ -222,7 +222,7 @@ if (target_os == "android") {
+ assert(host_os == "linux" || host_os == "mac",
+ "Android builds are only supported on Linux and Mac hosts.")
+ _default_toolchain = "//build/toolchain/android:android_clang_$target_cpu"
+-} else if (target_os == "chromeos" || target_os == "linux" || target_os == "openbsd") {
++} else if (target_os == "chromeos" || target_os == "linux" || target_os == "openbsd" || target_os == "haiku") {
+ # See comments in build/toolchain/cros/BUILD.gn about board compiles.
+ if (is_clang) {
+ _default_toolchain = "//build/toolchain/linux:clang_$target_cpu"
+@@ -286,6 +286,7 @@ if (custom_toolchain != "") {
+ is_android = current_os == "android"
+ is_chromeos = current_os == "chromeos"
+ is_fuchsia = current_os == "fuchsia"
++is_haiku = current_os == "haiku"
+ is_ios = current_os == "ios"
+ is_linux = current_os == "linux"
+ is_bsd = current_os == "openbsd"
+--
+2.48.1
+