Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a82eeec
wallpaper: add nonos_toolkit dep for decode_client — Cargo.toml [plan…
senseix21 May 18, 2026
a66d1d4
wallpaper: port plan-a feat() service path — src/main.rs [planA-port]
senseix21 May 18, 2026
b6e02d8
wallpaper: port plan-a feat() service path — src/server/handlers/fade…
senseix21 May 18, 2026
b61c7d6
wallpaper: port plan-a feat() service path — src/server/handlers/get_…
senseix21 May 18, 2026
3a8e415
wallpaper: port plan-a feat() service path — src/server/handlers/set_…
senseix21 May 18, 2026
689917d
wallpaper: port plan-a feat() service path — src/server/handlers/set_…
senseix21 May 18, 2026
c269b33
wallpaper: port plan-a feat() service path — src/setup/discover.rs [p…
senseix21 May 18, 2026
d15b35d
wallpaper: port plan-a feat() service path — src/setup/prime.rs [plan…
senseix21 May 18, 2026
390e4c7
wallpaper: port plan-a feat() service path — src/state/context.rs [pl…
senseix21 May 18, 2026
f9d238a
wallpaper: port plan-a image decode_client — src/decode_client/header…
senseix21 May 18, 2026
36c9dd6
wallpaper: port plan-a image decode_client — src/decode_client/mod.rs…
senseix21 May 18, 2026
195aef3
wallpaper: port plan-a image decode_client — src/decode_client/seq.rs…
senseix21 May 18, 2026
a3e3c2c
wallpaper: port plan-a image decode_client — src/decode_client/wire.r…
senseix21 May 18, 2026
38a3d23
wallpaper: lockfile for nonos_toolkit dep — Cargo.lock [planA-port]
senseix21 May 18, 2026
f2d1fa5
desktop_shell: drop file superseded by plan-a feat() architecture — s…
senseix21 May 18, 2026
ee75d1d
desktop_shell: port plan-a feat() service path — src/compositor_clien…
senseix21 May 18, 2026
bcdb5e4
desktop_shell: port plan-a feat() service path — src/main.rs [planA-p…
senseix21 May 18, 2026
9be5acf
desktop_shell: port plan-a feat() — src/market_client/mod.rs [planA-p…
senseix21 May 18, 2026
2075b7d
desktop_shell: port plan-a feat() service path — src/setup/discover.r…
senseix21 May 18, 2026
76eff2b
desktop_shell: port plan-a feat() service path — src/setup/mod.rs [pl…
senseix21 May 18, 2026
20fdcd4
desktop_shell: port plan-a feat() service path — src/setup/prime.rs […
senseix21 May 18, 2026
11a3279
desktop_shell: drop file superseded by plan-a feat() architecture — s…
senseix21 May 18, 2026
aa9da5f
desktop_shell: port plan-a feat() service path — src/state/context.rs…
senseix21 May 18, 2026
b3c45b1
desktop_shell: port plan-a feat() — src/wallpaper_client/mod.rs [plan…
senseix21 May 18, 2026
ff59b5f
desktop_shell: port plan-a feat() — src/wm_client/mod.rs [planA-port]
senseix21 May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions userland/capsule_desktop_shell/src/compositor_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

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;
3 changes: 3 additions & 0 deletions userland/capsule_desktop_shell/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
31 changes: 31 additions & 0 deletions userland/capsule_desktop_shell/src/market_client/mod.rs
Original file line number Diff line number Diff line change
@@ -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<i32, &'static str> {
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()))
Comment on lines +1 to +30
}
27 changes: 23 additions & 4 deletions userland/capsule_desktop_shell/src/setup/discover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32, &'static str> {
fn lookup_port(name: &[u8]) -> Result<u32, &'static str> {
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<u32, &'static str> {
lookup_port(COMPOSITOR_SERVICE).map_err(|_| "compositor service not announced")
}

pub fn require_wm() -> Result<u32, &'static str> {
lookup_port(WM_SERVICE).map_err(|_| "wm service not announced")
}

pub fn require_wallpaper() -> Result<u32, &'static str> {
lookup_port(WALLPAPER_SERVICE).map_err(|_| "wallpaper service not announced")
}

pub fn try_market() -> u32 {
lookup_port(MARKET_SERVICE).unwrap_or(0)
}
3 changes: 1 addition & 2 deletions userland/capsule_desktop_shell/src/setup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@

mod discover;
mod prime;
mod retry;

pub use retry::run;
pub use prime::run;
17 changes: 14 additions & 3 deletions userland/capsule_desktop_shell/src/setup/prime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Context, &'static str> {
pub fn run() -> Result<Context, &'static str> {
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);
Expand All @@ -55,6 +60,9 @@ pub fn run_once() -> Result<Context, &'static str> {
let backing_va = base as u64;
let mut ctx = Context {
compositor_port,
wm_port,
wallpaper_port,
market_port,
width,
height,
stride,
Expand Down Expand Up @@ -84,5 +92,8 @@ pub fn run_once() -> Result<Context, &'static str> {
}
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)
}
3 changes: 3 additions & 0 deletions userland/capsule_desktop_shell/src/state/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
29 changes: 29 additions & 0 deletions userland/capsule_desktop_shell/src/wallpaper_client/mod.rs
Original file line number Diff line number Diff line change
@@ -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<i32, &'static str> {
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()))
}
28 changes: 28 additions & 0 deletions userland/capsule_desktop_shell/src/wm_client/mod.rs
Original file line number Diff line number Diff line change
@@ -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<i32, &'static str> {
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()))
}
8 changes: 8 additions & 0 deletions userland/capsule_wallpaper/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions userland/capsule_wallpaper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
55 changes: 55 additions & 0 deletions userland/capsule_wallpaper/src/decode_client/header.rs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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<DecodeReq<'_>, 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..] })
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

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;
60 changes: 60 additions & 0 deletions userland/capsule_wallpaper/src/decode_client/seq.rs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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) };
}
}
}
Loading
Loading