diff --git a/userland/capsule_desktop_shell/src/compositor_client/mod.rs b/userland/capsule_desktop_shell/src/compositor_client/mod.rs
index f8a61ae0d..89ac53295 100644
--- a/userland/capsule_desktop_shell/src/compositor_client/mod.rs
+++ b/userland/capsule_desktop_shell/src/compositor_client/mod.rs
@@ -15,10 +15,8 @@
// along with this program. If not, see .
pub mod damage_commit;
-pub mod health;
pub mod scene_submit;
pub mod wire;
pub use damage_commit::push_damage_commit;
-pub use health::probe as probe_compositor;
pub use scene_submit::push_scene_submit;
diff --git a/userland/capsule_desktop_shell/src/main.rs b/userland/capsule_desktop_shell/src/main.rs
index 127e07639..13b68670b 100644
--- a/userland/capsule_desktop_shell/src/main.rs
+++ b/userland/capsule_desktop_shell/src/main.rs
@@ -21,11 +21,14 @@ extern crate alloc;
mod compositor_client;
mod debug;
+mod market_client;
mod protocol;
mod render;
mod server;
mod setup;
mod state;
+mod wallpaper_client;
+mod wm_client;
use nonos_libc::{heap_init, mk_exit};
diff --git a/userland/capsule_desktop_shell/src/market_client/mod.rs b/userland/capsule_desktop_shell/src/market_client/mod.rs
new file mode 100644
index 000000000..d043ce38d
--- /dev/null
+++ b/userland/capsule_desktop_shell/src/market_client/mod.rs
@@ -0,0 +1,31 @@
+use alloc::vec;
+use alloc::vec::Vec;
+
+use nonos_libc::mk_ipc_call;
+
+const MAGIC: u32 = 0x4E4D_4B54;
+const VERSION: u16 = 1;
+const HDR_LEN: usize = 20;
+const STATUS_LEN: usize = 4;
+const OP_HEALTHCHECK: u16 = 0x0006;
+
+pub fn healthcheck(port: u32, request_id: u32) -> Result {
+ if port == 0 {
+ return Ok(0);
+ }
+ let mut tx = Vec::with_capacity(HDR_LEN);
+ tx.extend_from_slice(&MAGIC.to_le_bytes());
+ tx.extend_from_slice(&VERSION.to_le_bytes());
+ tx.extend_from_slice(&OP_HEALTHCHECK.to_le_bytes());
+ tx.extend_from_slice(&0u16.to_le_bytes());
+ tx.extend_from_slice(&0u16.to_le_bytes());
+ tx.extend_from_slice(&request_id.to_le_bytes());
+ tx.extend_from_slice(&0u32.to_le_bytes());
+
+ let mut rx = vec![0u8; HDR_LEN + STATUS_LEN];
+ let rc = mk_ipc_call(port as u64, tx.as_ptr(), tx.len(), rx.as_mut_ptr(), rx.len());
+ if rc < (HDR_LEN + STATUS_LEN) as i64 {
+ return Err("market call failed");
+ }
+ Ok(i32::from_le_bytes(rx[HDR_LEN..HDR_LEN + STATUS_LEN].try_into().unwrap()))
+}
diff --git a/userland/capsule_desktop_shell/src/setup/discover.rs b/userland/capsule_desktop_shell/src/setup/discover.rs
index 2d42bc282..3a87d489b 100644
--- a/userland/capsule_desktop_shell/src/setup/discover.rs
+++ b/userland/capsule_desktop_shell/src/setup/discover.rs
@@ -17,18 +17,37 @@
use nonos_libc::mk_service_lookup;
const COMPOSITOR_SERVICE: &[u8] = b"compositor";
+const WM_SERVICE: &[u8] = b"wm";
+const WALLPAPER_SERVICE: &[u8] = b"wallpaper";
+const MARKET_SERVICE: &[u8] = b"market.index";
-pub fn require_compositor() -> Result {
+fn lookup_port(name: &[u8]) -> Result {
let mut pid: u32 = 0;
let mut port: u32 = 0;
let rc = mk_service_lookup(
- COMPOSITOR_SERVICE.as_ptr(),
- COMPOSITOR_SERVICE.len(),
+ name.as_ptr(),
+ name.len(),
&mut port as *mut u32,
&mut pid as *mut u32,
);
if rc < 0 || pid == 0 || port == 0 {
- return Err("compositor service not announced");
+ return Err("service not announced");
}
Ok(port)
}
+
+pub fn require_compositor() -> Result {
+ lookup_port(COMPOSITOR_SERVICE).map_err(|_| "compositor service not announced")
+}
+
+pub fn require_wm() -> Result {
+ lookup_port(WM_SERVICE).map_err(|_| "wm service not announced")
+}
+
+pub fn require_wallpaper() -> Result {
+ lookup_port(WALLPAPER_SERVICE).map_err(|_| "wallpaper service not announced")
+}
+
+pub fn try_market() -> u32 {
+ lookup_port(MARKET_SERVICE).unwrap_or(0)
+}
diff --git a/userland/capsule_desktop_shell/src/setup/mod.rs b/userland/capsule_desktop_shell/src/setup/mod.rs
index 7d87f3464..7197206f2 100644
--- a/userland/capsule_desktop_shell/src/setup/mod.rs
+++ b/userland/capsule_desktop_shell/src/setup/mod.rs
@@ -16,6 +16,5 @@
mod discover;
mod prime;
-mod retry;
-pub use retry::run;
+pub use prime::run;
diff --git a/userland/capsule_desktop_shell/src/setup/prime.rs b/userland/capsule_desktop_shell/src/setup/prime.rs
index dc465db8e..de3af1b85 100644
--- a/userland/capsule_desktop_shell/src/setup/prime.rs
+++ b/userland/capsule_desktop_shell/src/setup/prime.rs
@@ -20,17 +20,22 @@ use nonos_libc::{
};
use super::discover;
-use crate::compositor_client::{probe_compositor, push_scene_submit};
+use crate::compositor_client::push_scene_submit;
+use crate::market_client;
use crate::render::paint_chrome;
use crate::state::{Context, SpotlightState, TrayTable};
+use crate::wallpaper_client;
+use crate::wm_client;
const PROT_READ_WRITE: i32 = 0x3;
const MAP_PRIVATE_ANON: i32 = 0x22;
const OVERLAY_Z: u32 = 1;
-pub fn run_once() -> Result {
+pub fn run() -> Result {
let compositor_port = discover::require_compositor()?;
- probe_compositor(compositor_port, 1)?;
+ let wm_port = discover::require_wm()?;
+ let wallpaper_port = discover::require_wallpaper()?;
+ let market_port = discover::try_market();
let mut width: u32 = 0;
let mut height: u32 = 0;
let rc = nonos_display_dimensions(0, &mut width as *mut u32, &mut height as *mut u32);
@@ -55,6 +60,9 @@ pub fn run_once() -> Result {
let backing_va = base as u64;
let mut ctx = Context {
compositor_port,
+ wm_port,
+ wallpaper_port,
+ market_port,
width,
height,
stride,
@@ -84,5 +92,8 @@ pub fn run_once() -> Result {
}
let rid = ctx.issue_request_id();
push_scene_submit(compositor_port, rid, handle as u64, 0, 0, width, height, OVERLAY_Z)?;
+ let _ = wm_client::healthcheck(ctx.wm_port, ctx.issue_request_id());
+ let _ = wallpaper_client::set_policy(ctx.wallpaper_port, ctx.issue_request_id(), 0);
+ let _ = market_client::healthcheck(ctx.market_port, ctx.issue_request_id());
Ok(ctx)
}
diff --git a/userland/capsule_desktop_shell/src/state/context.rs b/userland/capsule_desktop_shell/src/state/context.rs
index 8e0e6cb59..f50dfc83a 100644
--- a/userland/capsule_desktop_shell/src/state/context.rs
+++ b/userland/capsule_desktop_shell/src/state/context.rs
@@ -18,6 +18,9 @@ use super::{NotifyLevel, SpotlightState, TrayTable};
pub struct Context {
pub compositor_port: u32,
+ pub wm_port: u32,
+ pub wallpaper_port: u32,
+ pub market_port: u32,
pub width: u32,
pub height: u32,
pub stride: u32,
diff --git a/userland/capsule_desktop_shell/src/wallpaper_client/mod.rs b/userland/capsule_desktop_shell/src/wallpaper_client/mod.rs
new file mode 100644
index 000000000..968d37957
--- /dev/null
+++ b/userland/capsule_desktop_shell/src/wallpaper_client/mod.rs
@@ -0,0 +1,29 @@
+use alloc::vec;
+use alloc::vec::Vec;
+
+use nonos_libc::mk_ipc_call;
+
+const MAGIC: u32 = 0x4E57_4C50;
+const VERSION: u16 = 1;
+const HDR_LEN: usize = 20;
+const STATUS_LEN: usize = 4;
+const OP_SET_POLICY: u16 = 0x0004;
+
+pub fn set_policy(port: u32, request_id: u32, policy: u32) -> Result {
+ let mut tx = Vec::with_capacity(HDR_LEN + 4);
+ tx.extend_from_slice(&MAGIC.to_le_bytes());
+ tx.extend_from_slice(&VERSION.to_le_bytes());
+ tx.extend_from_slice(&OP_SET_POLICY.to_le_bytes());
+ tx.extend_from_slice(&0u16.to_le_bytes());
+ tx.extend_from_slice(&0u16.to_le_bytes());
+ tx.extend_from_slice(&request_id.to_le_bytes());
+ tx.extend_from_slice(&4u32.to_le_bytes());
+ tx.extend_from_slice(&policy.to_le_bytes());
+
+ let mut rx = vec![0u8; HDR_LEN + STATUS_LEN];
+ let rc = mk_ipc_call(port as u64, tx.as_ptr(), tx.len(), rx.as_mut_ptr(), rx.len());
+ if rc < (HDR_LEN + STATUS_LEN) as i64 {
+ return Err("wallpaper call failed");
+ }
+ Ok(i32::from_le_bytes(rx[HDR_LEN..HDR_LEN + STATUS_LEN].try_into().unwrap()))
+}
diff --git a/userland/capsule_desktop_shell/src/wm_client/mod.rs b/userland/capsule_desktop_shell/src/wm_client/mod.rs
new file mode 100644
index 000000000..4dd757025
--- /dev/null
+++ b/userland/capsule_desktop_shell/src/wm_client/mod.rs
@@ -0,0 +1,28 @@
+use alloc::vec;
+use alloc::vec::Vec;
+
+use nonos_libc::mk_ipc_call;
+
+const MAGIC: u32 = 0x4E57_4D50;
+const VERSION: u16 = 1;
+const HDR_LEN: usize = 20;
+const STATUS_LEN: usize = 4;
+const OP_HEALTHCHECK: u16 = 0x0001;
+
+pub fn healthcheck(port: u32, request_id: u32) -> Result {
+ let mut tx = Vec::with_capacity(HDR_LEN);
+ tx.extend_from_slice(&MAGIC.to_le_bytes());
+ tx.extend_from_slice(&VERSION.to_le_bytes());
+ tx.extend_from_slice(&OP_HEALTHCHECK.to_le_bytes());
+ tx.extend_from_slice(&0u16.to_le_bytes());
+ tx.extend_from_slice(&0u16.to_le_bytes());
+ tx.extend_from_slice(&request_id.to_le_bytes());
+ tx.extend_from_slice(&0u32.to_le_bytes());
+
+ let mut rx = vec![0u8; HDR_LEN + STATUS_LEN];
+ let rc = mk_ipc_call(port as u64, tx.as_ptr(), tx.len(), rx.as_mut_ptr(), rx.len());
+ if rc < (HDR_LEN + STATUS_LEN) as i64 {
+ return Err("wm call failed");
+ }
+ Ok(i32::from_le_bytes(rx[HDR_LEN..HDR_LEN + STATUS_LEN].try_into().unwrap()))
+}
diff --git a/userland/capsule_wallpaper/Cargo.lock b/userland/capsule_wallpaper/Cargo.lock
index c12eceb28..8a3c966e9 100644
--- a/userland/capsule_wallpaper/Cargo.lock
+++ b/userland/capsule_wallpaper/Cargo.lock
@@ -23,6 +23,14 @@ dependencies = [
[[package]]
name = "nonos_capsule_wallpaper"
version = "0.1.0"
+dependencies = [
+ "nonos_toolkit",
+ "nonos_userland_libc",
+]
+
+[[package]]
+name = "nonos_toolkit"
+version = "0.1.0"
dependencies = [
"nonos_userland_libc",
]
diff --git a/userland/capsule_wallpaper/Cargo.toml b/userland/capsule_wallpaper/Cargo.toml
index 30de1154f..0ff52aa1c 100644
--- a/userland/capsule_wallpaper/Cargo.toml
+++ b/userland/capsule_wallpaper/Cargo.toml
@@ -24,6 +24,7 @@ path = "src/main.rs"
[dependencies]
nonos_libc = { package = "nonos_userland_libc", path = "../libc" }
+nonos_toolkit = { path = "../toolkit" }
[profile.release]
panic = "abort"
diff --git a/userland/capsule_wallpaper/src/decode_client/header.rs b/userland/capsule_wallpaper/src/decode_client/header.rs
new file mode 100644
index 000000000..70463caa4
--- /dev/null
+++ b/userland/capsule_wallpaper/src/decode_client/header.rs
@@ -0,0 +1,55 @@
+// NONOS Operating System
+// Copyright (C) 2026 NONOS Contributors
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::protocol::E_INVAL;
+
+pub const DECODE_HDR_LEN: usize = 16;
+
+#[derive(Clone, Copy)]
+pub enum DecodeKind {
+ Png,
+ Bmp,
+ Lz4Raw,
+ Jpeg,
+}
+
+pub struct DecodeReq<'a> {
+ pub kind: DecodeKind,
+ pub width: u32,
+ pub height: u32,
+ pub payload: &'a [u8],
+}
+
+pub fn parse_decode_req(body: &[u8]) -> Result, i32> {
+ if body.len() < DECODE_HDR_LEN {
+ return Err(E_INVAL);
+ }
+ let kind_raw = u32::from_le_bytes(body[0..4].try_into().unwrap());
+ let width = u32::from_le_bytes(body[4..8].try_into().unwrap());
+ let height = u32::from_le_bytes(body[8..12].try_into().unwrap());
+ let payload_len = u32::from_le_bytes(body[12..16].try_into().unwrap()) as usize;
+ if body.len() != DECODE_HDR_LEN + payload_len {
+ return Err(E_INVAL);
+ }
+ let kind = match kind_raw {
+ 1 => DecodeKind::Png,
+ 2 => DecodeKind::Bmp,
+ 3 => DecodeKind::Lz4Raw,
+ 4 => DecodeKind::Jpeg,
+ _ => return Err(E_INVAL),
+ };
+ Ok(DecodeReq { kind, width, height, payload: &body[DECODE_HDR_LEN..] })
+}
diff --git a/userland/capsule_desktop_shell/src/compositor_client/health.rs b/userland/capsule_wallpaper/src/decode_client/mod.rs
similarity index 72%
rename from userland/capsule_desktop_shell/src/compositor_client/health.rs
rename to userland/capsule_wallpaper/src/decode_client/mod.rs
index 85270b4ca..2f1deaf83 100644
--- a/userland/capsule_desktop_shell/src/compositor_client/health.rs
+++ b/userland/capsule_wallpaper/src/decode_client/mod.rs
@@ -14,14 +14,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use super::wire::call;
+pub mod header;
+pub mod seq;
+pub mod wire;
-const OP: u16 = 0x0001;
-
-pub fn probe(compositor_port: u32, request_id: u32) -> Result<(), &'static str> {
- let status = call(compositor_port, OP, request_id, &[])?;
- if status != 0 {
- return Err("compositor health rejected");
- }
- Ok(())
-}
+pub use seq::decode_and_paint;
diff --git a/userland/capsule_wallpaper/src/decode_client/seq.rs b/userland/capsule_wallpaper/src/decode_client/seq.rs
new file mode 100644
index 000000000..edc105ee6
--- /dev/null
+++ b/userland/capsule_wallpaper/src/decode_client/seq.rs
@@ -0,0 +1,60 @@
+// NONOS Operating System
+// Copyright (C) 2026 NONOS Contributors
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use alloc::vec;
+
+use super::{header::parse_decode_req, wire::decode_argb};
+use crate::{protocol::E_INVAL, state::Context};
+
+pub fn decode_and_paint(ctx: &Context, body: &[u8]) -> Result<(), i32> {
+ let req = parse_decode_req(body)?;
+ let cap = (ctx.width as usize).saturating_mul(ctx.height as usize);
+ let mut decoded = vec![0u32; cap];
+ let size = decode_argb(&req, &mut decoded).map_err(|_| E_INVAL)?;
+ paint_stretch(
+ ctx.backing_va,
+ ctx.stride as usize,
+ ctx.width as usize,
+ ctx.height as usize,
+ &decoded,
+ size.width as usize,
+ size.height as usize,
+ );
+ Ok(())
+}
+
+fn paint_stretch(
+ base_va: u64,
+ stride: usize,
+ dst_w: usize,
+ dst_h: usize,
+ src: &[u32],
+ src_w: usize,
+ src_h: usize,
+) {
+ if src_w == 0 || src_h == 0 || dst_w == 0 || dst_h == 0 {
+ return;
+ }
+ for y in 0..dst_h {
+ let sy = (y * src_h) / dst_h;
+ for x in 0..dst_w {
+ let sx = (x * src_w) / dst_w;
+ let px = src[sy * src_w + sx];
+ let addr = (base_va as usize + y * stride + x * 4) as *mut u32;
+ unsafe { core::ptr::write_volatile(addr, px) };
+ }
+ }
+}
diff --git a/userland/capsule_desktop_shell/src/setup/retry.rs b/userland/capsule_wallpaper/src/decode_client/wire.rs
similarity index 53%
rename from userland/capsule_desktop_shell/src/setup/retry.rs
rename to userland/capsule_wallpaper/src/decode_client/wire.rs
index bbbeb6fa0..e651b81cd 100644
--- a/userland/capsule_desktop_shell/src/setup/retry.rs
+++ b/userland/capsule_wallpaper/src/decode_client/wire.rs
@@ -14,23 +14,21 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use nonos_libc::mk_yield;
+use nonos_toolkit::image::{
+ bmp::decode_bmp_argb8888,
+ jpeg::decode_jpeg_argb8888,
+ lz4_raw::decode_lz4_raw_argb8888,
+ png::decoder::decode_png_argb8888,
+ types::{DecodeError, ImageSize},
+};
-use super::prime;
-use crate::state::Context;
+use super::header::{DecodeKind, DecodeReq};
-const READY_ATTEMPTS: usize = 256;
-
-pub fn run() -> Result {
- let mut last_err = "compositor unavailable";
- for _ in 0..READY_ATTEMPTS {
- match prime::run_once() {
- Ok(ctx) => return Ok(ctx),
- Err(e) => {
- last_err = e;
- mk_yield();
- }
- }
+pub fn decode_argb(req: &DecodeReq<'_>, out: &mut [u32]) -> Result {
+ match req.kind {
+ DecodeKind::Png => decode_png_argb8888(req.payload, out),
+ DecodeKind::Bmp => decode_bmp_argb8888(req.payload, out),
+ DecodeKind::Lz4Raw => decode_lz4_raw_argb8888(req.width, req.height, req.payload, out),
+ DecodeKind::Jpeg => decode_jpeg_argb8888(req.payload, out),
}
- Err(last_err)
}
diff --git a/userland/capsule_wallpaper/src/main.rs b/userland/capsule_wallpaper/src/main.rs
index 18c1bc00b..af7001683 100644
--- a/userland/capsule_wallpaper/src/main.rs
+++ b/userland/capsule_wallpaper/src/main.rs
@@ -17,80 +17,27 @@
#![no_std]
#![no_main]
-use nonos_libc::{
- mk_debug, mk_exit, nonos_display_dimensions, nonos_surface_create, nonos_surface_destroy,
- nonos_surface_map, nonos_surface_present_full, NONOS_PIXEL_FMT_ARGB8888,
-};
+extern crate alloc;
-const SOLID_ARGB: u32 = 0xFF20_2030;
-const ENOTSUP: i64 = -95;
+mod compositor_client;
+mod decode_client;
+mod debug;
+mod paint;
+mod protocol;
+mod server;
+mod setup;
+mod state;
-fn marker(stage: &[u8]) {
- let mut buf = [0u8; 64];
- let prefix = b"[wallpaper] ";
- let mut n = 0usize;
- let cap = buf.len() - 1;
- for &b in prefix.iter().chain(stage.iter()) {
- if n >= cap {
- break;
- }
- buf[n] = b;
- n += 1;
- }
- buf[n] = b'\n';
- n += 1;
- let _ = mk_debug(buf.as_ptr(), n);
-}
+use nonos_libc::{heap_init, mk_exit};
#[no_mangle]
pub unsafe extern "C" fn _start() -> ! {
- let mut w: u32 = 0;
- let mut h: u32 = 0;
- let rc = nonos_display_dimensions(0, &mut w as *mut u32, &mut h as *mut u32);
- if rc == ENOTSUP {
- marker(b"graphics parked");
- marker(b"PASS");
- mk_exit(0);
- }
- if rc != 0 || w == 0 || h == 0 {
- marker(b"FAIL display_dimensions");
+ if heap_init().is_err() {
mk_exit(1);
}
- marker(b"display ok");
-
- let id = nonos_surface_create(w, h, NONOS_PIXEL_FMT_ARGB8888);
- if id < 0 {
- marker(b"FAIL surface_create");
+ let Ok(ctx) = setup::run() else {
+ debug::marker(b"setup failed");
mk_exit(2);
- }
- marker(b"surface created");
-
- let base = nonos_surface_map(id as u64);
- if base.is_null() {
- marker(b"FAIL surface_map");
- let _ = nonos_surface_destroy(id as u64);
- mk_exit(3);
- }
- let pixels = base as *mut u32;
- let count = (w as usize) * (h as usize);
- for i in 0..count {
- core::ptr::write_volatile(pixels.add(i), SOLID_ARGB);
- }
- marker(b"surface filled");
-
- let prc = nonos_surface_present_full(0, id as u64);
- if prc != 0 {
- marker(b"FAIL surface_present");
- let _ = nonos_surface_destroy(id as u64);
- mk_exit(4);
- }
- marker(b"present ok");
-
- let drc = nonos_surface_destroy(id as u64);
- if drc != 0 {
- marker(b"FAIL surface_destroy");
- mk_exit(5);
- }
- marker(b"PASS");
- mk_exit(0)
+ };
+ server::run(ctx);
}
diff --git a/userland/capsule_wallpaper/src/server/handlers/fade.rs b/userland/capsule_wallpaper/src/server/handlers/fade.rs
index a80d61386..2ca447497 100644
--- a/userland/capsule_wallpaper/src/server/handlers/fade.rs
+++ b/userland/capsule_wallpaper/src/server/handlers/fade.rs
@@ -16,6 +16,8 @@
use nonos_libc::mk_display_vsync_wait;
+use crate::compositor_client::push_damage_commit;
+use crate::paint::fill_argb;
use crate::protocol::{Request, E_INVAL, FADE_REQ_LEN};
use crate::server::respond;
use crate::state::Context;
@@ -35,5 +37,12 @@ pub fn handle(ctx: &mut Context, sender_pid: u32, req: &Request, body: &[u8], tx
let now_ns = if now > 0 { now as u64 } else { 0 };
let duration_ns = (duration_ms as u64).saturating_mul(1_000_000);
ctx.fade.start(ctx.alpha, target_alpha as u8, now_ns, duration_ns);
+ if duration_ns == 0 {
+ ctx.alpha = target_alpha as u8;
+ let argb = ctx.current_argb();
+ fill_argb(ctx.backing_va, ctx.stride, ctx.width, ctx.height, argb);
+ let rid = ctx.issue_request_id();
+ let _ = push_damage_commit(ctx.compositor_port, rid, 0, 0, ctx.width, ctx.height);
+ }
let _ = respond::status(sender_pid, req, 0, tx);
}
diff --git a/userland/capsule_wallpaper/src/server/handlers/get_wallpaper.rs b/userland/capsule_wallpaper/src/server/handlers/get_wallpaper.rs
index 142f21741..431651a72 100644
--- a/userland/capsule_wallpaper/src/server/handlers/get_wallpaper.rs
+++ b/userland/capsule_wallpaper/src/server/handlers/get_wallpaper.rs
@@ -20,7 +20,7 @@ use crate::state::Context;
pub fn handle(ctx: &Context, sender_pid: u32, req: &Request, tx: &mut [u8]) {
let off = HDR_LEN + STATUS_LEN;
- tx[off..off + 4].copy_from_slice(&ctx.argb.to_le_bytes());
+ tx[off..off + 4].copy_from_slice(&ctx.current_argb().to_le_bytes());
tx[off + 4..off + 8].copy_from_slice(&ctx.policy.as_u32().to_le_bytes());
tx[off + 8..off + 12].copy_from_slice(&ctx.width.to_le_bytes());
tx[off + 12..off + 16].copy_from_slice(&ctx.height.to_le_bytes());
diff --git a/userland/capsule_wallpaper/src/server/handlers/set_policy.rs b/userland/capsule_wallpaper/src/server/handlers/set_policy.rs
index bbf995ede..fb8b9e19e 100644
--- a/userland/capsule_wallpaper/src/server/handlers/set_policy.rs
+++ b/userland/capsule_wallpaper/src/server/handlers/set_policy.rs
@@ -28,6 +28,6 @@ pub fn handle(ctx: &mut Context, sender_pid: u32, req: &Request, body: &[u8], tx
let _ = respond::status(sender_pid, req, E_INVAL, tx);
return;
};
- ctx.policy = policy;
+ ctx.set_policy(policy);
let _ = respond::status(sender_pid, req, 0, tx);
}
diff --git a/userland/capsule_wallpaper/src/server/handlers/set_wallpaper.rs b/userland/capsule_wallpaper/src/server/handlers/set_wallpaper.rs
index 2463b3765..28f8d2ab0 100644
--- a/userland/capsule_wallpaper/src/server/handlers/set_wallpaper.rs
+++ b/userland/capsule_wallpaper/src/server/handlers/set_wallpaper.rs
@@ -15,21 +15,22 @@
// along with this program. If not, see .
use crate::compositor_client::push_damage_commit;
+use crate::decode_client::decode_and_paint;
use crate::paint::fill_argb;
use crate::protocol::{Request, E_INVAL, SET_WALLPAPER_REQ_LEN};
use crate::server::respond;
use crate::state::Context;
pub fn handle(ctx: &mut Context, sender_pid: u32, req: &Request, body: &[u8], tx: &mut [u8]) {
- if body.len() != SET_WALLPAPER_REQ_LEN {
+ if body.len() == SET_WALLPAPER_REQ_LEN {
+ let argb = u32::from_le_bytes(body[0..4].try_into().unwrap());
+ ctx.set_argb(argb);
+ let composed = ctx.current_argb();
+ fill_argb(ctx.backing_va, ctx.stride, ctx.width, ctx.height, composed);
+ } else if decode_and_paint(ctx, body).is_err() {
let _ = respond::status(sender_pid, req, E_INVAL, tx);
return;
}
- let argb = u32::from_le_bytes(body[0..4].try_into().unwrap());
- ctx.argb = argb;
- ctx.alpha = (argb >> 24) as u8;
- let composed = ctx.current_argb();
- fill_argb(ctx.backing_va, ctx.stride, ctx.width, ctx.height, composed);
let rid = ctx.issue_request_id();
let _ = push_damage_commit(ctx.compositor_port, rid, 0, 0, ctx.width, ctx.height);
let _ = respond::status(sender_pid, req, 0, tx);
diff --git a/userland/capsule_wallpaper/src/setup/discover.rs b/userland/capsule_wallpaper/src/setup/discover.rs
index f6a2c710c..f6d58401e 100644
--- a/userland/capsule_wallpaper/src/setup/discover.rs
+++ b/userland/capsule_wallpaper/src/setup/discover.rs
@@ -17,18 +17,27 @@
use nonos_libc::mk_service_lookup;
const COMPOSITOR_SERVICE: &[u8] = b"compositor";
+const DESKTOP_SHELL_SERVICE: &[u8] = b"desktop_shell";
-pub fn lookup_compositor_port() -> Result {
+fn lookup_port(name: &[u8]) -> Result {
let mut pid: u32 = 0;
let mut port: u32 = 0;
let rc = mk_service_lookup(
- COMPOSITOR_SERVICE.as_ptr(),
- COMPOSITOR_SERVICE.len(),
+ name.as_ptr(),
+ name.len(),
&mut port as *mut u32,
&mut pid as *mut u32,
);
if rc < 0 || pid == 0 || port == 0 {
- return Err("compositor service not announced");
+ return Err("service not announced");
}
Ok(port)
}
+
+pub fn lookup_compositor_port() -> Result {
+ lookup_port(COMPOSITOR_SERVICE).map_err(|_| "compositor service not announced")
+}
+
+pub fn lookup_desktop_shell_port() -> Result {
+ lookup_port(DESKTOP_SHELL_SERVICE).map_err(|_| "desktop_shell service not announced")
+}
diff --git a/userland/capsule_wallpaper/src/setup/prime.rs b/userland/capsule_wallpaper/src/setup/prime.rs
index 3cd9087e6..72c163ee1 100644
--- a/userland/capsule_wallpaper/src/setup/prime.rs
+++ b/userland/capsule_wallpaper/src/setup/prime.rs
@@ -31,6 +31,7 @@ const BOTTOM_Z: u32 = 0;
pub fn run() -> Result {
let compositor_port = discover::lookup_compositor_port()?;
+ let _ = discover::lookup_desktop_shell_port()?;
let mut width: u32 = 0;
let mut height: u32 = 0;
let rc = nonos_display_dimensions(0, &mut width as *mut u32, &mut height as *mut u32);
@@ -83,6 +84,7 @@ pub fn run() -> Result {
fade: FadeTimeline::new(),
next_request_id: 1,
};
+ ctx.set_argb(DEFAULT_ARGB);
let rid = ctx.issue_request_id();
push_scene_submit(compositor_port, rid, handle as u64, 0, 0, width, height, BOTTOM_Z)?;
Ok(ctx)
diff --git a/userland/capsule_wallpaper/src/state/context.rs b/userland/capsule_wallpaper/src/state/context.rs
index 6913c101c..3dc195778 100644
--- a/userland/capsule_wallpaper/src/state/context.rs
+++ b/userland/capsule_wallpaper/src/state/context.rs
@@ -36,6 +36,15 @@ impl Context {
id
}
+ pub fn set_argb(&mut self, argb: u32) {
+ self.argb = argb;
+ self.alpha = (argb >> 24) as u8;
+ }
+
+ pub fn set_policy(&mut self, policy: Policy) {
+ self.policy = policy;
+ }
+
pub fn current_argb(&self) -> u32 {
let rgb = self.argb & 0x00FF_FFFF;
((self.alpha as u32) << 24) | rgb