From 38e5829196e87cf67a09fb2cf4539dd399b38145 Mon Sep 17 00:00:00 2001 From: darkfi Date: Tue, 6 Jan 2026 15:27:39 +0100 Subject: [PATCH] app: various cleanups to Editor used by BaseEdit with main one being moving from async to purely sync. other changes: * Removed `Option` wrapper from editor * Removed `EditorHandle` wrapper * Changed all editor locks to synchronous * Made all Editor methods synchronous * Created `ParleyDriverWrapper`. This makes using the driver much easier. --- bin/app/src/text/editor/android.rs | 16 +- bin/app/src/text/editor/mod.rs | 1 + bin/app/src/text/editor/parley.rs | 16 +- bin/app/src/text/mod.rs | 8 +- bin/app/src/ui/edit/behave.rs | 33 +-- bin/app/src/ui/edit/mod.rs | 328 +++++++++++++---------------- 6 files changed, 173 insertions(+), 229 deletions(-) diff --git a/bin/app/src/text/editor/android.rs b/bin/app/src/text/editor/android.rs index 71d98bb3c..d2453937e 100644 --- a/bin/app/src/text/editor/android.rs +++ b/bin/app/src/text/editor/android.rs @@ -73,16 +73,16 @@ impl Editor { } } - pub async fn on_text_prop_changed(&mut self) { + pub fn on_text_prop_changed(&mut self) { // Update GameTextInput state self.state.text = self.text.get(); self.state.select = (0, 0); self.state.compose = None; self.input.set_state(self.state.clone()); // Refresh our layout - self.refresh().await; + self.refresh(); } - pub async fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) { + pub fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) { // Only refresh layout if text content actually changed // Avoid triggering expensive recomputes of layout and property tree. let old_text = self.text.get(); @@ -90,7 +90,7 @@ impl Editor { return } - self.refresh().await; + self.refresh(); // Update the text attribute self.text.set(atom, &self.state.text); } @@ -102,7 +102,7 @@ impl Editor { self.input.hide(); } - pub async fn refresh(&mut self) { + pub fn refresh(&mut self) { let font_size = self.font_size.get(); let text_color = self.text_color.get(); let window_scale = self.window_scale.get(); @@ -139,7 +139,7 @@ impl Editor { self.input.set_select(cursor_idx, cursor_idx); } - pub async fn select_word_at_point(&mut self, pos: Point) { + pub fn select_word_at_point(&mut self, pos: Point) { let select = parley::Selection::word_from_point(&self.layout, pos.x, pos.y); assert!(!select.is_collapsed()); let select = select.text_range(); @@ -163,7 +163,7 @@ impl Editor { Point::new(cursor_rect.x0 as f32, cursor_rect.y0 as f32) } - pub async fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) { + pub fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) { // TODO: need to verify this is correct // Insert text by updating the state self.state.text.push_str(txt); @@ -214,7 +214,7 @@ impl Editor { parley::Selection::new(anchor, focus) } - pub async fn set_selection(&mut self, select_start: usize, select_end: usize) { + pub fn set_selection(&mut self, select_start: usize, select_end: usize) { assert!(select_start <= self.state.text.len()); assert!(select_end <= self.state.text.len()); assert_eq!(self.state.text, self.text.get()); diff --git a/bin/app/src/text/editor/mod.rs b/bin/app/src/text/editor/mod.rs index 4618d6bc2..8d569e916 100644 --- a/bin/app/src/text/editor/mod.rs +++ b/bin/app/src/text/editor/mod.rs @@ -21,6 +21,7 @@ mod android; mod driver; #[cfg(target_os = "android")] pub use android::Editor; +pub use driver::ParleyDriverWrapper; #[cfg(not(target_os = "android"))] mod parley; diff --git a/bin/app/src/text/editor/parley.rs b/bin/app/src/text/editor/parley.rs index 7e7bdbf98..69ec32efa 100644 --- a/bin/app/src/text/editor/parley.rs +++ b/bin/app/src/text/editor/parley.rs @@ -57,19 +57,19 @@ impl Editor { pub fn focus(&self) {} pub fn unfocus(&self) {} - pub async fn on_text_prop_changed(&mut self) { + pub fn on_text_prop_changed(&mut self) { // Get modified text property let txt = self.text.get(); // Update Parley text buffer self.editor.set_text(&txt); // Refresh our layout - self.refresh().await; + self.refresh(); } - pub async fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) { + pub fn on_buffer_changed(&mut self, atom: &mut PropertyAtomicGuard) { self.text.set(atom, self.editor.raw_text()); } - pub async fn refresh(&mut self) { + pub fn refresh(&mut self) { let font_size = self.font_size.get(); let text_color = self.text_color.get(); let window_scale = self.window_scale.get(); @@ -99,7 +99,7 @@ impl Editor { pub fn move_to_pos(&self, _pos: Point) { unimplemented!() } - pub async fn select_word_at_point(&mut self, _pos: Point) { + pub fn select_word_at_point(&mut self, _pos: Point) { unimplemented!() } @@ -109,9 +109,9 @@ impl Editor { cursor_pos } - pub async fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) { + pub fn insert(&mut self, txt: &str, atom: &mut PropertyAtomicGuard) { self.driver().insert_or_replace_selection(&txt); - self.on_buffer_changed(atom).await; + self.on_buffer_changed(atom); } pub fn driver(&mut self) -> ParleyDriverWrapper { @@ -137,7 +137,7 @@ impl Editor { } /// Android uses byte indexes whereas parley has its own things. So this API is a compromise /// between them both. - pub async fn set_selection(&mut self, select_start: usize, select_end: usize) { + pub fn set_selection(&mut self, select_start: usize, select_end: usize) { self.driver().select_byte_range(select_start, select_end); } diff --git a/bin/app/src/text/mod.rs b/bin/app/src/text/mod.rs index 1bf57e748..303fc87f7 100644 --- a/bin/app/src/text/mod.rs +++ b/bin/app/src/text/mod.rs @@ -16,14 +16,18 @@ * along with this program. If not, see . */ -use std::{cell::RefCell, ops::Range, sync::{Arc, LazyLock}}; use parley::fontique::{Collection, CollectionOptions, SourceCache, SourceCacheOptions}; +use std::{ + cell::RefCell, + ops::Range, + sync::{Arc, LazyLock}, +}; use crate::{mesh::Color, util::spawn_thread}; pub mod atlas; mod editor; -pub use editor::Editor; +pub use editor::{Editor, ParleyDriverWrapper}; mod render; pub use render::{render_layout, render_layout_with_opts, DebugRenderOptions}; diff --git a/bin/app/src/ui/edit/behave.rs b/bin/app/src/ui/edit/behave.rs index f62316a64..a03fc8ebd 100644 --- a/bin/app/src/ui/edit/behave.rs +++ b/bin/app/src/ui/edit/behave.rs @@ -15,7 +15,6 @@ * along with this program. If not, see . */ -use async_lock::Mutex as AsyncMutex; use async_trait::async_trait; use atomic_float::AtomicF32; use parking_lot::Mutex as SyncMutex; @@ -27,8 +26,6 @@ use crate::{ text::Editor, }; -use super::EditorHandle; - //macro_rules! t { ($($arg:tt)*) => { trace!(target: "ui::edit::behave", $($arg)*); } } pub enum BaseEditType { @@ -87,17 +84,12 @@ pub(super) struct MultiLine { pub padding: PropertyPtr, pub cursor_descent: PropertyFloat32, pub parent_rect: Arc>>, - pub editor: Arc>>, + pub editor: Arc>, pub content_height: AtomicF32, pub scroll: Arc, } impl MultiLine { - /// Lazy-initializes the editor and returns a handle to it - async fn lock_editor<'a>(&'a self) -> EditorHandle<'a> { - EditorHandle { guard: self.editor.lock().await } - } - fn bounded_height(&self, height: f32) -> f32 { height.clamp(self.min_height.get(), self.max_height.get()) } @@ -112,7 +104,7 @@ impl MultiLine { /// Gets the real cursor pos within the rect. async fn get_cursor_pos(&self) -> Point { // This is the position within the content. - let cursor_pos = self.lock_editor().await.get_cursor_pos(); + let cursor_pos = self.editor.lock().get_cursor_pos(); // Apply the inner padding cursor_pos + self.inner_pos() } @@ -140,9 +132,9 @@ impl EditorBehavior for MultiLine { // Use the width to adjust the height calcs let rect_w = self.rect.get_width() - pad_left - pad_right; let content_height = { - let mut editor = self.lock_editor().await; + let mut editor = self.editor.lock(); editor.set_width(rect_w); - editor.refresh().await; + editor.refresh(); editor.height() }; self.content_height.store(content_height, Ordering::Relaxed); @@ -242,24 +234,17 @@ pub(super) struct SingleLine { pub padding: PropertyPtr, pub cursor_width: PropertyFloat32, pub parent_rect: Arc>>, - pub editor: Arc>>, + pub editor: Arc>, pub content_height: AtomicF32, pub scroll: Arc, } -impl SingleLine { - /// Lazy-initializes the editor and returns a handle to it - async fn lock_editor<'a>(&'a self) -> EditorHandle<'a> { - EditorHandle { guard: self.editor.lock().await } - } -} - #[async_trait] impl EditorBehavior for SingleLine { async fn eval_rect(&self, atom: &mut PropertyAtomicGuard) { let content_height = { - let mut editor = self.lock_editor().await; - editor.refresh().await; + let mut editor = self.editor.lock(); + editor.refresh(); editor.height() }; self.content_height.store(content_height, Ordering::Relaxed); @@ -283,7 +268,7 @@ impl EditorBehavior for SingleLine { let pad_left = self.padding.get_f32(3).unwrap(); let scroll = self.scroll.load(Ordering::Relaxed); let rect_w = self.rect.get_width() - pad_right; - let cursor_x0 = self.lock_editor().await.get_cursor_pos().x + pad_left; + let cursor_x0 = self.editor.lock().get_cursor_pos().x + pad_left; let cursor_x1 = cursor_x0 + self.cursor_width.get(); if cursor_x0 < scroll { @@ -304,7 +289,7 @@ impl EditorBehavior for SingleLine { let pad_right = self.padding.get_f32(1).unwrap(); let pad_left = self.padding.get_f32(3).unwrap(); let rect_w = self.rect.get_width(); - let content_w = self.lock_editor().await.width() + self.cursor_width.get(); + let content_w = self.editor.lock().width() + self.cursor_width.get(); (pad_left + pad_right + content_w - rect_w).max(0.) } diff --git a/bin/app/src/ui/edit/mod.rs b/bin/app/src/ui/edit/mod.rs index d1d449980..7fb26166d 100644 --- a/bin/app/src/ui/edit/mod.rs +++ b/bin/app/src/ui/edit/mod.rs @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -use async_lock::Mutex as AsyncMutex; use async_trait::async_trait; use atomic_float::AtomicF32; use darkfi::system::msleep; @@ -179,23 +178,6 @@ impl std::fmt::Debug for Editor { } */ -struct EditorHandle<'a> { - guard: async_lock::MutexGuard<'a, Option>, -} - -impl<'a> Deref for EditorHandle<'a> { - type Target = Editor; - - fn deref(&self) -> &Self::Target { - self.guard.as_ref().unwrap() - } -} -impl<'a> DerefMut for EditorHandle<'a> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.guard.as_mut().unwrap() - } -} - pub type BaseEditPtr = Arc; pub struct BaseEdit { @@ -258,7 +240,7 @@ pub struct BaseEdit { parent_rect: Arc>>, is_mouse_hover: AtomicBool, - editor: Arc>>, + editor: Arc>, behave: Box, } @@ -309,8 +291,16 @@ impl BaseEdit { let debug = PropertyBool::wrap(node_ref, Role::Internal, "debug", 0).unwrap(); let parent_rect = Arc::new(SyncMutex::new(None)); - let editor = Arc::new(AsyncMutex::new(None)); let scroll = Arc::new(AtomicF32::new(0.)); + + let editor = Arc::new(SyncMutex::new(Editor::new( + text.clone(), + font_size.clone(), + text_color.clone(), + window_scale.clone(), + lineheight.clone(), + ))); + let behave: Box = match edit_type { BaseEditType::SingleLine => Box::new(SingleLine { rect: rect.clone(), @@ -420,16 +410,11 @@ impl BaseEdit { /// Gets the real cursor pos within the rect. async fn get_cursor_pos(&self) -> Point { // This is the position within the content. - let cursor_pos = self.lock_editor().await.get_cursor_pos(); + let cursor_pos = self.editor.lock().get_cursor_pos(); // Apply the inner padding cursor_pos + self.behave.inner_pos() } - /// Lazy-initializes the editor and returns a handle to it - async fn lock_editor<'a>(&'a self) -> EditorHandle<'a> { - EditorHandle { guard: self.editor.lock().await } - } - fn regen_cursor_mesh(&self) -> DrawMesh { let cursor_width = self.cursor_width.get(); let cursor_ascent = self.cursor_ascent.get(); @@ -516,7 +501,7 @@ impl BaseEdit { match key { 'a' => { if action_mod { - let mut editor = self.lock_editor().await; + let mut editor = self.editor.lock(); editor.driver().select_all(); if let Some(seltext) = editor.selected_text() { self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap(); @@ -525,7 +510,7 @@ impl BaseEdit { } 'c' => { if action_mod { - let editor = self.lock_editor().await; + let editor = self.editor.lock(); if let Some(txt) = editor.selected_text() { miniquad::window::clipboard_set(&txt); } @@ -534,7 +519,7 @@ impl BaseEdit { 'v' => { if action_mod { if let Some(txt) = miniquad::window::clipboard_get() { - self.insert(&txt, atom).await; + self.editor.lock().insert(&txt, atom); // Maybe insert should call this? self.behave.apply_cursor_scroll().await; } @@ -556,135 +541,132 @@ impl BaseEdit { ) -> bool { #[cfg(not(target_os = "macos"))] let action_mod = mods.ctrl; - #[cfg(target_os = "macos")] let action_mod = mods.logo; t!("handle_key({:?}, {:?}) action_mod={action_mod}", key, mods); + { + let mut editor = self.editor.lock(); + match key { + KeyCode::Left => { + if action_mod { + if mods.shift { + editor.driver().select_word_left(); + } else { + editor.driver().move_word_left(); + } + } else if mods.shift { + editor.driver().select_left(); + } else { + editor.driver().move_left(); + } + } + KeyCode::Right => { + if action_mod { + if mods.shift { + editor.driver().select_word_right(); + } else { + editor.driver().move_word_right(); + } + } else if mods.shift { + editor.driver().select_right(); + } else { + editor.driver().move_right(); + } + } + KeyCode::Up => { + if mods.shift { + editor.driver().select_up(); + } else { + editor.driver().move_up(); + } + } + KeyCode::Down => { + if mods.shift { + editor.driver().select_down(); + } else { + editor.driver().move_down(); + } + } + KeyCode::Enter | KeyCode::KpEnter => { + if mods.shift { + if self.behave.allow_endl() { + editor.driver().insert_or_replace_selection("\n"); + editor.on_buffer_changed(atom); + } + } else { + //let node = self.node.upgrade().unwrap(); + //node.trigger("enter_pressed", vec![]).await.unwrap(); + return false; + } + } + KeyCode::Delete => { + if action_mod { + editor.driver().delete_word(); + } else { + editor.driver().delete(); + } + editor.on_buffer_changed(atom); + } + KeyCode::Backspace => { + if action_mod { + editor.driver().backdelete_word(); + } else { + editor.driver().backdelete(); + } + editor.on_buffer_changed(atom); + } + KeyCode::Home => { + if action_mod { + if mods.shift { + editor.driver().select_to_text_start(); + } else { + editor.driver().move_to_text_start(); + } + } else if mods.shift { + editor.driver().select_to_line_start(); + } else { + editor.driver().move_to_line_start(); + } + } + KeyCode::End => { + if action_mod { + if mods.shift { + editor.driver().select_to_text_end(); + } else { + editor.driver().move_to_text_end(); + } + } else if mods.shift { + editor.driver().select_to_line_end(); + } else { + editor.driver().move_to_line_end(); + } + } + _ => return false, + } - let mut editor = self.lock_editor().await; - - match key { - KeyCode::Left => { - if action_mod { - if mods.shift { - editor.driver().select_word_left(); - } else { - editor.driver().move_word_left(); - } - } else if mods.shift { - editor.driver().select_left(); - } else { - editor.driver().move_left(); - } + if let Some(seltext) = editor.selected_text() { + self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap(); + } else { + self.select_text.clone().set_null(atom, Role::Internal, 0).unwrap(); } - KeyCode::Right => { - if action_mod { - if mods.shift { - editor.driver().select_word_right(); - } else { - editor.driver().move_word_right(); - } - } else if mods.shift { - editor.driver().select_right(); - } else { - editor.driver().move_right(); - } - } - KeyCode::Up => { - if mods.shift { - editor.driver().select_up(); - } else { - editor.driver().move_up(); - } - } - KeyCode::Down => { - if mods.shift { - editor.driver().select_down(); - } else { - editor.driver().move_down(); - } - } - KeyCode::Enter | KeyCode::KpEnter => { - if mods.shift { - if self.behave.allow_endl() { - editor.driver().insert_or_replace_selection("\n"); - editor.on_buffer_changed(atom).await; - } - } else { - //let node = self.node.upgrade().unwrap(); - //node.trigger("enter_pressed", vec![]).await.unwrap(); - return false; - } - } - KeyCode::Delete => { - if action_mod { - editor.driver().delete_word(); - } else { - editor.driver().delete(); - } - editor.on_buffer_changed(atom).await; - } - KeyCode::Backspace => { - if action_mod { - editor.driver().backdelete_word(); - } else { - editor.driver().backdelete(); - } - editor.on_buffer_changed(atom).await; - } - KeyCode::Home => { - if action_mod { - if mods.shift { - editor.driver().select_to_text_start(); - } else { - editor.driver().move_to_text_start(); - } - } else if mods.shift { - editor.driver().select_to_line_start(); - } else { - editor.driver().move_to_line_start(); - } - } - KeyCode::End => { - if action_mod { - if mods.shift { - editor.driver().select_to_text_end(); - } else { - editor.driver().move_to_text_end(); - } - } else if mods.shift { - editor.driver().select_to_line_end(); - } else { - editor.driver().move_to_line_end(); - } - } - _ => return false, } - if let Some(seltext) = editor.selected_text() { - self.select_text.clone().set_str(atom, Role::Internal, 0, seltext).unwrap(); - } else { - self.select_text.clone().set_null(atom, Role::Internal, 0).unwrap(); - } - - drop(editor); - self.eval_rect().await; self.behave.apply_cursor_scroll().await; self.pause_blinking(); self.redraw(atom).await; - return true + true } /// This will select the entire word rather than move the cursor to that location async fn start_touch_select(&self, touch_pos: Point, atom: &mut PropertyAtomicGuard) { t!("start_touch_select({touch_pos:?})"); - let mut editor = self.lock_editor().await; - editor.select_word_at_point(touch_pos).await; - editor.refresh().await; + let mut editor = self.editor.lock(); + editor.select_word_at_point(touch_pos); + editor.refresh(); let seltext = editor.selected_text().unwrap(); d!("Selected {seltext:?} from {touch_pos:?}"); @@ -717,7 +699,7 @@ impl BaseEdit { true } - async fn get_select_handles(&self, editor: &Editor) -> Option<(Point, Point)> { + fn get_select_handles(&self, editor: &Editor) -> Option<(Point, Point)> { let layout = editor.layout(); let sel = editor.selection(1); @@ -732,10 +714,8 @@ impl BaseEdit { } async fn try_handle_drag(&self, mut touch_pos: Point) -> bool { - let editor = self.lock_editor().await; - let Some((mut first, mut last)) = self.get_select_handles(&editor).await else { - return false - }; + let editor = self.editor.lock(); + let Some((mut first, mut last)) = self.get_select_handles(&editor) else { return false }; self.abs_to_local(&mut touch_pos); t!("localize touch_pos = {touch_pos:?}"); @@ -878,9 +858,9 @@ impl BaseEdit { async fn touch_set_cursor_pos(&self, atom: &mut PropertyAtomicGuard, touch_pos: Point) { t!("touch_set_cursor_pos({touch_pos:?})"); - let mut editor = self.lock_editor().await; + let mut editor = self.editor.lock(); editor.move_to_pos(touch_pos); - editor.refresh().await; + editor.refresh(); drop(editor); self.pause_blinking(); @@ -926,7 +906,7 @@ impl BaseEdit { } let seltext = { - let mut editor = self.lock_editor().await; + let mut editor = self.editor.lock(); // The below lines rely on parley driver which android does not use //let mut txt_ctx = text::TEXT_CTX.get().await; @@ -970,8 +950,8 @@ impl BaseEdit { assert!(start < end); //t!("handle_select(): set_selection({start}, {end})"); - editor.set_selection(start, end).await; - editor.refresh().await; + editor.set_selection(start, end); + editor.refresh(); editor.selected_text() }; @@ -1096,7 +1076,7 @@ impl BaseEdit { async fn regen_txt_mesh(&self) -> Vec { let mut instrs = vec![DrawInstruction::Move(self.behave.inner_pos())]; - let editor = self.lock_editor().await; + let editor = self.editor.lock(); let layout = editor.layout(); let mut render_instrs = @@ -1109,7 +1089,7 @@ impl BaseEdit { async fn regen_select_mesh(&self) -> Vec { let mut instrs = vec![DrawInstruction::Move(self.behave.inner_pos())]; - let editor = self.lock_editor().await; + let editor = self.editor.lock(); let layout = editor.layout(); let sel = editor.selection(1); @@ -1131,8 +1111,8 @@ impl BaseEdit { //t!("regen_phone_select_handle_mesh() [DISABLED]"); return vec![] } - let editor = self.lock_editor().await; - let (first, last) = self.get_select_handles(&editor).await.unwrap(); + let editor = self.editor.lock(); + let (first, last) = self.get_select_handles(&editor).unwrap(); let sel = editor.selection(1); assert!(!sel.is_collapsed()); @@ -1214,11 +1194,6 @@ impl BaseEdit { } } - async fn insert(&self, txt: &str, atom: &mut PropertyAtomicGuard) { - let mut editor = self.lock_editor().await; - editor.insert(txt, atom).await; - } - async fn process_insert_text_method(me: &Weak, sub: &MethodCallSub) -> bool { let Ok(method_call) = sub.receive().await else { debug!(target: "ui::chatedit", "Event relayer closed"); @@ -1246,7 +1221,7 @@ impl BaseEdit { let atom = &mut self_.render_api.make_guard(gfxtag!("BaseEdit::process_insert_text_method")); - self_.insert(&text, atom).await; + self_.editor.lock().insert(&text, atom); self_.eval_rect().await; self_.redraw(atom).await; true @@ -1267,8 +1242,7 @@ impl BaseEdit { panic!("self destroyed before insert_text_method_task was stopped!"); }; - let mut editor = self_.lock_editor().await; - editor.focus(); + self_.editor.lock().focus(); true } async fn process_unfocus_method(me: &Weak, sub: &MethodCallSub) -> bool { @@ -1286,8 +1260,7 @@ impl BaseEdit { panic!("self destroyed before insert_text_method_task was stopped!"); }; - let mut editor = self_.lock_editor().await; - editor.unfocus(); + self_.editor.lock().unfocus(); true } @@ -1300,7 +1273,7 @@ impl BaseEdit { t!("handle_android_event({state:?})"); let atom = &mut self.render_api.make_guard(gfxtag!("BaseEdit::handle_android_event")); - let mut editor = self.lock_editor().await; + let mut editor = self.editor.lock(); // Diff old and new state so we know what changed let is_text_changed = editor.state.text != state.text; let is_select_changed = editor.state.select != state.select; @@ -1357,22 +1330,7 @@ impl UIObject for BaseEdit { self.priority.get() } - fn init(&self) { - let mut guard = self.editor.lock_blocking(); - assert!(guard.is_none()); - let editor = Editor::new( - self.text.clone(), - self.font_size.clone(), - self.text_color.clone(), - self.window_scale.clone(), - self.lineheight.clone(), - ); - // For Android you can do this: - //let atom = &mut PropertyAtomicGuard::none(); - //self.text.set(atom, "the quick brown fox jumped over the"); - //smol::block_on(editor.on_text_prop_changed()); - *guard = Some(editor); - } + fn init(&self) {} async fn start(self: Arc, ex: ExecutorPtr) { let me = Arc::downgrade(&self); @@ -1414,7 +1372,7 @@ impl UIObject for BaseEdit { self_.redraw(atom).await; } async fn set_text(self_: Arc, batch: BatchGuardPtr) { - self_.lock_editor().await.on_text_prop_changed().await; + self_.editor.lock().on_text_prop_changed(); let atom = &mut batch.spawn(); self_.eval_rect().await; self_.redraw(atom).await; @@ -1549,7 +1507,6 @@ impl UIObject for BaseEdit { *self.parent_rect.lock() = None; self.key_repeat.lock().clear(); *self.cursor_mesh.lock() = None; - *self.editor.lock_blocking() = None; } #[instrument(target = "ui::edit")] @@ -1598,7 +1555,7 @@ impl UIObject for BaseEdit { t!("Key {:?} has {} actions", key, actions); let key_str = key.to_string().repeat(actions as usize); - self.insert(&key_str, atom).await; + self.editor.lock().insert(&key_str, atom); self.eval_rect().await; self.behave.apply_cursor_scroll().await; self.redraw(atom).await; @@ -1672,10 +1629,7 @@ impl UIObject for BaseEdit { // Move mouse pos within this widget self.abs_to_local(&mut mouse_pos); - { - let mut editor = self.lock_editor().await; - editor.driver().move_to_point(mouse_pos.x, mouse_pos.y); - } + self.editor.lock().driver().move_to_point(mouse_pos.x, mouse_pos.y); if !self.select_text.is_null(0).unwrap() { self.select_text.clone().set_null(atom, Role::Internal, 0).unwrap();