feat: Wave A — boot DRM wait, D-Bus login1, Wayland wire fixes
Boot: greeter DRM wait window, pcid-spawner ordering, plan updated D-Bus: sessiond login1 manager extension (GetUser, ActivateSessionOnSeat, lock/unlock, terminate/kill), KDE activation files (ActivityManager, JobViewServer, ksmserver), plan v3.0 Wayland: proper little-endian/padded strings, SCM_RIGHTS fd passing, xdg_toplevel.configure fix, compositor-checker protocol probes Verified: bash -n, TOML parsed, sessiond 30/30 tests, compositor all tests pass w/ warnings denied.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
# KIO — reduced real KIOCore build for Red Bear OS.
|
||||
#
|
||||
# Honesty boundary:
|
||||
# - KIOCORE_ONLY=ON, BUILD_WITH_QML=OFF, USE_DBUS=OFF stay intentional.
|
||||
# - KIOCORE_ONLY=ON and BUILD_WITH_QML=OFF stay intentional.
|
||||
# - USE_DBUS=ON is now enabled to expose more real KIOCore functionality.
|
||||
# - QtNetwork is still unavailable on Redox, so KIOCore uses source-local
|
||||
# Redox compatibility headers for the small QHostInfo/QHostAddress surface it needs.
|
||||
# - This recipe no longer forges QtNetwork headers into the shared sysroot.
|
||||
@@ -17,6 +18,7 @@ dependencies = [
|
||||
"kf6-kcoreaddons",
|
||||
"kf6-kconfig",
|
||||
"kf6-ki18n",
|
||||
"kf6-kdbusaddons",
|
||||
"kf6-kjobwidgets",
|
||||
"kf6-kservice",
|
||||
"kf6-kbookmarks",
|
||||
@@ -62,7 +64,7 @@ cmake "${COOKBOOK_SOURCE}" \
|
||||
-DQT_SKIP_AUTO_PLUGIN_INCLUSION=ON \
|
||||
-DKIOCORE_ONLY=ON \
|
||||
-DBUILD_WITH_QML=OFF \
|
||||
-DUSE_DBUS=OFF \
|
||||
-DUSE_DBUS=ON \
|
||||
-DWITH_X11=OFF \
|
||||
-Wno-dev
|
||||
|
||||
|
||||
@@ -17,16 +17,37 @@ public:
|
||||
IPv6Protocol,
|
||||
};
|
||||
|
||||
enum SpecialAddress {
|
||||
Null,
|
||||
Broadcast,
|
||||
LocalHost,
|
||||
LocalHostIPv6,
|
||||
AnyIPv4,
|
||||
AnyIPv6,
|
||||
Any = AnyIPv4,
|
||||
};
|
||||
|
||||
QHostAddress() = default;
|
||||
|
||||
explicit QHostAddress(SpecialAddress address)
|
||||
{
|
||||
setAddress(address);
|
||||
}
|
||||
|
||||
explicit QHostAddress(const QString &address)
|
||||
{
|
||||
setAddress(address);
|
||||
}
|
||||
|
||||
explicit QHostAddress(quint32 ip4Address)
|
||||
{
|
||||
setAddress(ip4Address);
|
||||
}
|
||||
|
||||
void setAddress(const QString &address)
|
||||
{
|
||||
m_address = address;
|
||||
m_ipv4Address = 0;
|
||||
|
||||
if (address.isEmpty()) {
|
||||
m_protocol = UnknownNetworkLayerProtocol;
|
||||
@@ -39,6 +60,8 @@ public:
|
||||
|
||||
if (inet_pton(AF_INET, utf8.constData(), ipv4) == 1) {
|
||||
m_protocol = IPv4Protocol;
|
||||
m_ipv4Address = (static_cast<quint32>(ipv4[0]) << 24) | (static_cast<quint32>(ipv4[1]) << 16)
|
||||
| (static_cast<quint32>(ipv4[2]) << 8) | static_cast<quint32>(ipv4[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,24 +73,96 @@ public:
|
||||
m_protocol = UnknownNetworkLayerProtocol;
|
||||
}
|
||||
|
||||
void setAddress(SpecialAddress address)
|
||||
{
|
||||
switch (address) {
|
||||
case Null:
|
||||
clear();
|
||||
break;
|
||||
case Broadcast:
|
||||
setAddress(QStringLiteral("255.255.255.255"));
|
||||
break;
|
||||
case LocalHost:
|
||||
setAddress(QStringLiteral("127.0.0.1"));
|
||||
break;
|
||||
case LocalHostIPv6:
|
||||
setAddress(QStringLiteral("::1"));
|
||||
break;
|
||||
case AnyIPv4:
|
||||
setAddress(QStringLiteral("0.0.0.0"));
|
||||
break;
|
||||
case AnyIPv6:
|
||||
setAddress(QStringLiteral("::"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setAddress(quint32 ip4Address)
|
||||
{
|
||||
in_addr address = {};
|
||||
address.s_addr = ip4Address;
|
||||
|
||||
char buffer[INET_ADDRSTRLEN] = {};
|
||||
if (inet_ntop(AF_INET, &address, buffer, sizeof(buffer)) != nullptr) {
|
||||
m_address = QString::fromUtf8(buffer);
|
||||
m_protocol = IPv4Protocol;
|
||||
m_ipv4Address = ip4Address;
|
||||
return;
|
||||
}
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_address.clear();
|
||||
m_protocol = UnknownNetworkLayerProtocol;
|
||||
m_ipv4Address = 0;
|
||||
}
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return m_protocol == UnknownNetworkLayerProtocol;
|
||||
}
|
||||
|
||||
bool isLoopback() const
|
||||
{
|
||||
return m_address == QStringLiteral("127.0.0.1") || m_address == QStringLiteral("::1");
|
||||
}
|
||||
|
||||
QString toString() const
|
||||
{
|
||||
return m_address;
|
||||
}
|
||||
|
||||
quint32 toIPv4Address(bool *ok = nullptr) const
|
||||
{
|
||||
if (ok) {
|
||||
*ok = m_protocol == IPv4Protocol;
|
||||
}
|
||||
|
||||
return m_protocol == IPv4Protocol ? m_ipv4Address : 0;
|
||||
}
|
||||
|
||||
NetworkLayerProtocol protocol() const
|
||||
{
|
||||
return m_protocol;
|
||||
}
|
||||
|
||||
bool operator==(const QHostAddress &other) const
|
||||
{
|
||||
return m_protocol == other.m_protocol && m_address == other.m_address && m_ipv4Address == other.m_ipv4Address;
|
||||
}
|
||||
|
||||
bool operator!=(const QHostAddress &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_address;
|
||||
NetworkLayerProtocol m_protocol = UnknownNetworkLayerProtocol;
|
||||
quint32 m_ipv4Address = 0;
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &stream, const QHostAddress &address)
|
||||
{
|
||||
|
||||
@@ -116,6 +116,10 @@ public:
|
||||
return info;
|
||||
}
|
||||
|
||||
static void abortHostLookup(int)
|
||||
{
|
||||
}
|
||||
|
||||
void setHostName(const QString &hostName)
|
||||
{
|
||||
m_hostName = hostName;
|
||||
@@ -156,11 +160,22 @@ public:
|
||||
return m_errorString;
|
||||
}
|
||||
|
||||
void setLookupId(int lookupId)
|
||||
{
|
||||
m_lookupId = lookupId;
|
||||
}
|
||||
|
||||
int lookupId() const
|
||||
{
|
||||
return m_lookupId;
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_hostName;
|
||||
QList<QHostAddress> m_addresses;
|
||||
HostInfoError m_error = UnknownError;
|
||||
QString m_errorString;
|
||||
int m_lookupId = -1;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QHostInfo)
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
#TODO: Kirigami — QtQuick lightweight UI framework. QML-heavy but required by KDE Plasma.
|
||||
# Real build requires Qt6Quick/QML runtime proof (qtdeclarative exports Qt6Quick metadata,
|
||||
# but downstream QML-dependent build and runtime paths are insufficient). Stub provides
|
||||
# cmake configs for dependency resolution only.
|
||||
#TODO: Kirigami — build the real non-QML C++ core on Redox. Qt Quick, templates, examples, and autotests stay disabled until the Qt6 QML/Quick runtime surface is stronger.
|
||||
[source]
|
||||
tar = "https://invent.kde.org/frameworks/kirigami/-/archive/v6.10.0/kirigami-v6.10.0.tar.gz"
|
||||
|
||||
@@ -9,12 +6,7 @@ tar = "https://invent.kde.org/frameworks/kirigami/-/archive/v6.10.0/kirigami-v6.
|
||||
template = "custom"
|
||||
dependencies = [
|
||||
"qtbase",
|
||||
"qtdeclarative",
|
||||
"kf6-extra-cmake-modules",
|
||||
"kf6-kcoreaddons",
|
||||
"kf6-ki18n",
|
||||
"kf6-kconfig",
|
||||
"kf6-kguiaddons",
|
||||
]
|
||||
script = """
|
||||
DYNAMIC_INIT
|
||||
@@ -27,44 +19,35 @@ for qtdir in plugins mkspecs metatypes modules; do
|
||||
fi
|
||||
done
|
||||
|
||||
STAGE="${COOKBOOK_STAGE}/usr"
|
||||
mkdir -p "${STAGE}/lib/cmake/KF6Kirigami"
|
||||
mkdir -p "${STAGE}/lib/cmake/KF6Kirigami2"
|
||||
sed -i 's/COMPONENTS Core Gui Concurrent Qml Quick Qml Quick Qml Quick/COMPONENTS Core Gui Concurrent/' \
|
||||
"${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||
sed -i 's/^ find_package(Qt6QuickTest .*/# find_package(Qt6QuickTest disabled for Redox core-only build)/' \
|
||||
"${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||
sed -i 's/^ add_subdirectory(templates)/# add_subdirectory(templates) # disabled for Redox core-only build/' \
|
||||
"${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||
sed -i 's/^ add_subdirectory(autotests)/# add_subdirectory(autotests) # disabled for Redox core-only build/' \
|
||||
"${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||
|
||||
cat > "${STAGE}/lib/cmake/KF6Kirigami/KF6KirigamiConfig.cmake" << 'EOFCFG'
|
||||
add_library(KF6::Kirigami INTERFACE)
|
||||
EOFCFG
|
||||
rm -f CMakeCache.txt
|
||||
rm -rf CMakeFiles
|
||||
|
||||
cat > "${STAGE}/lib/cmake/KF6Kirigami/KF6KirigamiConfigVersion.cmake" << 'EOFVER'
|
||||
set(PACKAGE_VERSION "6.10.0")
|
||||
set(PACKAGE_VERSIONCompatible TRUE)
|
||||
EOFVER
|
||||
cmake "${COOKBOOK_SOURCE}" \
|
||||
-DCMAKE_TOOLCHAIN_FILE="${COOKBOOK_ROOT}/local/recipes/qt/redox-toolchain.cmake" \
|
||||
-DQT_HOST_PATH="${HOST_BUILD}" \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH="${COOKBOOK_SYSROOT}:${COOKBOOK_STAGE}/usr/lib/cmake" \
|
||||
-DBUILD_TESTING=OFF \
|
||||
-DBUILD_QCH=OFF \
|
||||
-DBUILD_EXAMPLES=OFF \
|
||||
-DUSE_DBUS=OFF \
|
||||
-Wno-dev
|
||||
|
||||
cat > "${STAGE}/lib/cmake/KF6Kirigami/KF6KirigamiTargets.cmake" << 'EOFTGT'
|
||||
add_library(KF6::Kirigami INTERFACE)
|
||||
EOFTGT
|
||||
cmake --build . -j${COOKBOOK_MAKE_JOBS}
|
||||
cmake --install . --prefix "${COOKBOOK_STAGE}/usr"
|
||||
|
||||
cat > "${STAGE}/lib/cmake/KF6Kirigami2/KF6Kirigami2Config.cmake" << 'EOFCFG2'
|
||||
add_library(KF6::Kirigami2 INTERFACE)
|
||||
EOFCFG2
|
||||
|
||||
cat > "${STAGE}/lib/cmake/KF6Kirigami2/KF6Kirigami2ConfigVersion.cmake" << 'EOFVER2'
|
||||
set(PACKAGE_VERSION "6.10.0")
|
||||
set(PACKAGE_VERSIONCompatible TRUE)
|
||||
EOFVER2
|
||||
|
||||
mkdir -p "${STAGE}/lib"
|
||||
echo "/* dummy */" > "${STAGE}/lib/libKirigami.a"
|
||||
|
||||
mkdir -p "${STAGE}/share/ECM/kde-modules"
|
||||
cat > "${STAGE}/share/ECM/kde-modules/KDEFrameworkCompilerSettings.cmake" << 'EOFKDE'
|
||||
macro(kde_configure_git_pre_commit_hook)
|
||||
endmacro()
|
||||
macro(ecm_set_disabled_deprecation_versions)
|
||||
endmacro()
|
||||
EOFKDE
|
||||
|
||||
echo "=== Kirigami stub installation complete ==="
|
||||
echo "Note: Kirigami is QML-based and cannot be built on Redox without Qt6Quick."
|
||||
echo "Dummy cmake configs installed for dependency resolution."
|
||||
for lib in "${COOKBOOK_STAGE}/usr/lib/"libKirigami*.so.* "${COOKBOOK_STAGE}/usr/lib/"libKF6*.so.*; do
|
||||
[ -f "${lib}" ] || continue
|
||||
patchelf --remove-rpath "${lib}" 2>/dev/null || true
|
||||
done
|
||||
"""
|
||||
|
||||
+80
-25
@@ -66,11 +66,16 @@ fn read_wayland_string(data: &[u8], cursor: &mut usize) -> Result<String, String
|
||||
return Ok(String::new());
|
||||
}
|
||||
if *cursor + length > data.len() {
|
||||
return Err(String::from("unexpected end of message while reading string"));
|
||||
return Err(String::from(
|
||||
"unexpected end of message while reading string",
|
||||
));
|
||||
}
|
||||
|
||||
let bytes = &data[*cursor..*cursor + length];
|
||||
let string_len = bytes.iter().position(|byte| *byte == 0).unwrap_or(bytes.len());
|
||||
let string_len = bytes
|
||||
.iter()
|
||||
.position(|byte| *byte == 0)
|
||||
.unwrap_or(bytes.len());
|
||||
*cursor += length;
|
||||
while *cursor % 4 != 0 {
|
||||
*cursor += 1;
|
||||
@@ -139,11 +144,10 @@ impl WaylandProbe {
|
||||
iov_base: msg.as_mut_ptr().cast(),
|
||||
iov_len: msg.len(),
|
||||
};
|
||||
let control_len = unsafe {
|
||||
libc::CMSG_SPACE((fds.len() * mem::size_of::<i32>()) as u32) as usize
|
||||
};
|
||||
let control_len =
|
||||
unsafe { libc::CMSG_SPACE((fds.len() * mem::size_of::<i32>()) as u32) as usize };
|
||||
let mut control = vec![0u8; control_len];
|
||||
let mut header = libc::msghdr {
|
||||
let header = libc::msghdr {
|
||||
msg_name: std::ptr::null_mut(),
|
||||
msg_namelen: 0,
|
||||
msg_iov: &mut iov,
|
||||
@@ -170,10 +174,17 @@ impl WaylandProbe {
|
||||
|
||||
let written = unsafe { libc::sendmsg(self.stream.as_raw_fd(), &header, 0) };
|
||||
if written < 0 {
|
||||
return Err(format!("sendmsg failed: {}", std::io::Error::last_os_error()));
|
||||
return Err(format!(
|
||||
"sendmsg failed: {}",
|
||||
std::io::Error::last_os_error()
|
||||
));
|
||||
}
|
||||
if written as usize != msg.len() {
|
||||
return Err(format!("short sendmsg write: expected {}, got {}", msg.len(), written));
|
||||
return Err(format!(
|
||||
"short sendmsg write: expected {}, got {}",
|
||||
msg.len(),
|
||||
written
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -209,7 +220,13 @@ impl WaylandProbe {
|
||||
Ok(registry_id)
|
||||
}
|
||||
|
||||
fn bind(&mut self, registry_id: u32, name: u32, interface: &str, version: u32) -> Result<u32, String> {
|
||||
fn bind(
|
||||
&mut self,
|
||||
registry_id: u32,
|
||||
name: u32,
|
||||
interface: &str,
|
||||
version: u32,
|
||||
) -> Result<u32, String> {
|
||||
let new_id = self.alloc_id();
|
||||
let mut payload = Vec::new();
|
||||
push_u32(&mut payload, name);
|
||||
@@ -257,7 +274,9 @@ fn expect_shm_formats(probe: &mut WaylandProbe, shm_id: u32) -> Result<(), Strin
|
||||
payload.len()
|
||||
));
|
||||
}
|
||||
formats.push(u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]));
|
||||
formats.push(u32::from_le_bytes([
|
||||
payload[0], payload[1], payload[2], payload[3],
|
||||
]));
|
||||
}
|
||||
|
||||
if !formats.contains(&0) || !formats.contains(&1) {
|
||||
@@ -267,7 +286,11 @@ fn expect_shm_formats(probe: &mut WaylandProbe, shm_id: u32) -> Result<(), Strin
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn expect_xdg_configure(probe: &mut WaylandProbe, toplevel_id: u32, xdg_surface_id: u32) -> Result<u32, String> {
|
||||
fn expect_xdg_configure(
|
||||
probe: &mut WaylandProbe,
|
||||
toplevel_id: u32,
|
||||
xdg_surface_id: u32,
|
||||
) -> Result<u32, String> {
|
||||
let (object_id, opcode, payload) = probe.read_message()?;
|
||||
if object_id != toplevel_id || opcode != XDG_TOPLEVEL_CONFIGURE {
|
||||
return Err(format!(
|
||||
@@ -276,18 +299,26 @@ fn expect_xdg_configure(probe: &mut WaylandProbe, toplevel_id: u32, xdg_surface_
|
||||
));
|
||||
}
|
||||
if payload.len() < 12 {
|
||||
return Err(format!("short xdg_toplevel.configure payload: {} bytes", payload.len()));
|
||||
return Err(format!(
|
||||
"short xdg_toplevel.configure payload: {} bytes",
|
||||
payload.len()
|
||||
));
|
||||
}
|
||||
|
||||
let states_len = u32::from_le_bytes([payload[8], payload[9], payload[10], payload[11]]) as usize;
|
||||
let states_len =
|
||||
u32::from_le_bytes([payload[8], payload[9], payload[10], payload[11]]) as usize;
|
||||
if payload.len() != 12 + states_len {
|
||||
return Err(format!(
|
||||
"invalid xdg_toplevel.configure payload length: {} (states_len={})",
|
||||
payload.len(), states_len
|
||||
payload.len(),
|
||||
states_len
|
||||
));
|
||||
}
|
||||
if states_len % 4 != 0 {
|
||||
return Err(format!("invalid xdg_toplevel.configure states array length: {}", states_len));
|
||||
return Err(format!(
|
||||
"invalid xdg_toplevel.configure states array length: {}",
|
||||
states_len
|
||||
));
|
||||
}
|
||||
|
||||
let (object_id, opcode, payload) = probe.read_message()?;
|
||||
@@ -300,7 +331,9 @@ fn expect_xdg_configure(probe: &mut WaylandProbe, toplevel_id: u32, xdg_surface_
|
||||
));
|
||||
}
|
||||
|
||||
Ok(u32::from_le_bytes([payload[0], payload[1], payload[2], payload[3]]))
|
||||
Ok(u32::from_le_bytes([
|
||||
payload[0], payload[1], payload[2], payload[3],
|
||||
]))
|
||||
}
|
||||
|
||||
fn exercise_shm_pool(probe: &mut WaylandProbe, shm_id: u32, surface_id: u32) -> Result<(), String> {
|
||||
@@ -320,8 +353,11 @@ fn exercise_shm_pool(probe: &mut WaylandProbe, shm_id: u32, surface_id: u32) ->
|
||||
.map_err(|err| format!("failed to size temp SHM file: {err}"))?;
|
||||
|
||||
let mut file = file;
|
||||
file.write_all(&[0x40, 0x40, 0xFF, 0xFF, 0x40, 0x40, 0xFF, 0xFF, 0x40, 0x40, 0xFF, 0xFF, 0x40, 0x40, 0xFF, 0xFF])
|
||||
.map_err(|err| format!("failed to seed temp SHM file: {err}"))?;
|
||||
file.write_all(&[
|
||||
0x40, 0x40, 0xFF, 0xFF, 0x40, 0x40, 0xFF, 0xFF, 0x40, 0x40, 0xFF, 0xFF, 0x40, 0x40, 0xFF,
|
||||
0xFF,
|
||||
])
|
||||
.map_err(|err| format!("failed to seed temp SHM file: {err}"))?;
|
||||
|
||||
let pool_id = probe.alloc_id();
|
||||
let mut payload = Vec::new();
|
||||
@@ -363,7 +399,8 @@ fn exercise_shm_pool(probe: &mut WaylandProbe, shm_id: u32, surface_id: u32) ->
|
||||
}
|
||||
|
||||
fn check_wayland_socket() -> Result<(), String> {
|
||||
let runtime_dir = std::env::var("XDG_RUNTIME_DIR").unwrap_or_else(|_| "/tmp/run/redbear-greeter".into());
|
||||
let runtime_dir =
|
||||
std::env::var("XDG_RUNTIME_DIR").unwrap_or_else(|_| "/tmp/run/redbear-greeter".into());
|
||||
let display = std::env::var("WAYLAND_DISPLAY").unwrap_or_else(|_| "wayland-0".into());
|
||||
let socket_path = format!("{}/{}", runtime_dir, display);
|
||||
|
||||
@@ -388,7 +425,11 @@ fn check_wayland_socket() -> Result<(), String> {
|
||||
expect_shm_formats(&mut probe, shm_id)?;
|
||||
|
||||
let surface_id = probe.alloc_id();
|
||||
probe.send_message(compositor_id, WL_COMPOSITOR_CREATE_SURFACE, &surface_id.to_le_bytes())?;
|
||||
probe.send_message(
|
||||
compositor_id,
|
||||
WL_COMPOSITOR_CREATE_SURFACE,
|
||||
&surface_id.to_le_bytes(),
|
||||
)?;
|
||||
|
||||
let xdg_surface_id = probe.alloc_id();
|
||||
let mut payload = Vec::new();
|
||||
@@ -397,9 +438,17 @@ fn check_wayland_socket() -> Result<(), String> {
|
||||
probe.send_message(xdg_wm_base_id, XDG_WM_BASE_GET_XDG_SURFACE, &payload)?;
|
||||
|
||||
let toplevel_id = probe.alloc_id();
|
||||
probe.send_message(xdg_surface_id, XDG_SURFACE_GET_TOPLEVEL, &toplevel_id.to_le_bytes())?;
|
||||
probe.send_message(
|
||||
xdg_surface_id,
|
||||
XDG_SURFACE_GET_TOPLEVEL,
|
||||
&toplevel_id.to_le_bytes(),
|
||||
)?;
|
||||
let serial = expect_xdg_configure(&mut probe, toplevel_id, xdg_surface_id)?;
|
||||
probe.send_message(xdg_surface_id, XDG_SURFACE_ACK_CONFIGURE, &serial.to_le_bytes())?;
|
||||
probe.send_message(
|
||||
xdg_surface_id,
|
||||
XDG_SURFACE_ACK_CONFIGURE,
|
||||
&serial.to_le_bytes(),
|
||||
)?;
|
||||
|
||||
exercise_shm_pool(&mut probe, shm_id, surface_id)
|
||||
}
|
||||
@@ -430,11 +479,17 @@ fn check_framebuffer() -> Result<(), String> {
|
||||
let addr = std::env::var("FRAMEBUFFER_ADDR").unwrap_or_default();
|
||||
|
||||
if width.is_empty() || height.is_empty() || addr.is_empty() {
|
||||
return Err("FRAMEBUFFER_* environment not set — bootloader didn't provide framebuffer".into());
|
||||
return Err(
|
||||
"FRAMEBUFFER_* environment not set — bootloader didn't provide framebuffer".into(),
|
||||
);
|
||||
}
|
||||
|
||||
let w: u32 = width.parse().map_err(|_| format!("invalid FRAMEBUFFER_WIDTH: {}", width))?;
|
||||
let h: u32 = height.parse().map_err(|_| format!("invalid FRAMEBUFFER_HEIGHT: {}", height))?;
|
||||
let w: u32 = width
|
||||
.parse()
|
||||
.map_err(|_| format!("invalid FRAMEBUFFER_WIDTH: {}", width))?;
|
||||
let h: u32 = height
|
||||
.parse()
|
||||
.map_err(|_| format!("invalid FRAMEBUFFER_HEIGHT: {}", height))?;
|
||||
|
||||
if w == 0 || h == 0 {
|
||||
return Err("framebuffer dimensions are zero".into());
|
||||
|
||||
Reference in New Issue
Block a user