diff --git a/services/gam/src/canvas.rs b/services/gam/src/canvas.rs index 59c129fd0..730d0fc4b 100644 --- a/services/gam/src/canvas.rs +++ b/services/gam/src/canvas.rs @@ -23,9 +23,12 @@ pub enum CanvasState { OffScreenNotDrawable, } +use std::cell::RefCell; +use std::rc::Rc; + /// A rectangular region that defines a top-left zero relative offset for graphical items /// and a bottom-right point that defines a clipping area for things drawn inside. -#[derive(Debug, Copy, Clone)] +#[derive(Debug)] pub struct Canvas { // unique, random identifier for the Canvas gid: Gid, @@ -36,7 +39,7 @@ pub struct Canvas { // enables scroll/pan of objects within a region pan_offset: Point, // track the drawing state of the canvas - state: CanvasState, + state: Rc>, // The type of canvas. Useful for debugging, don't remove it. #[allow(dead_code)] canvas_type: crate::api::CanvasType, @@ -57,12 +60,12 @@ impl Canvas { Ok(if pan_offset.is_some() { Canvas { - clip_rect, trust_level, state: CanvasState::OffScreenDrawable, gid: Gid::new(gid), pan_offset: pan_offset.unwrap(), + clip_rect, trust_level, state: Rc::new(RefCell::new(CanvasState::OffScreenDrawable)), gid: Gid::new(gid), pan_offset: pan_offset.unwrap(), canvas_type, } } else { Canvas { - clip_rect, trust_level, state: CanvasState::OffScreenDrawable, gid: Gid::new(gid), pan_offset: Point::new(0, 0), + clip_rect, trust_level, state: Rc::new(RefCell::new(CanvasState::OffScreenDrawable)), gid: Gid::new(gid), pan_offset: Point::new(0, 0), canvas_type, } }) @@ -75,93 +78,96 @@ impl Canvas { } pub fn pan_offset(&self) -> Point { self.pan_offset } pub fn clip_rect(&self) -> Rectangle { self.clip_rect } - pub fn set_clip(&mut self, cr: Rectangle) { self.clip_rect = cr; self.state = CanvasState::OffScreenDrawable } + pub fn set_clip(&mut self, cr: Rectangle) { self.clip_rect = cr; *self.state.borrow_mut() = CanvasState::OffScreenDrawable } pub fn gid(&self) -> Gid { self.gid } pub fn trust_level(&self) -> u8 { self.trust_level } pub fn set_trust_level(&mut self, level: u8) {self.trust_level = level;} - pub fn state(&self) -> CanvasState { self.state } + pub fn state(&self) -> CanvasState { *self.state.borrow() } pub fn is_onscreen(&self) -> bool { - if self.state == CanvasState::OffScreenDrawable || self.state == CanvasState::OffScreenNotDrawable { + if *self.state.borrow() == CanvasState::OffScreenDrawable || *self.state.borrow() == CanvasState::OffScreenNotDrawable { false } else { true } } pub fn is_drawable(&self) -> bool { - if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn || self.state == CanvasState::OffScreenDrawable { + if *self.state.borrow() == CanvasState::DrawableDirty + || *self.state.borrow() == CanvasState::DrawableDrawn + || *self.state.borrow() == CanvasState::OffScreenDrawable { true } else { false } } pub fn is_drawable_or_offscreen(&self) -> bool { - if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn - || self.state == CanvasState::OffScreenDrawable { + if *self.state.borrow() == CanvasState::DrawableDirty + || *self.state.borrow() == CanvasState::DrawableDrawn + || *self.state.borrow() == CanvasState::OffScreenDrawable { true } else { false } } - pub fn set_drawable(&mut self, drawable: bool) { + pub fn set_drawable(&self, drawable: bool) { if drawable { - if self.state == CanvasState::OffScreenNotDrawable { - self.state = CanvasState::OffScreenDrawable - } else if self.state != CanvasState::DrawableDrawn { - self.state = CanvasState::DrawableDirty; + if *self.state.borrow() == CanvasState::OffScreenNotDrawable { + *self.state.borrow_mut() = CanvasState::OffScreenDrawable + } else if *self.state.borrow() != CanvasState::DrawableDrawn { + *self.state.borrow_mut() = CanvasState::DrawableDirty; } } else { - if self.state == CanvasState::OffScreenDrawable { - self.state = CanvasState::OffScreenNotDrawable - } else if self.state != CanvasState::NotDrawableDefaced { - self.state = CanvasState::NotDrawableDirty; + if *self.state.borrow() == CanvasState::OffScreenDrawable { + *self.state.borrow_mut() = CanvasState::OffScreenNotDrawable + } else if *self.state.borrow() != CanvasState::NotDrawableDefaced { + *self.state.borrow_mut() = CanvasState::NotDrawableDirty; } } } - pub fn set_onscreen(&mut self, onscreen: bool) { + pub fn set_onscreen(&self, onscreen: bool) { if onscreen { - if self.state == CanvasState::OffScreenDrawable { - self.state = CanvasState::DrawableDirty; - } else if self.state == CanvasState::OffScreenNotDrawable { - self.state = CanvasState::NotDrawableDirty; + if *self.state.borrow() == CanvasState::OffScreenDrawable { + *self.state.borrow_mut() = CanvasState::DrawableDirty; + } else if *self.state.borrow() == CanvasState::OffScreenNotDrawable { + *self.state.borrow_mut() = CanvasState::NotDrawableDirty; } // other states are already onscreen } else { - if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn { - self.state = CanvasState::OffScreenDrawable; - } else if self.state == CanvasState::NotDrawableDirty || self.state == CanvasState::NotDrawableDefaced { - self.state = CanvasState::OffScreenNotDrawable; + if *self.state.borrow() == CanvasState::DrawableDirty || *self.state.borrow() == CanvasState::DrawableDrawn { + *self.state.borrow_mut() = CanvasState::OffScreenDrawable; + } else if *self.state.borrow() == CanvasState::NotDrawableDirty || *self.state.borrow() == CanvasState::NotDrawableDefaced { + *self.state.borrow_mut() = CanvasState::OffScreenNotDrawable; } // other states are already offscreen } } // call this after the screen has been flushed - pub fn do_flushed(&mut self) -> Result<(), xous::Error> { - if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn { - self.state = CanvasState::DrawableDrawn; + pub fn do_flushed(&self) -> Result<(), xous::Error> { + if *self.state.borrow() == CanvasState::DrawableDirty || *self.state.borrow() == CanvasState::DrawableDrawn { + *self.state.borrow_mut() = CanvasState::DrawableDrawn; Ok(()) - } else if self.state == CanvasState::NotDrawableDefaced - || self.state == CanvasState::OffScreenNotDrawable - || self.state == CanvasState::OffScreenDrawable { + } else if *self.state.borrow() == CanvasState::NotDrawableDefaced + || *self.state.borrow() == CanvasState::OffScreenNotDrawable + || *self.state.borrow() == CanvasState::OffScreenDrawable { Ok(()) } else { error!("Canvas: flush happened before not drawable regions were defaced, or before initialized! {:?}", self.state); Err(xous::Error::UseBeforeInit) } } - pub fn do_drawn(&mut self) -> Result<(), xous::Error> { - if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn { - self.state = CanvasState::DrawableDirty; + pub fn do_drawn(&self) -> Result<(), xous::Error> { + if *self.state.borrow() == CanvasState::DrawableDirty || *self.state.borrow() == CanvasState::DrawableDrawn { + *self.state.borrow_mut() = CanvasState::DrawableDirty; Ok(()) } else { error!("Canvas: attempt to draw on regions that are not drawable, or not initialized!"); Err(xous::Error::AccessDenied) } } - pub fn do_defaced(&mut self) -> Result<(), xous::Error> { - if self.state == CanvasState::NotDrawableDirty { - self.state = CanvasState::NotDrawableDefaced; + pub fn do_defaced(&self) -> Result<(), xous::Error> { + if *self.state.borrow() == CanvasState::NotDrawableDirty { + *self.state.borrow_mut() = CanvasState::NotDrawableDefaced; Ok(()) - } else if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn { + } else if *self.state.borrow() == CanvasState::DrawableDirty || *self.state.borrow() == CanvasState::DrawableDrawn { info!("Canvas: drawable region was defaced. Allowing it, but this could be a logic bug"); Ok(()) } else { @@ -170,7 +176,7 @@ impl Canvas { } } pub fn needs_defacing(&self) -> bool { - if self.state == CanvasState::NotDrawableDirty { + if *self.state.borrow() == CanvasState::NotDrawableDirty { true } else { false @@ -206,8 +212,6 @@ pub fn deface(gfx: &graphics_server::Gfx, trng: &trng::Trng, canvases: &mut Hash } } if needs_defacing { - log::info!("doing a deface computation!"); - let screensize = gfx.screen_size().unwrap(); let screen_rect = Rectangle::new(Point::new(0, 0,), screensize); /* @@ -292,50 +296,27 @@ fn remap_rand(end_range: i32, rand: i16, source_range: i32) -> i16 { } // we use the "screen" parameter to determine when we can turn off drawing to canvases that are off-screen -pub(crate) fn recompute_canvases(canvases: &HashMap, screen: Rectangle) -> HashMap { - let debug = false; // keep this around, it's really convenient for turning off just this specific subset of debug messages +pub(crate) fn recompute_canvases(canvases: &HashMap) { // first, sort canvases by trust_level. Canvas implements ord/eq based on the trust_level attribute // so jush pushing it into a max binary heap does the trick. - if debug { info!("CANVAS: recompute canvas"); } - let mut sorted_clipregions: BinaryHeap = BinaryHeap::new(); - for (&k, &c) in canvases.iter() { - if debug { info!(" CANVAS: sorting gid {:?}, canvas {:?}", k, c);} - sorted_clipregions.push(c); // always succeeds because incoming type is the same size + let mut sorted_clipregions: BinaryHeap<&Canvas> = BinaryHeap::new(); + for c in canvases.values() { + sorted_clipregions.push(c); } - // now, descend through trust levels and compute intersections, putting the updated drawable states into higher_clipregions - let mut higher_clipregions: BinaryHeap<&Canvas> = BinaryHeap::new(); - let mut current_trust_level: u8 = 255; - // sorted_clipregions is a Max heap keyed on trust, so popping the elements off will return them sorted from most to least trusted - if debug{info!("CANVAS: received screen argument of {:?}", screen);} - if debug{info!("CANVAS: now determining which regions are drawable");} - - let mut sorted_clipregions_vec = sorted_clipregions.into_sorted_vec(); - for canvas in sorted_clipregions_vec.iter_mut() { - if canvas.is_onscreen() { - if canvas.trust_level() < current_trust_level { - current_trust_level = canvas.trust_level(); - } - for region in higher_clipregions.iter() { - if region.is_onscreen() - && (region.trust_level() > current_trust_level) // regions of same trust level have arbitrary draw order - && region.clip_rect().intersects(canvas.clip_rect()) { - canvas.set_drawable(false); - } else { - canvas.set_drawable(true); + let mut higher_clipregions = Vec::<&Canvas>::new(); // contains only a subset of on-screen clip rects to consider + while let Some(candidate) = sorted_clipregions.pop() { + log::trace!("candidate {}", candidate.trust_level()); + if candidate.is_onscreen() { + candidate.set_drawable(true); // i *think* this is ok and doesn't cause thrashing, but verify... + for previous in higher_clipregions.iter() { + log::trace!("candidate {:?}/{} veruss {:?}/{}", candidate.canvas_type, candidate.trust_level, previous.canvas_type, previous.trust_level); + if candidate.clip_rect().intersects(previous.clip_rect()) { + log::trace!("candidate is less trusted, setting to not drawable"); + candidate.set_drawable(false); } } + higher_clipregions.push(candidate); } - higher_clipregions.push(canvas); } - - // create a new index map out of the recomputed higher_clipregions - let mut map: HashMap = HashMap::new(); - if debug { info!("CANVAS: reconstituting index map");} - for &c in higher_clipregions.iter() { - if debug { info!(" CANVAS: inserting gid {:?}, canvas {:?}", c.gid(), c);} - map.insert(c.gid(), *c); - } - - map } diff --git a/services/gam/src/contexts.rs b/services/gam/src/contexts.rs index f2cd02cad..2adf75d1d 100644 --- a/services/gam/src/contexts.rs +++ b/services/gam/src/contexts.rs @@ -26,7 +26,7 @@ pub(crate) enum LayoutBehavior { pub(crate) trait LayoutApi { fn clear(&self, gfx: &graphics_server::Gfx, canvases: &mut HashMap) -> Result<(), xous::Error>; // for Chats, this resizes the height of the input area; for menus, it resizes the overall height - fn resize_height(&mut self, gfx: &graphics_server::Gfx, new_height: i16, status_canvas: &Canvas, canvases: &mut HashMap) -> Result; + fn resize_height(&mut self, gfx: &graphics_server::Gfx, new_height: i16, status_cliprect: &Rectangle, canvases: &mut HashMap) -> Result; fn get_gids(&self) -> Vec; //fn get_input_canvas(&self) -> Option { None } //fn get_prediction_canvas(&self) -> Option { None } @@ -128,7 +128,7 @@ impl ContextManager { pub(crate) fn register(&mut self, gfx: &graphics_server::Gfx, trng: &trng::Trng, - status_canvas: &Canvas, + status_cliprect: &Rectangle, canvases: &mut HashMap, registration: UxRegistration) -> Option<[u32; 4]> { @@ -137,7 +137,7 @@ impl ContextManager { match registration.ux_type { UxType::Chat => { let mut chatlayout = ChatLayout::init(&gfx, &trng, - &status_canvas, canvases).expect("couldn't create chat layout"); + status_cliprect, canvases).expect("couldn't create chat layout"); // default to off-screen for all layouts chatlayout.set_visibility_state(false, canvases); let ux_context = UxContext { @@ -212,7 +212,7 @@ impl ContextManager { } UxType::Framebuffer => { let mut raw_fb = Framebuffer::init(&gfx, &trng, - &status_canvas, canvases).expect("couldn't create raw fb layout"); + &status_cliprect, canvases).expect("couldn't create raw fb layout"); raw_fb.set_visibility_state(false, canvases); log::debug!("debug raw fb layout: {:?}", raw_fb); let ux_context = UxContext { @@ -272,12 +272,12 @@ impl ContextManager { gfx: &graphics_server::Gfx, gam_token: [u32; 4], new_height: i16, - status_canvas: &Canvas, + status_cliprect: &Rectangle, canvases: &mut HashMap) -> Option { for context in self.contexts.values_mut() { if context.gam_token == gam_token { - let result = context.layout.resize_height(gfx, new_height, status_canvas, canvases).expect("couldn't adjust height of active Ux context"); + let result = context.layout.resize_height(gfx, new_height, status_cliprect, canvases).expect("couldn't adjust height of active Ux context"); return Some(result) } } @@ -288,11 +288,11 @@ impl ContextManager { gfx: &graphics_server::Gfx, app_token: [u32; 4], new_height: i16, - status_canvas: &Canvas, + status_cliprect: &Rectangle, canvases: &mut HashMap) -> Option { if let Some(context) = self.contexts.get_mut(&app_token) { - let result = context.layout.resize_height(gfx, new_height, status_canvas, canvases).expect("couldn't adjust height of active Ux context"); + let result = context.layout.resize_height(gfx, new_height, status_cliprect, canvases).expect("couldn't adjust height of active Ux context"); Some(result) } else { None @@ -407,8 +407,7 @@ impl ContextManager { } // now recompute the drawability of canvases, based on on-screen visibility and trust state - let screensize = gfx.screen_size().expect("Couldn't get screen size"); - *canvases = recompute_canvases(canvases, Rectangle::new(Point::new(0, 0), screensize)); + recompute_canvases(canvases); } } log::trace!("foregrounding new context"); @@ -437,7 +436,7 @@ impl ContextManager { } // run the defacement before we redraw all the canvases if deface(gfx, &self.trng, canvases) { - log::info!("activate triggered a defacement"); + log::trace!("activate triggered a defacement"); } log::trace!("activate redraw"); self.redraw().expect("couldn't redraw the currently focused app"); diff --git a/services/gam/src/layouts/chat.rs b/services/gam/src/layouts/chat.rs index 5f9e84bc8..b3659dffa 100644 --- a/services/gam/src/layouts/chat.rs +++ b/services/gam/src/layouts/chat.rs @@ -26,7 +26,7 @@ pub(crate) struct ChatLayout { impl ChatLayout { // pass in the status canvas so we can size around it, but we can't draw on it pub fn init(gfx: &graphics_server::Gfx, trng: &trng::Trng, - status_canvas: &Canvas, canvases: &mut HashMap) -> Result { + status_cliprect: &Rectangle, canvases: &mut HashMap) -> Result { let screensize = gfx.screen_size().expect("Couldn't get screen size"); // get the height of various text regions to compute the layout let small_height: i16 = gfx.glyph_height_hint(GlyphStyle::Small).expect("couldn't get glyph height") as i16; @@ -40,25 +40,30 @@ impl ChatLayout { MISC_CONTEXT_DEFAULT_TRUST - TRUST_OFFSET, &trng, None, crate::api::CanvasType::ChatPreditive ).expect("couldn't create predictive text canvas"); + let pred_gid = predictive_canvas.gid(); + let predictive_cr = predictive_canvas.clip_rect(); canvases.insert(predictive_canvas.gid(), predictive_canvas); let min_input_height = regular_height + margin*2; let input_canvas = Canvas::new( - Rectangle::new_v_stack(predictive_canvas.clip_rect(), -min_input_height), + Rectangle::new_v_stack(predictive_cr, -min_input_height), MISC_CONTEXT_DEFAULT_TRUST - TRUST_OFFSET, &trng, None, crate::api::CanvasType::ChatInput ).expect("couldn't create input text canvas"); + let input_gid = input_canvas.gid(); + let input_cr = input_canvas.clip_rect(); canvases.insert(input_canvas.gid(), input_canvas); let content_canvas = Canvas::new( - Rectangle::new_v_span(status_canvas.clip_rect(), input_canvas.clip_rect()), + Rectangle::new_v_span(*status_cliprect, input_cr), (MISC_CONTEXT_DEFAULT_TRUST - TRUST_OFFSET) / 2, &trng, None, crate::api::CanvasType::ChatContent ).expect("couldn't create content canvas"); + let content_gid = content_canvas.gid(); canvases.insert(content_canvas.gid(), content_canvas); Ok(ChatLayout { - content: content_canvas.gid(), - predictive: predictive_canvas.gid(), - input: input_canvas.gid(), + content: content_gid, + predictive: pred_gid, + input: input_gid, min_content_height: 64, min_input_height, _screensize: screensize, @@ -89,7 +94,7 @@ impl LayoutApi for ChatLayout { gfx.draw_rectangle(rect).expect("can't clear canvas"); Ok(()) } - fn resize_height(&mut self, gfx: &graphics_server::Gfx, new_height: i16, status_canvas: &Canvas, canvases: &mut HashMap) -> Result { + fn resize_height(&mut self, gfx: &graphics_server::Gfx, new_height: i16, status_canvas: &Rectangle, canvases: &mut HashMap) -> Result { let input_canvas = canvases.get(&self.input).expect("couldn't find input canvas"); let predictive_canvas = canvases.get(&self.predictive).expect("couldn't find predictive canvas"); @@ -99,7 +104,7 @@ impl LayoutApi for ChatLayout { new_height }; let mut new_input_rect = Rectangle::new_v_stack(predictive_canvas.clip_rect(), -height); - let mut new_content_rect = Rectangle::new_v_span(status_canvas.clip_rect(), new_input_rect); + let mut new_content_rect = Rectangle::new_v_span(*status_canvas, new_input_rect); if (new_content_rect.br.y - new_content_rect.tl.y) > self.min_content_height { { let input_canvas_mut = canvases.get_mut(&self.input).expect("couldn't find input canvas"); diff --git a/services/gam/src/layouts/framebuffer.rs b/services/gam/src/layouts/framebuffer.rs index 55c16cf1b..cdc9c1366 100644 --- a/services/gam/src/layouts/framebuffer.rs +++ b/services/gam/src/layouts/framebuffer.rs @@ -15,19 +15,20 @@ impl Framebuffer { pub fn init( gfx: &graphics_server::Gfx, trng: &trng::Trng, - status_canvas: &Canvas, + status_cliprect: &Rectangle, canvases: &mut HashMap ) -> Result { let screensize = gfx.screen_size().expect("Couldn't get screen size"); let fb_canvas = Canvas::new( - Rectangle::new(Point::new(0, status_canvas.clip_rect().br().y + 1), screensize), + Rectangle::new(Point::new(0, status_cliprect.br().y + 1), screensize), MISC_CONTEXT_DEFAULT_TRUST - TRUST_OFFSET, &trng, None, crate::api::CanvasType::Framebuffer ).expect("couldn't create modal canvas"); + let fb_gid = fb_canvas.gid(); canvases.insert(fb_canvas.gid(), fb_canvas); Ok(Framebuffer { - gid: fb_canvas.gid(), + gid: fb_gid, _screensize: screensize, }) } @@ -43,7 +44,7 @@ impl LayoutApi for Framebuffer { rect.style = DrawStyle {fill_color: Some(PixelColor::Light), stroke_color: None, stroke_width: 0,}; gfx.draw_rectangle(rect) } - fn resize_height(&mut self, _gfx: &graphics_server::Gfx, new_height: i16, _status_canvas: &Canvas, canvases: &mut HashMap) -> Result { + fn resize_height(&mut self, _gfx: &graphics_server::Gfx, new_height: i16, _status_canvas: &Rectangle, canvases: &mut HashMap) -> Result { let fb_canvas = canvases.get_mut(&self.gid).expect("couldn't find my canvas"); let orig_rect = fb_canvas.clip_rect(); diff --git a/services/gam/src/layouts/menu.rs b/services/gam/src/layouts/menu.rs index 10f918c5f..1b26d19f2 100644 --- a/services/gam/src/layouts/menu.rs +++ b/services/gam/src/layouts/menu.rs @@ -31,10 +31,11 @@ impl MenuLayout { Rectangle::new_coords(MENU_X_PAD, MENU_Y_PAD, screensize.x - MENU_X_PAD, MENU_Y_PAD + height), MISC_CONTEXT_DEFAULT_TRUST - TRUST_OFFSET, &trng, None, crate::api::CanvasType::Menu ).expect("couldn't create menu canvas"); + let gid = menu_canvas.gid(); canvases.insert(menu_canvas.gid(), menu_canvas); Ok(MenuLayout { - menu: menu_canvas.gid(), + menu: gid, menu_y_pad: MENU_Y_PAD, _menu_x_pad: MENU_X_PAD, menu_min_height: height, @@ -54,7 +55,7 @@ impl LayoutApi for MenuLayout { rect.style = DrawStyle {fill_color: Some(PixelColor::Light), stroke_color: None, stroke_width: 0,}; gfx.draw_rectangle(rect) } - fn resize_height(&mut self, _gfx: &graphics_server::Gfx, new_height: i16, _status_canvas: &Canvas, canvases: &mut HashMap) -> Result { + fn resize_height(&mut self, _gfx: &graphics_server::Gfx, new_height: i16, _status_canvas: &Rectangle, canvases: &mut HashMap) -> Result { let menu_canvas = canvases.get_mut(&self.menu).expect("couldn't find menu canvas"); let orig_rect = menu_canvas.clip_rect(); diff --git a/services/gam/src/layouts/modal.rs b/services/gam/src/layouts/modal.rs index d66a7b1e6..76b0803b0 100644 --- a/services/gam/src/layouts/modal.rs +++ b/services/gam/src/layouts/modal.rs @@ -33,10 +33,11 @@ impl ModalLayout { Rectangle::new_coords(MODAL_X_PAD, MODAL_Y_PAD, screensize.x - MODAL_X_PAD, crate::api::MODAL_Y_MAX), MISC_CONTEXT_DEFAULT_TRUST - TRUST_OFFSET, &trng, None, CanvasType::Modal ).expect("couldn't create modal canvas"); + let modal_gid = modal_canvas.gid(); canvases.insert(modal_canvas.gid(), modal_canvas); Ok(ModalLayout { - modal: modal_canvas.gid(), + modal: modal_gid, modal_y_pad: MODAL_Y_PAD, _modal_x_pad: MODAL_X_PAD, modal_min_height: height, @@ -57,7 +58,7 @@ impl LayoutApi for ModalLayout { rect.style = DrawStyle {fill_color: Some(PixelColor::Light), stroke_color: None, stroke_width: 0,}; gfx.draw_rectangle(rect) } - fn resize_height(&mut self, _gfx: &graphics_server::Gfx, new_height: i16, _status_canvas: &Canvas, canvases: &mut HashMap) -> Result { + fn resize_height(&mut self, _gfx: &graphics_server::Gfx, new_height: i16, _status_canvas: &Rectangle, canvases: &mut HashMap) -> Result { let modal_canvas = canvases.get_mut(&self.modal).expect("couldn't find modal canvas"); let orig_rect = modal_canvas.clip_rect(); diff --git a/services/gam/src/main.rs b/services/gam/src/main.rs index 671feb70a..50a4c24f8 100644 --- a/services/gam/src/main.rs +++ b/services/gam/src/main.rs @@ -59,16 +59,18 @@ fn xmain() -> ! { let screensize = gfx.screen_size().expect("Couldn't get screen size"); // the status canvas is special -- there can only be one, and it is ultimately trusted - let mut status_canvas = Canvas::new( + let status_canvas = Canvas::new( Rectangle::new_coords( 0, 0, screensize.x, gfx.glyph_height_hint(GlyphStyle::Cjk).expect("couldn't get glyph height") as i16 * 2), 255, &trng, None, crate::api::CanvasType::Status ).expect("couldn't create status canvas"); + let status_cliprect = status_canvas.clip_rect(); status_canvas.set_onscreen(true); status_canvas.set_drawable(true); + let status_gid = status_canvas.gid().gid(); canvases.insert(status_canvas.gid(), status_canvas); - canvases = recompute_canvases(&canvases, Rectangle::new(Point::new(0, 0), screensize)); + recompute_canvases(&canvases); // initialize the status bar -- this needs to start late, after the IMEF and most other things are initialized // this used to be domiciled in the GAM, but we split it out because this started to pull too much functionality @@ -76,8 +78,6 @@ fn xmain() -> ! { // we do a hack to try and push a GID to the status bar "securely": we introduce a race condition where we hope // that the GAM is the first thing to talk to the status bar, and the first message is its GID to render on. // generally should be OK, because during boot, all processes are trusted... - let status_gid = status_canvas.gid().gid(); - log::trace!("initializing status bar with gid {:?}", status_gid); let status_conn = xns.request_connection_blocking("_Status bar GID receiver_").expect("couldn't connect to status bar GID receiver"); xous::send_message(status_conn, xous::Message::new_scalar(0, // message type doesn't matter because there is only one message it should ever receive @@ -273,14 +273,13 @@ fn xmain() -> ! { log::trace!("SetCanvasBoundsRequest {:?}", cb); let granted = if cb.token_type == TokenType::Gam { - context_mgr.set_canvas_height(&gfx, cb.token, cb.requested.y, &status_canvas, &mut canvases) + context_mgr.set_canvas_height(&gfx, cb.token, cb.requested.y, &status_cliprect, &mut canvases) } else { - context_mgr.set_canvas_height_app_token(&gfx, cb.token, cb.requested.y, &status_canvas, &mut canvases) + context_mgr.set_canvas_height_app_token(&gfx, cb.token, cb.requested.y, &status_cliprect, &mut canvases) }; if granted.is_some() { // recompute the canvas orders based on the new layout - let recomp_canvases = recompute_canvases(&canvases, Rectangle::new(Point::new(0, 0), screensize)); - canvases = recomp_canvases; + recompute_canvases(&canvases); // this set of redraw commands is not needed because every context will call redraw after it has finished fitting its bounds // log::info!("canvas bounds redraw"); // context_mgr.redraw().expect("can't redraw after new canvas bounds"); @@ -416,13 +415,13 @@ fn xmain() -> ! { }; // note that we are currently assigning all Ux registrations a trust level consistent with a boot context (ultimately trusted) // this needs to be modified later on once we allow post-boot apps to be created - let token = context_mgr.register(&gfx, &trng, &status_canvas, &mut canvases, + let token = context_mgr.register(&gfx, &trng, &status_cliprect, &mut canvases, registration); // compute what canvases are drawable // this _replaces_ the original canvas structure, to avoid complications of tracking mutable references through compound data structures // this is broken into two steps because of https://github.com/rust-lang/rust/issues/71126 - canvases = recompute_canvases(&canvases, Rectangle::new(Point::new(0, 0), screensize)); + recompute_canvases(&canvases); buffer.replace(Return::UxToken(token)).unwrap();