diff --git a/services/gam/src/api.rs b/services/gam/src/api.rs index 25b3fa14e..339083e47 100644 --- a/services/gam/src/api.rs +++ b/services/gam/src/api.rs @@ -1,5 +1,5 @@ use xous::{Message, ScalarMessage}; -use graphics_server::api::{Point, Rectangle, TextView, TextViewResult, Gid}; +use graphics_server::api::{Point, Rectangle, TextView, TextViewResult, Gid, Line}; use blitstr_ref as blitstr; use blitstr::{GlyphStyle, Cursor}; @@ -23,6 +23,12 @@ pub enum Opcode { // indicates if the current UI layout requires an input field HasInput(bool), + + // return the dimensions of a canvas + GetCanvasBounds(Gid), + + // draws a line on a canvas + DrawLine(Gid, Line), } impl core::convert::TryFrom<&Message> for Opcode { @@ -33,6 +39,10 @@ impl core::convert::TryFrom<&Message> for Opcode { 0 => Ok(Opcode::ClearCanvas(Gid::new([m.arg1 as _, m.arg2 as _, m.arg3 as _, m.arg4 as _]))), _ => Err("GAM api: unknown Scalar ID"), }, + Message::BlockingScalar(m) => match m.id { + 0 => Ok(Opcode::GetCanvasBounds(Gid::new([m.arg1 as _, m.arg2 as _, m.arg3 as _, m.arg4 as _]))), + _ => Err("GAM api: unknown BlockingScalar ID"), + } _ => Err("GAM api: unhandled message type"), } } @@ -44,6 +54,9 @@ impl Into for Opcode { Opcode::ClearCanvas(gid) => Message::Scalar(ScalarMessage { id: 0, arg1: gid.gid()[0] as _, arg2: gid.gid()[1] as _, arg3: gid.gid()[2] as _, arg4: gid.gid()[3] as _ }), + Opcode::GetCanvasBounds(gid) => Message::BlockingScalar(ScalarMessage { + id: 0, arg1: gid.gid()[0] as _, arg2: gid.gid()[1] as _, arg3: gid.gid()[2] as _, arg4: gid.gid()[3] as _ + }), _ => panic!("GAM api: Opcode type not handled by Into(), maybe you meant to use a helper method?"), } } diff --git a/services/gam/src/lib.rs b/services/gam/src/lib.rs index 61bab93fa..d5651b5ad 100644 --- a/services/gam/src/lib.rs +++ b/services/gam/src/lib.rs @@ -17,10 +17,10 @@ pub fn post_textview(gam_cid: xous::CID, tv: &mut TextView) -> Result<(), xous:: tv.set_op(TextOp::Render); let mut rkyv_tv = api::Opcode::RenderTextView(*tv); let mut writer = rkyv::ArchiveBuffer::new(xous::XousBuffer::new(4096)); - let pos = writer.archive(&rkyv_tv).expect("couldn't archive textview"); + let pos = writer.archive(&rkyv_tv).expect("GAM_API: couldn't archive textview"); let mut xous_buffer = writer.into_inner(); - xous_buffer.lend_mut(gam_cid, pos as u32).expect("RenderTextView operation failure"); + xous_buffer.lend_mut(gam_cid, pos as u32).expect("GAM_API: RenderTextView operation failure"); // recover the mutable values and mirror the ones we care about back into our local structure let returned = unsafe { rkyv::archived_value::(xous_buffer.as_ref(), pos)}; @@ -31,9 +31,20 @@ pub fn post_textview(gam_cid: xous::CID, tv: &mut TextView) -> Result<(), xous:: } else { let tvr = returned.unarchive(); info!("got {:?}", tvr); - panic!("post_textview got a return value from the server that isn't expected or handled"); + panic!("GAM_API: post_textview got a return value from the server that isn't expected or handled"); } tv.set_op(TextOp::Nop); Ok(()) +} + +pub fn get_canvas_bounds(gam_cid: xous::CID, gid: Gid) -> Result { + let response = xous::send_message(gam_cid, api::Opcode::GetCanvasBounds(gid).into())?; + if let xous::Result::Scalar2(tl, br) = response { + // note that the result should always be normalized so the rectangle's "tl" should be (0,0) + assert!(tl == 0, "GAM_API: api call returned non-zero top left for canvas bounds"); + Ok(br.into()) + } else { + panic!("GAM_API: can't get canvas bounds") + } } \ No newline at end of file diff --git a/services/gam/src/main.rs b/services/gam/src/main.rs index 7ccccc9c2..66119a2ad 100644 --- a/services/gam/src/main.rs +++ b/services/gam/src/main.rs @@ -160,6 +160,19 @@ fn xmain() -> ! { None => info!("GAM: attempt to clear bogus canvas, ignored."), } }, + Opcode::GetCanvasBounds(gid) => { + match canvases.get(&gid) { + Some(c) => { + let mut rect = c.clip_rect(); + rect.translate(rect.tl); // normalize to 0,0 coordinates + xous::return_scalar2(envelope.sender, + rect.tl.into(), + rect.br.into(), + ).expect("GAM: couldn't return canvas bounds"); + }, + None => info!("GAM: attempt to get bounds on bogus canvas, ignored."), + } + } _ => todo!("GAM: opcode not yet implemented"), } } else if let xous::Message::MutableBorrow(m) = &envelope.body { diff --git a/services/gam/src/status.rs b/services/gam/src/status.rs index 0fc8c30c6..2befa68f0 100644 --- a/services/gam/src/status.rs +++ b/services/gam/src/status.rs @@ -22,15 +22,13 @@ pub fn status_thread(canvas_gid: [u32; 4]) { let gam_conn = xous_names::request_connection_blocking(xous::names::SERVER_NAME_GAM).expect("GAM|status: can't connect to GAM"); info!("GAM|status: getting screen size"); - let screensize = graphics_server::screen_size(gfx_conn).expect("GAM|status: Couldn't get screen size"); - info!("GAM|status: getting height hints"); - let small_height: i16 = graphics_server::glyph_height_hint(gfx_conn, blitstr::GlyphStyle::Small).expect("GAM|status: couldn't get glyph height") as i16; + let screensize = gam::get_canvas_bounds(gam_conn, status_gid).expect("GAM|status: Couldn't get canvas size"); info!("GAM|status: building textview objects"); // build uptime text view: left half of status bar let mut uptime_tv = TextView::new(status_gid, 0, TextBounds::BoundingBox(Rectangle::new(Point::new(0,0), - Point::new(screensize.x / 2, small_height)))); + Point::new(screensize.x / 2, screensize.y - 1)))); uptime_tv.untrusted = false; uptime_tv.style = blitstr::GlyphStyle::Small; uptime_tv.draw_border = false; @@ -42,7 +40,7 @@ pub fn status_thread(canvas_gid: [u32; 4]) { // build battstats text view: right half of status bar let mut battstats_tv = TextView::new(status_gid, 0, TextBounds::BoundingBox(Rectangle::new(Point::new(screensize.x / 2, 0), - Point::new(screensize.x, small_height)))); + Point::new(screensize.x, screensize.y - 1)))); battstats_tv.style = blitstr::GlyphStyle::Small; battstats_tv.draw_border = false; battstats_tv.margin = Point::new(0, 0);