Jelajahi Sumber

app: introduce a new handle_touch_sync() which is much lower latency for touch events

jkds 6 bulan lalu
induk
melakukan
d6b524ced5
5 mengubah file dengan 66 tambahan dan 9 penghapusan
  1. 25 0
      bin/app/src/gfx/mod.rs
  2. 12 9
      bin/app/src/ui/edit/mod.rs
  3. 14 0
      bin/app/src/ui/layer.rs
  4. 4 0
      bin/app/src/ui/mod.rs
  5. 11 0
      bin/app/src/ui/win.rs

+ 25 - 0
bin/app/src/gfx/mod.rs

@@ -49,6 +49,7 @@ use trax::get_trax;
 
 
 use crate::{
 use crate::{
     prop::{BatchGuardId, PropertyAtomicGuard},
     prop::{BatchGuardId, PropertyAtomicGuard},
+    scene::{Pimpl, SceneNodePtr},
     util::unixtime,
     util::unixtime,
     GOD,
     GOD,
 };
 };
@@ -1031,6 +1032,9 @@ struct Stage {
 
 
     pruner: PruneMethodHeap,
     pruner: PruneMethodHeap,
     screen_state: ScreenState,
     screen_state: ScreenState,
+
+    /// Cached window node, looked up lazily on first touch event
+    window_node: Option<SceneNodePtr>,
 }
 }
 
 
 impl Stage {
 impl Stage {
@@ -1082,6 +1086,8 @@ impl Stage {
 
 
             pruner: PruneMethodHeap::new(epoch),
             pruner: PruneMethodHeap::new(epoch),
             screen_state: ScreenState::On,
             screen_state: ScreenState::On,
+
+            window_node: None,
         };
         };
         self_.pruner.textures = &*self_.textures as *const _;
         self_.pruner.textures = &*self_.textures as *const _;
         self_.pruner.buffers = &*self_.buffers as *const _;
         self_.pruner.buffers = &*self_.buffers as *const _;
@@ -1889,6 +1895,25 @@ impl EventHandler for Stage {
     /// The id corresponds to multi-touch. Multiple touch events have different ids.
     /// The id corresponds to multi-touch. Multiple touch events have different ids.
     fn touch_event(&mut self, phase: TouchPhase, id: u64, x: f32, y: f32) {
     fn touch_event(&mut self, phase: TouchPhase, id: u64, x: f32, y: f32) {
         let pos = Point::from([x, y]);
         let pos = Point::from([x, y]);
+
+        // Lazy cache window on first touch event
+        if self.window_node.is_none() {
+            let god = GOD.get().unwrap();
+            self.window_node = god.app.sg_root.lookup_node("/window");
+        }
+
+        // Direct call to Window's handle_touch_event_sync
+        if let Some(window_node) = &self.window_node {
+            match window_node.pimpl() {
+                Pimpl::Window(win) => {
+                    if win.handle_touch_sync(phase, id, pos) {
+                        return
+                    }
+                }
+                _ => panic!(),
+            }
+        }
+
         self.event_pub.notify_touch(phase, id, pos);
         self.event_pub.notify_touch(phase, id, pos);
     }
     }
 
 

+ 12 - 9
bin/app/src/ui/edit/mod.rs

@@ -773,7 +773,7 @@ impl BaseEdit {
         false
         false
     }
     }
 
 
-    async fn handle_touch_move(&self, mut touch_pos: Point) -> bool {
+    fn handle_touch_move(&self, mut touch_pos: Point) -> bool {
         if !self.is_active.get() {
         if !self.is_active.get() {
             return false
             return false
         }
         }
@@ -847,10 +847,10 @@ impl BaseEdit {
                 // If so we gotta scroll it while selecting.
                 // If so we gotta scroll it while selecting.
                 if !is_touch_hover {
                 if !is_touch_hover {
                     // This process will begin selecting text and applying scroll too.
                     // This process will begin selecting text and applying scroll too.
-                    sel_sender.send(Some((touch_pos, Some(*side)))).await.unwrap();
+                    sel_sender.try_send(Some((touch_pos, Some(*side)))).unwrap();
                 } else {
                 } else {
                     // Stop any existing select/scroll process
                     // Stop any existing select/scroll process
-                    sel_sender.send(None).await.unwrap();
+                    sel_sender.try_send(None).unwrap();
                     // Mouse is inside so just select the text once and be done.
                     // Mouse is inside so just select the text once and be done.
                     self.handle_select(touch_pos, Some(*side));
                     self.handle_select(touch_pos, Some(*side));
                 }
                 }
@@ -876,7 +876,7 @@ impl BaseEdit {
         }
         }
         true
         true
     }
     }
-    async fn handle_touch_end(&self, mut touch_pos: Point) -> bool {
+    fn handle_touch_end(&self, mut touch_pos: Point) -> bool {
         //t!("handle_touch_end({touch_pos:?})");
         //t!("handle_touch_end({touch_pos:?})");
         self.abs_to_local(&mut touch_pos);
         self.abs_to_local(&mut touch_pos);
 
 
@@ -893,9 +893,12 @@ impl BaseEdit {
 
 
         // Stop any selection scrolling
         // Stop any selection scrolling
         let scroll_sender = self.sel_sender.lock().clone().unwrap();
         let scroll_sender = self.sel_sender.lock().clone().unwrap();
-        scroll_sender.send(None).await.unwrap();
+        scroll_sender.try_send(None).unwrap();
 
 
-        self.node().trigger("focus_request", vec![]).await.unwrap();
+        let node = self.node();
+        smol::block_on(async {
+            node.trigger("focus_request", vec![]).await.unwrap();
+        });
 
 
         true
         true
     }
     }
@@ -1820,7 +1823,7 @@ impl UIObject for BaseEdit {
         true
         true
     }
     }
 
 
-    async fn handle_touch(&self, phase: TouchPhase, id: u64, touch_pos: Point) -> bool {
+    fn handle_touch_sync(&self, phase: TouchPhase, id: u64, touch_pos: Point) -> bool {
         if !self.is_active.get() {
         if !self.is_active.get() {
             return false
             return false
         }
         }
@@ -1832,8 +1835,8 @@ impl UIObject for BaseEdit {
 
 
         match phase {
         match phase {
             TouchPhase::Started => self.handle_touch_start(touch_pos),
             TouchPhase::Started => self.handle_touch_start(touch_pos),
-            TouchPhase::Moved => self.handle_touch_move(touch_pos).await,
-            TouchPhase::Ended => self.handle_touch_end(touch_pos).await,
+            TouchPhase::Moved => self.handle_touch_move(touch_pos),
+            TouchPhase::Ended => self.handle_touch_end(touch_pos),
             TouchPhase::Cancelled => false,
             TouchPhase::Cancelled => false,
         }
         }
     }
     }

+ 14 - 0
bin/app/src/ui/layer.rs

@@ -307,6 +307,20 @@ impl UIObject for Layer {
         false
         false
     }
     }
 
 
+    fn handle_touch_sync(&self, phase: TouchPhase, id: u64, mut touch_pos: Point) -> bool {
+        if !self.is_visible.get() {
+            return false
+        }
+        touch_pos -= self.rect.get().pos();
+        for child in self.get_children() {
+            let obj = get_ui_object3(&child);
+            if obj.handle_touch_sync(phase, id, touch_pos) {
+                return true
+            }
+        }
+        false
+    }
+
     fn set_i18n(&self, i18n_fish: &I18nBabelFish) {
     fn set_i18n(&self, i18n_fish: &I18nBabelFish) {
         for child in self.get_children() {
         for child in self.get_children() {
             let obj = get_ui_object3(&child);
             let obj = get_ui_object3(&child);

+ 4 - 0
bin/app/src/ui/mod.rs

@@ -108,6 +108,10 @@ pub trait UIObject: Sync {
         false
         false
     }
     }
 
 
+    fn handle_touch_sync(&self, _phase: TouchPhase, _id: u64, _touch_pos: Point) -> bool {
+        false
+    }
+
     fn set_i18n(&self, _i18n_fish: &I18nBabelFish) {}
     fn set_i18n(&self, _i18n_fish: &I18nBabelFish) {}
 }
 }
 
 

+ 11 - 0
bin/app/src/ui/win.rs

@@ -467,6 +467,17 @@ impl Window {
         }
         }
     }
     }
 
 
+    pub fn handle_touch_sync(&self, phase: TouchPhase, id: u64, mut touch_pos: Point) -> bool {
+        self.local_scale(&mut touch_pos);
+        for child in self.get_children() {
+            let obj = get_ui_object3(&child);
+            if obj.handle_touch_sync(phase, id, touch_pos) {
+                return true
+            }
+        }
+        false
+    }
+
     #[instrument(target = "ui::win")]
     #[instrument(target = "ui::win")]
     pub async fn draw(&self, atom: &mut PropertyAtomicGuard) {
     pub async fn draw(&self, atom: &mut PropertyAtomicGuard) {
         let virt_size = self.screen_size.get() / self.scale.get();
         let virt_size = self.screen_size.get() / self.scale.get();