mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-08 04:56:43 +00:00
refactoring of interfaces
This commit is contained in:
parent
82e7855b24
commit
b72d2f2bb3
8 changed files with 181 additions and 83 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -65,6 +65,10 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blitstr"
|
||||
version = "0.3.0"
|
||||
|
||||
[[package]]
|
||||
name = "blitstr"
|
||||
version = "0.3.0"
|
||||
|
|
@ -256,7 +260,7 @@ name = "gam"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"blitstr",
|
||||
"blitstr 0.3.0",
|
||||
"com",
|
||||
"graphics-server",
|
||||
"hash32",
|
||||
|
|
@ -315,7 +319,7 @@ dependencies = [
|
|||
name = "graphics-server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blitstr",
|
||||
"blitstr 0.3.0",
|
||||
"keyboard",
|
||||
"log",
|
||||
"log-server",
|
||||
|
|
@ -893,7 +897,7 @@ name = "shell"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"blitstr",
|
||||
"blitstr 0.3.0 (git+https://github.com/betrusted-io/blitstr.git?rev=ea27e611d5ee165d8be894f9ca1c1130156c1931)",
|
||||
"com",
|
||||
"graphics-server",
|
||||
"heapless",
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ hash32-derive = "0.1.0"
|
|||
|
||||
com = { path = "../com"}
|
||||
|
||||
# blitstr = { path = "../../../blitstr" }
|
||||
blitstr = { git = "https://github.com/betrusted-io/blitstr.git", rev = "ea27e611d5ee165d8be894f9ca1c1130156c1931" }
|
||||
blitstr = { path = "../../../blitstr" }
|
||||
# blitstr = { git = "https://github.com/betrusted-io/blitstr.git", rev = "ea27e611d5ee165d8be894f9ca1c1130156c1931" }
|
||||
|
||||
|
||||
[target.'cfg(not(any(windows,unix)))'.dependencies]
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ impl<'a> TextView<'a> {
|
|||
}
|
||||
pub fn set_op(&mut self, op: TextOp) { self.operation = op; }
|
||||
pub fn get_op(&self) -> TextOp { self.operation }
|
||||
pub fn get_canvas_gid(&self) -> Gid { self.canvas }
|
||||
}
|
||||
|
||||
impl<'a> core::fmt::Debug for TextView<'a> {
|
||||
|
|
|
|||
|
|
@ -5,16 +5,17 @@ use heapless::Vec;
|
|||
use heapless::consts::*;
|
||||
use graphics_server::{Rectangle, Point};
|
||||
use xous::ipc::Sendable;
|
||||
use log::{error, info};
|
||||
|
||||
use crate::api::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum CanvasState {
|
||||
// the initial state of every Canvas. Not drawable.
|
||||
Created,
|
||||
// this state indicates the Canvas can be drawn, but has yet to be.
|
||||
// this state indicates the Canvas can be drawn, and may or may not need to be flushed to the screen.
|
||||
DrawableDirty,
|
||||
// this state indicates the Canvas has been drawn.
|
||||
// this state indicates the Canvas has been flushed to the screen.
|
||||
DrawableDrawn,
|
||||
// indicates that the Canvas is not drawable, but needs to be defaced
|
||||
NotDrawableDirty,
|
||||
|
|
@ -41,59 +42,6 @@ pub struct Canvas {
|
|||
// enables scroll/pan of objects within a region
|
||||
pan_offset: Point,
|
||||
}
|
||||
|
||||
// we need the "screen" parameter so we can turn off drawing to canvases that are off-screen
|
||||
pub fn recompute_canvases(mut canvases: BinaryHeap<Canvas, U32, Max>, screen: Rectangle) -> (BinaryHeap<Canvas, U32, Max>, FnvIndexMap<Gid, Canvas, U32>) {
|
||||
let mut higher_clipregions: BinaryHeap<Canvas, U32, Max> = BinaryHeap::new();
|
||||
|
||||
let mut trust_level: u8 = 255;
|
||||
// canvases is a Max heap keyed on trust, so popping the elements off will return them sorted from most to least trusted
|
||||
if let Some(c) = canvases.pop() {
|
||||
let mut canvas = c.clone();
|
||||
|
||||
let mut drawable: bool = true;
|
||||
let clip_region = canvas.clip_rect();
|
||||
if trust_level < canvas.trust_level() {
|
||||
trust_level = canvas.trust_level();
|
||||
}
|
||||
// note that this .iter() is *not* sorted by trust level, but all elements will be of greater than or equal to the current trust level
|
||||
for ®ion in higher_clipregions.iter() {
|
||||
// regions of the same trust level can draw over each other. Draw order is arbitrary.
|
||||
if region.clip_rect().intersects(clip_region) && (region.trust_level() < trust_level) ||
|
||||
!region.clip_rect().intersects(screen) {
|
||||
drawable = false;
|
||||
}
|
||||
}
|
||||
match canvas.state() {
|
||||
CanvasState::Created =>
|
||||
if drawable { canvas.set_state(CanvasState::DrawableDirty) }
|
||||
else { canvas.set_state(CanvasState::NotDrawableDirty) },
|
||||
CanvasState::DrawableDirty | CanvasState::DrawableDrawn =>
|
||||
if !drawable { canvas.set_state(CanvasState::NotDrawableDirty) },
|
||||
CanvasState::NotDrawableDefaced | CanvasState::NotDrawableDirty =>
|
||||
if drawable { canvas.set_state(CanvasState::DrawableDirty) }
|
||||
}
|
||||
higher_clipregions.push(canvas).unwrap();
|
||||
}
|
||||
|
||||
let mut map: FnvIndexMap<Gid, Canvas, U32> = FnvIndexMap::new();
|
||||
for &c in higher_clipregions.iter() {
|
||||
map.insert(c.gid(), c).unwrap();
|
||||
}
|
||||
|
||||
(higher_clipregions, map)
|
||||
}
|
||||
|
||||
// Crate-level draw_textview() call for "local" services that can't use the lib.rs API
|
||||
pub fn draw_textview(gam_cid: xous::CID, tv: &mut TextView) -> Result<(), xous::Error> {
|
||||
let mut sendable_tv = Sendable::new(tv).expect("can't create sendable textview");
|
||||
sendable_tv.set_op(TextOp::Render);
|
||||
sendable_tv.lend_mut(gam_cid, sendable_tv.get_op().into()).expect("draw_textview operation failure");
|
||||
|
||||
sendable_tv.set_op(TextOp::Nop);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
pub fn new(clip_rect: Rectangle, trust_level: u8,
|
||||
trng_conn: xous::CID, pan_offset: Option<Point>) -> Result<Canvas, xous::Error> {
|
||||
|
|
@ -120,7 +68,57 @@ impl Canvas {
|
|||
pub fn gid(&self) -> Gid { self.gid }
|
||||
pub fn trust_level(&self) -> u8 { self.trust_level }
|
||||
pub fn state(&self) -> CanvasState { self.state }
|
||||
pub fn set_state(&mut self, state: CanvasState) { self.state = state; }
|
||||
pub fn is_drawable(&self) -> bool {
|
||||
if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
pub fn set_drawable(&mut self, drawable: bool) {
|
||||
if drawable {
|
||||
if self.state != CanvasState::DrawableDrawn {
|
||||
self.state = CanvasState::DrawableDirty;
|
||||
}
|
||||
} else {
|
||||
if self.state != CanvasState::NotDrawableDefaced {
|
||||
self.state = CanvasState::NotDrawableDirty;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
Ok(())
|
||||
} else if self.state == CanvasState::NotDrawableDefaced {
|
||||
Ok(())
|
||||
} else {
|
||||
error!("Canvas: flush happened before not drawable regions were defaced, or before initialized!");
|
||||
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;
|
||||
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;
|
||||
Ok(())
|
||||
} else if self.state == CanvasState::DrawableDirty || self.state == CanvasState::DrawableDrawn {
|
||||
info!("Canvas: drawable region was defaced. Allowing it, but this could be a logic bug");
|
||||
Ok(())
|
||||
} else {
|
||||
error!("Canvas: attempt to deface region already defaced, or not initialized!");
|
||||
Err(xous::Error::DoubleFree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Canvas {
|
||||
|
|
@ -139,3 +137,57 @@ impl PartialEq for Canvas {
|
|||
}
|
||||
}
|
||||
impl Eq for Canvas {}
|
||||
|
||||
|
||||
|
||||
// we use the "screen" parameter to determine when we can turn off drawing to canvases that are off-screen
|
||||
pub fn recompute_canvases(mut canvases: FnvIndexMap<Gid, Canvas, U32>, screen: Rectangle) -> FnvIndexMap<Gid, Canvas, U32> {
|
||||
// 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.
|
||||
let mut sorted_clipregions: BinaryHeap<Canvas, U32, Max> = BinaryHeap::new();
|
||||
for (_, &c) in canvases.iter() {
|
||||
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, U32, Max> = BinaryHeap::new();
|
||||
let mut 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 let Some(c) = sorted_clipregions.pop() {
|
||||
let mut canvas = c.clone();
|
||||
|
||||
let mut drawable: bool = true;
|
||||
let clip_region = canvas.clip_rect();
|
||||
if trust_level < canvas.trust_level() {
|
||||
trust_level = canvas.trust_level();
|
||||
}
|
||||
// note that this .iter() is *not* sorted by trust level, but all elements will be of greater than or equal to the current trust level
|
||||
for ®ion in higher_clipregions.iter() {
|
||||
// regions of the same trust level can draw over each other. Draw order is arbitrary.
|
||||
if region.clip_rect().intersects(clip_region) && (region.trust_level() < trust_level) ||
|
||||
!region.clip_rect().intersects(screen) {
|
||||
drawable = false;
|
||||
}
|
||||
}
|
||||
canvas.set_drawable(drawable);
|
||||
higher_clipregions.push(canvas).unwrap();
|
||||
}
|
||||
|
||||
// create a new index map out of the recomputed higher_clipregions
|
||||
let mut map: FnvIndexMap<Gid, Canvas, U32> = FnvIndexMap::new();
|
||||
for &c in higher_clipregions.iter() {
|
||||
map.insert(c.gid(), c).unwrap();
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
// Crate-level draw_textview() call for "local" services that can't use the lib.rs API
|
||||
pub fn draw_textview(gam_cid: xous::CID, tv: &mut TextView) -> Result<(), xous::Error> {
|
||||
let mut sendable_tv = Sendable::new(tv).expect("can't create sendable textview");
|
||||
sendable_tv.set_op(TextOp::Render);
|
||||
sendable_tv.lend_mut(gam_cid, sendable_tv.get_op().into()).expect("draw_textview operation failure");
|
||||
|
||||
sendable_tv.set_op(TextOp::Nop);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,24 +38,24 @@ struct ModalCanvases {
|
|||
pub alert: Gid,
|
||||
}
|
||||
|
||||
fn add_modal_layout(trng_conn: xous::CID, canvases: &mut BinaryHeap<Canvas, U32, Max>) -> Result<ModalCanvases, xous::Error> {
|
||||
fn add_modal_layout(trng_conn: xous::CID, canvases: &mut FnvIndexMap<Gid, Canvas, U32>) -> Result<ModalCanvases, xous::Error> {
|
||||
let password_canvas = Canvas::new(
|
||||
Rectangle::new_coords(-1, -1, -1, -1),
|
||||
0, trng_conn, None
|
||||
).expect("GAM: couldn't create password canvas");
|
||||
canvases.push(password_canvas).expect("GAM: can't store password canvas");
|
||||
canvases.insert(password_canvas.gid(), password_canvas).expect("GAM: can't store password canvas");
|
||||
|
||||
let menu_canvas = Canvas::new(
|
||||
Rectangle::new_coords(-1, -1, -1, -1),
|
||||
0, trng_conn, None
|
||||
).expect("GAM: couldn't create menu canvas");
|
||||
canvases.push(menu_canvas).expect("GAM: can't store menu canvas");
|
||||
canvases.insert(menu_canvas.gid(), menu_canvas).expect("GAM: can't store menu canvas");
|
||||
|
||||
let alert_canvas = Canvas::new(
|
||||
Rectangle::new_coords(-1, -1, -1, -1),
|
||||
0, trng_conn, None
|
||||
).expect("GAM: couldn't create alert canvas");
|
||||
canvases.push(alert_canvas).expect("GAM: can't store alert canvas");
|
||||
canvases.insert(alert_canvas.gid(), alert_canvas).expect("GAM: can't store alert canvas");
|
||||
|
||||
Ok(ModalCanvases {
|
||||
password: password_canvas.gid(),
|
||||
|
|
@ -64,7 +64,7 @@ fn add_modal_layout(trng_conn: xous::CID, canvases: &mut BinaryHeap<Canvas, U32,
|
|||
})
|
||||
}
|
||||
|
||||
fn add_chat_layout(gfx_conn: xous::CID, trng_conn: xous::CID, canvases: &mut BinaryHeap<Canvas, U32, Max>) -> Result<ChatLayout, xous::Error> {
|
||||
fn add_chat_layout(gfx_conn: xous::CID, trng_conn: xous::CID, canvases: &mut FnvIndexMap<Gid, Canvas, U32>) -> Result<ChatLayout, xous::Error> {
|
||||
let screensize = graphics_server::screen_size(gfx_conn).expect("GAM: Couldn't get screen size");
|
||||
// get the height of various text regions to compute the layout
|
||||
let small_height: i16 = graphics_server::glyph_height_hint(gfx_conn, GlyphStyle::Small).expect("GAM: couldn't get glyph height") as i16;
|
||||
|
|
@ -75,26 +75,26 @@ fn add_chat_layout(gfx_conn: xous::CID, trng_conn: xous::CID, canvases: &mut Bin
|
|||
Rectangle::new_coords(0, 0, screensize.x, small_height),
|
||||
0, trng_conn, None
|
||||
).expect("GAM: couldn't create status canvas");
|
||||
canvases.push(status_canvas).expect("GAM: can't store status canvus");
|
||||
canvases.insert(status_canvas.gid(), status_canvas).expect("GAM: can't store status canvus");
|
||||
|
||||
let predictive_canvas = Canvas::new(
|
||||
Rectangle::new_coords(0, screensize.y - regular_height, screensize.x, screensize.y),
|
||||
1,
|
||||
trng_conn, None
|
||||
).expect("GAM: couldn't create predictive text canvas");
|
||||
canvases.push(predictive_canvas).expect("GAM: couldn't store predictive canvas");
|
||||
canvases.insert(predictive_canvas.gid(), predictive_canvas).expect("GAM: couldn't store predictive canvas");
|
||||
|
||||
let input_canvas = Canvas::new(
|
||||
Rectangle::new_v_stack(predictive_canvas.clip_rect(), -regular_height),
|
||||
1, trng_conn, None
|
||||
).expect("GAM: couldn't create input text canvas");
|
||||
canvases.push(input_canvas).expect("GAM: couldn't store input canvas");
|
||||
canvases.insert(input_canvas.gid(), input_canvas).expect("GAM: couldn't store input canvas");
|
||||
|
||||
let content_canvas = Canvas::new(
|
||||
Rectangle::new_v_span(status_canvas.clip_rect(), input_canvas.clip_rect()),
|
||||
2, trng_conn, None
|
||||
).expect("GAM: couldn't create content canvas");
|
||||
canvases.push(content_canvas).expect("GAM: can't store content canvas");
|
||||
canvases.insert(content_canvas.gid(), content_canvas).expect("GAM: can't store content canvas");
|
||||
|
||||
Ok(ChatLayout {
|
||||
status: status_canvas.gid(),
|
||||
|
|
@ -104,7 +104,7 @@ fn add_chat_layout(gfx_conn: xous::CID, trng_conn: xous::CID, canvases: &mut Bin
|
|||
})
|
||||
}
|
||||
|
||||
fn tv_draw(gfx_conn: xous::CID, trng_conn: xous::CID, tv: &mut TextView) -> Result<(), xous::Error> {
|
||||
fn tv_draw(gfx_conn: xous::CID, trng_conn: xous::CID, canvases: &mut FnvIndexMap<Gid, Canvas, U32>, tv: &mut TextView) -> Result<(), xous::Error> {
|
||||
/*
|
||||
1. figure out text bounds
|
||||
2. clear background, if requested
|
||||
|
|
@ -112,9 +112,24 @@ fn tv_draw(gfx_conn: xous::CID, trng_conn: xous::CID, tv: &mut TextView) -> Resu
|
|||
4. draw text
|
||||
*/
|
||||
|
||||
// figure out text bounds: figure out how wide our text is, to start with.
|
||||
if let Some(canvas) = canvases.get_mut(&tv.get_canvas_gid()) {
|
||||
// first, figure out if we should even be drawing to this canvas.
|
||||
if canvas.is_drawable() {
|
||||
// figure out text bounds: figure out how wide our text is, to start with.
|
||||
|
||||
} else {
|
||||
info!("GAM: attempt to draw TextView on non-drawable canvas. Not fatal, but request ignored.");
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
info!("GAM: bogus GID in TextView, not doing anything in response to draw request.");
|
||||
return Ok(()) // silently fail if a bogus Gid is given???
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
#[xous::xous_main]
|
||||
|
|
@ -130,18 +145,15 @@ fn xmain() -> ! {
|
|||
|
||||
let screensize = graphics_server::screen_size(gfx_conn).expect("GAM: Couldn't get screen size");
|
||||
|
||||
let mut canvases: BinaryHeap<Canvas, U32, Max> = BinaryHeap::new();
|
||||
// a map of canvases accessable by Gid
|
||||
let mut canvases: FnvIndexMap<Gid, Canvas, U32> = FnvIndexMap::new();
|
||||
let modallayout = add_modal_layout(trng_conn, &mut canvases).expect("GAM: can't add modal layouts");
|
||||
let chatlayout = add_chat_layout(gfx_conn, trng_conn, &mut canvases).expect("GAM: couldn't create chat layout");
|
||||
|
||||
// canvas_map is a copy of the canvases, but searchable by GID
|
||||
let canvas_map: FnvIndexMap<Gid, Canvas, U32>;
|
||||
|
||||
// now that all the initial canvases have been allocated, 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
|
||||
let (c_tuple, m_tuple) = recompute_canvases(canvases, Rectangle::new(Point::new(0, 0), screensize));
|
||||
canvases = c_tuple; canvas_map = m_tuple;
|
||||
canvases = recompute_canvases(canvases, Rectangle::new(Point::new(0, 0), screensize));
|
||||
|
||||
// make a thread to manage the status bar
|
||||
xous::create_thread_simple(status_thread, chatlayout.status).expect("GAM: couldn't create status thread");
|
||||
|
|
@ -157,7 +169,7 @@ fn xmain() -> ! {
|
|||
if let Ok(opcode) = Opcode::try_from(&envelope.body) {
|
||||
match opcode {
|
||||
Opcode::ClearCanvas(gid) => {
|
||||
match canvas_map.get(&gid) {
|
||||
match canvases.get(&gid) {
|
||||
Some(c) => {
|
||||
let mut rect = c.clip_rect();
|
||||
rect.style = DrawStyle {
|
||||
|
|
@ -180,7 +192,7 @@ fn xmain() -> ! {
|
|||
&mut *(m.buf.as_mut_ptr() as *mut TextView)
|
||||
};
|
||||
info!("GAM: render request for {:?}", tv);
|
||||
tv_draw(gfx_conn, trng_conn, &mut tv).expect("GAM: can't render TextView");
|
||||
tv_draw(gfx_conn, trng_conn, &mut canvases, &mut tv).expect("GAM: can't render TextView");
|
||||
},
|
||||
TextOp::ComputeBounds => {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ log-server = { path = "../log-server" }
|
|||
xous-names = { path = "../xous-names" }
|
||||
log = "0.4"
|
||||
keyboard = { path = "../keyboard" }
|
||||
blitstr = { git = "https://github.com/betrusted-io/blitstr.git", rev = "ea27e611d5ee165d8be894f9ca1c1130156c1931" }
|
||||
# blitstr = { path = "../../../blitstr" }
|
||||
# blitstr = { git = "https://github.com/betrusted-io/blitstr.git", rev = "ea27e611d5ee165d8be894f9ca1c1130156c1931" }
|
||||
blitstr = { path = "../../../blitstr" }
|
||||
|
||||
[target.'cfg(not(any(windows,unix)))'.dependencies]
|
||||
utralib = { path = "../../utralib"}
|
||||
|
|
|
|||
|
|
@ -466,6 +466,9 @@ pub enum Opcode<'a> {
|
|||
/// Xor the string inside the clipping region.
|
||||
StringXor(&'a str),
|
||||
|
||||
/// Simulate the string on the clipping region (for computing text widths)
|
||||
SimulateString(&'a str),
|
||||
|
||||
/// Retrieve the X and Y dimensions of the screen
|
||||
ScreenSize,
|
||||
|
||||
|
|
@ -538,6 +541,15 @@ impl<'a> core::convert::TryFrom<&'a Message> for Opcode<'a> {
|
|||
};
|
||||
Ok(Opcode::StringXor(core::str::from_utf8(s).unwrap()))
|
||||
},
|
||||
3 => {
|
||||
let s = unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
m.buf.as_ptr(),
|
||||
m.valid.map(|x| x.get()).unwrap_or_else(|| m.buf.len()),
|
||||
)
|
||||
};
|
||||
Ok(Opcode::SimulateString(core::str::from_utf8(s).unwrap()))
|
||||
},
|
||||
_ => Err("unrecognized opcode"),
|
||||
},
|
||||
_ => Err("unhandled message type"),
|
||||
|
|
@ -619,6 +631,10 @@ impl<'a> Into<Message> for Opcode<'a> {
|
|||
let region = xous::carton::Carton::from_bytes(string.as_bytes());
|
||||
Message::Borrow(region.into_message(2))
|
||||
}
|
||||
Opcode::SimulateString(string) => {
|
||||
let region = xous::carton::Carton::from_bytes(string.as_bytes());
|
||||
Message::Borrow(region.into_message(3))
|
||||
}
|
||||
Opcode::SetCursor(c) => Message::Scalar(ScalarMessage {
|
||||
id: 12,
|
||||
arg1: c.pt.x,
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ fn xmain() -> ! {
|
|||
current_glyph.into(),
|
||||
s,
|
||||
false,
|
||||
blitstr::xor_char
|
||||
);
|
||||
}
|
||||
Opcode::StringXor(s) => {
|
||||
|
|
@ -81,6 +82,18 @@ fn xmain() -> ! {
|
|||
current_glyph.into(),
|
||||
s,
|
||||
true,
|
||||
blitstr::xor_char
|
||||
);
|
||||
}
|
||||
Opcode::SimulateString(s) => {
|
||||
blitstr::paint_str(
|
||||
display.native_buffer(),
|
||||
current_string_clip.into(),
|
||||
&mut current_cursor,
|
||||
current_glyph.into(),
|
||||
s,
|
||||
false,
|
||||
blitstr::simulate_char
|
||||
);
|
||||
}
|
||||
Opcode::SetGlyphStyle(glyph) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue