raise window owner
All checks were successful
Intrepid/Prometeu/Runtime/pipeline/head This commit looks good

This commit is contained in:
bQUARKz 2026-05-15 11:26:41 +01:00
parent 1663ab5413
commit a8e3040d1e
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
13 changed files with 107 additions and 40 deletions

View File

@ -350,8 +350,8 @@ mod tests {
firmware.tick(&signals, &mut hardware); firmware.tick(&signals, &mut hardware);
assert!(matches!(firmware.state, FirmwareState::ShellRunning(_))); assert!(matches!(firmware.state, FirmwareState::ShellRunning(_)));
assert!(firmware.os.window().focused_window().is_some()); assert!(firmware.os.windows().focused_window().is_some());
assert_eq!(firmware.os.window().window_count(), 1); assert_eq!(firmware.os.windows().window_count(), 1);
} }
#[test] #[test]

View File

@ -5,8 +5,9 @@ use crate::firmware::prometeu_context::PrometeuContext;
use prometeu_hal::cartridge::{AppMode, Cartridge}; use prometeu_hal::cartridge::{AppMode, Cartridge};
use prometeu_hal::color::Color; use prometeu_hal::color::Color;
use prometeu_hal::log::{LogLevel, LogSource}; use prometeu_hal::log::{LogLevel, LogSource};
use prometeu_hal::window::Rect; use prometeu_hal::primitives::Rect;
use prometeu_system::CrashReport; use prometeu_system::CrashReport;
use prometeu_system::windows::WindowOwner;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LoadCartridgeStep { pub struct LoadCartridgeStep {
@ -43,17 +44,17 @@ impl LoadCartridgeStep {
} }
if self.cartridge.app_mode == AppMode::Shell { if self.cartridge.app_mode == AppMode::Shell {
let id = ctx.os.window().add_window(
self.cartridge.title.clone(),
Rect { x: 40, y: 20, w: 240, h: 140 },
Color::WHITE,
);
ctx.os.window().set_focus(id);
let task_id = ctx let task_id = ctx
.os .os
.sessions() .sessions()
.create_vm_shell_task(self.cartridge.app_id, self.cartridge.title.clone()); .create_vm_shell_task(self.cartridge.app_id, self.cartridge.title.clone());
let id = ctx.os.windows().add_window(
self.cartridge.title.clone(),
WindowOwner::Task(task_id),
Rect { x: 40, y: 20, w: 240, h: 140 },
Color::WHITE,
);
ctx.os.windows().set_focus(id);
return Some(FirmwareState::ShellRunning(ShellRunningStep::new(task_id))); return Some(FirmwareState::ShellRunning(ShellRunningStep::new(task_id)));
} }

View File

@ -18,6 +18,7 @@ pub mod log;
pub mod native_helpers; pub mod native_helpers;
pub mod native_interface; pub mod native_interface;
pub mod pad_bridge; pub mod pad_bridge;
pub mod primitives;
pub mod sample; pub mod sample;
pub mod scene_bank; pub mod scene_bank;
pub mod scene_layer; pub mod scene_layer;
@ -31,7 +32,6 @@ pub mod tile;
pub mod tilemap; pub mod tilemap;
pub mod touch_bridge; pub mod touch_bridge;
pub mod vm_fault; pub mod vm_fault;
pub mod window;
pub use asset_bridge::AssetBridge; pub use asset_bridge::AssetBridge;
pub use audio_bridge::{AudioBridge, AudioOpStatus, LoopMode}; pub use audio_bridge::{AudioBridge, AudioOpStatus, LoopMode};

View File

@ -0,0 +1,7 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Rect {
pub x: i32,
pub y: i32,
pub w: i32,
pub h: i32,
}

View File

@ -10,3 +10,4 @@ pub use services::fs;
pub use services::process; pub use services::process;
pub use services::task; pub use services::task;
pub use services::vm_runtime::VirtualMachineRuntime; pub use services::vm_runtime::VirtualMachineRuntime;
pub use services::windows;

View File

@ -1,14 +1,21 @@
use crate::os::SystemOS; use crate::os::SystemOS;
use crate::windows::{Window, WindowId, WindowOwner};
use prometeu_hal::color::Color; use prometeu_hal::color::Color;
use prometeu_hal::window::{Rect, Window, WindowId}; use prometeu_hal::primitives::Rect;
pub struct WindowFacade<'a> { pub struct WindowFacade<'a> {
pub(in crate::os) os: &'a mut SystemOS, pub(in crate::os) os: &'a mut SystemOS,
} }
impl<'a> WindowFacade<'a> { impl<'a> WindowFacade<'a> {
pub fn add_window(&mut self, title: String, viewport: Rect, color: Color) -> WindowId { pub fn add_window(
self.os.window_manager.add_window(title, viewport, color) &mut self,
title: String,
owner: WindowOwner,
viewport: Rect,
color: Color,
) -> WindowId {
self.os.window_manager.add_window(title, owner, viewport, color)
} }
pub fn set_focus(&mut self, id: WindowId) { pub fn set_focus(&mut self, id: WindowId) {

View File

@ -3,7 +3,7 @@ use crate::fs::{FsState, VirtualFS};
use crate::os::{FsFacade, LifecycleFacade, SessionsFacade, VmFacade, WindowFacade}; use crate::os::{FsFacade, LifecycleFacade, SessionsFacade, VmFacade, WindowFacade};
use crate::process::ProcessManager; use crate::process::ProcessManager;
use crate::services::memcard::MemcardService; use crate::services::memcard::MemcardService;
use crate::services::window_manager::WindowManager; use crate::services::windows::WindowManager;
use crate::task::TaskManager; use crate::task::TaskManager;
use prometeu_hal::log::{LogEvent, LogLevel, LogService, LogSource}; use prometeu_hal::log::{LogEvent, LogLevel, LogService, LogSource};
use prometeu_hal::telemetry::CertificationConfig; use prometeu_hal::telemetry::CertificationConfig;
@ -115,7 +115,7 @@ impl SystemOS {
FsFacade { os: self } FsFacade { os: self }
} }
pub fn window(&mut self) -> WindowFacade<'_> { pub fn windows(&mut self) -> WindowFacade<'_> {
WindowFacade { os: self } WindowFacade { os: self }
} }

View File

@ -1,7 +1,8 @@
use crate::windows::WindowOwner;
use crate::{CrashReport, SystemOS}; use crate::{CrashReport, SystemOS};
use prometeu_hal::color::Color; use prometeu_hal::color::Color;
use prometeu_hal::log::{LogLevel, LogSource}; use prometeu_hal::log::{LogLevel, LogSource};
use prometeu_hal::window::Rect; use prometeu_hal::primitives::Rect;
use prometeu_hal::{HardwareBridge, InputSignals}; use prometeu_hal::{HardwareBridge, InputSignals};
use prometeu_vm::VirtualMachine; use prometeu_vm::VirtualMachine;
@ -61,15 +62,15 @@ impl PrometeuHub {
} }
if let Some((title, rect, color)) = next_window { if let Some((title, rect, color)) = next_window {
let mut window = os.window(); let mut window = os.windows();
window.remove_all_windows(); window.remove_all_windows();
let id = window.add_window(title, rect, color); let id = window.add_window(title, WindowOwner::Hub, rect, color);
window.set_focus(id); window.set_focus(id);
} }
} }
pub fn render(&mut self, os: &mut SystemOS, hw: &mut dyn HardwareBridge) { pub fn render(&mut self, os: &mut SystemOS, hw: &mut dyn HardwareBridge) {
for window in os.window().windows() { for window in os.windows().windows() {
hw.gfx_mut().fill_rect( hw.gfx_mut().fill_rect(
window.viewport.x, window.viewport.x,
window.viewport.y, window.viewport.y,
@ -91,9 +92,9 @@ impl PrometeuHub {
self.gui_update(os, hw); self.gui_update(os, hw);
if let Some(focused_id) = os.window().focused_window() { if let Some(focused_id) = os.windows().focused_window() {
if hw.pad().start().down { if hw.pad().start().down {
os.window().close_window(focused_id); os.windows().close_window(focused_id);
} else { } else {
crash = os.vm().tick(vm, signals, hw); crash = os.vm().tick(vm, signals, hw);
} }
@ -102,6 +103,9 @@ impl PrometeuHub {
self.render(os, hw); self.render(os, hw);
hw.gfx_mut().present(); hw.gfx_mut().present();
SystemProfileUpdate { crash, focused_window_active: os.window().focused_window().is_some() } SystemProfileUpdate {
crash,
focused_window_active: os.windows().focused_window().is_some(),
}
} }
} }

View File

@ -3,4 +3,4 @@ pub mod memcard;
pub mod process; pub mod process;
pub mod task; pub mod task;
pub mod vm_runtime; pub mod vm_runtime;
pub mod window_manager; pub mod windows;

View File

@ -0,0 +1,8 @@
mod window;
mod window_manager;
mod window_owner;
pub use window::Window;
pub use window::WindowId;
pub use window_manager::WindowManager;
pub use window_owner::WindowOwner;

View File

@ -1,12 +1,6 @@
use crate::color::Color; use crate::windows::WindowOwner;
use prometeu_hal::color::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] use prometeu_hal::primitives::Rect;
pub struct Rect {
pub x: i32,
pub y: i32,
pub w: i32,
pub h: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WindowId(pub u32); pub struct WindowId(pub u32);
@ -14,6 +8,7 @@ pub struct WindowId(pub u32);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Window { pub struct Window {
pub id: WindowId, pub id: WindowId,
pub owner: WindowOwner,
pub viewport: Rect, pub viewport: Rect,
pub has_focus: bool, pub has_focus: bool,
pub title: String, pub title: String,

View File

@ -1,5 +1,7 @@
use crate::services::windows::window::{Window, WindowId};
use crate::windows::WindowOwner;
use prometeu_hal::color::Color; use prometeu_hal::color::Color;
use prometeu_hal::window::{Rect, Window, WindowId}; use prometeu_hal::primitives::Rect;
/// PROMETEU Window Manager. /// PROMETEU Window Manager.
pub struct WindowManager { pub struct WindowManager {
@ -7,14 +9,26 @@ pub struct WindowManager {
pub focused: Option<WindowId>, pub focused: Option<WindowId>,
} }
impl Default for WindowManager {
fn default() -> Self {
Self::new()
}
}
impl WindowManager { impl WindowManager {
pub fn new() -> Self { pub fn new() -> Self {
Self { windows: Vec::new(), focused: None } Self { windows: Vec::new(), focused: None }
} }
pub fn add_window(&mut self, title: String, viewport: Rect, color: Color) -> WindowId { pub fn add_window(
&mut self,
title: String,
owner: WindowOwner,
viewport: Rect,
color: Color,
) -> WindowId {
let id = WindowId(self.windows.len() as u32); let id = WindowId(self.windows.len() as u32);
let window = Window { id, viewport, has_focus: false, title, color }; let window = Window { id, owner, viewport, has_focus: false, title, color };
self.windows.push(window); self.windows.push(window);
id id
} }
@ -46,10 +60,15 @@ mod tests {
#[test] #[test]
fn test_window_manager_focus() { fn test_window_manager_focus() {
let mut wm = WindowManager::new(); let mut wm = WindowManager::new();
let id1 = let id1 = wm.add_window(
wm.add_window("Window 1".to_string(), Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE); "Window 1".to_string(),
WindowOwner::Hub,
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
let id2 = wm.add_window( let id2 = wm.add_window(
"Window 2".to_string(), "Window 2".to_string(),
WindowOwner::Hub,
Rect { x: 10, y: 10, w: 10, h: 10 }, Rect { x: 10, y: 10, w: 10, h: 10 },
Color::WHITE, Color::WHITE,
); );
@ -71,8 +90,12 @@ mod tests {
#[test] #[test]
fn test_window_manager_remove_window() { fn test_window_manager_remove_window() {
let mut wm = WindowManager::new(); let mut wm = WindowManager::new();
let id = let id = wm.add_window(
wm.add_window("Window".to_string(), Rect { x: 0, y: 0, w: 10, h: 10 }, Color::WHITE); "Window".to_string(),
WindowOwner::Hub,
Rect { x: 0, y: 0, w: 10, h: 10 },
Color::WHITE,
);
wm.set_focus(id); wm.set_focus(id);
assert_eq!(wm.focused, Some(id)); assert_eq!(wm.focused, Some(id));

View File

@ -0,0 +1,21 @@
use crate::task::TaskId;
/// Identifies the logical owner of a shell window.
///
/// Game cartridges do not currently own WindowManager windows. Games run as
/// fullscreen firmware steps. The WindowManager is used for Hub/Home UI,
/// Shell task windows, and system overlays.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WindowOwner {
/// Window owned by the Prometeu Hub/Home.
Hub,
/// Window owned by a managed Shell task.
Task(TaskId),
/// Temporary system-owned window drawn above the current context.
///
/// Examples: notifications, crash dialogs, quick menus, debug panels,
/// permission prompts, and modal confirmations.
Overlay,
}