@@ -114,23 +114,37 @@ pub fn button_from_mouse_event(event: &web_sys::MouseEvent) -> Option<egui::Poin
114114 }
115115}
116116
117- pub fn pos_from_touch_event ( canvas_id : & str , event : & web_sys:: TouchEvent ) -> egui:: Pos2 {
118- // TO BE CLARIFIED: For some types of touch events (e.g. `touchcancel`) it may be necessary to
119- // change the return type to an `Option<Pos2>` – but this would be an incompatible change. Can
120- // we do this?
121-
122- // Calculate the average of all touch positions:
123- let mut accu = egui:: Vec2 :: ZERO ;
124- let touch_count = event. touches ( ) . length ( ) ;
125- if touch_count > 0 {
126- let canvas_origin = canvas_origin ( canvas_id) ;
127- for touch_idx in 0 ..touch_count {
128- let touch = event. touches ( ) . get ( touch_idx) . unwrap ( ) ;
129- accu += pos_from_touch ( canvas_origin, & touch) . to_vec2 ( ) ;
130- }
131- accu = accu / touch_count as f32 ;
117+ /// A single touch is translated to a pointer movement. When a second touch is added, the pointer
118+ /// should not jump to a different position. Therefore, we do not calculate the average position
119+ /// of all touches, but we keep using the same touch as long as it is available.
120+ ///
121+ /// `touch_id_for_pos` is the `TouchId` of the `Touch` we previously used to determine the
122+ /// pointer position.
123+ pub fn pos_from_touch_event (
124+ canvas_id : & str ,
125+ event : & web_sys:: TouchEvent ,
126+ touch_id_for_pos : & mut Option < egui:: TouchId > ,
127+ ) -> egui:: Pos2 {
128+ let touch_for_pos;
129+ if let Some ( touch_id_for_pos) = touch_id_for_pos {
130+ // search for the touch we previously used for the position
131+ // (unfortunately, `event.touches()` is not a rust collection):
132+ touch_for_pos = ( 0 ..event. touches ( ) . length ( ) )
133+ . into_iter ( )
134+ . map ( |i| event. touches ( ) . get ( i) . unwrap ( ) )
135+ . find ( |touch| egui:: TouchId :: from ( touch. identifier ( ) ) == * touch_id_for_pos) ;
136+ } else {
137+ touch_for_pos = None ;
132138 }
133- egui:: Pos2 :: ZERO + accu
139+ // Use the touch found above or pick the first, or return a default position if there is no
140+ // touch at all. (The latter is not expected as the current method is only called when there is
141+ // at least one touch.)
142+ touch_for_pos
143+ . or_else ( || event. touches ( ) . get ( 0 ) )
144+ . map_or ( Default :: default ( ) , |touch| {
145+ * touch_id_for_pos = Some ( egui:: TouchId :: from ( touch. identifier ( ) ) ) ;
146+ pos_from_touch ( canvas_origin ( canvas_id) , & touch)
147+ } )
134148}
135149
136150fn pos_from_touch ( canvas_origin : egui:: Pos2 , touch : & web_sys:: Touch ) -> egui:: Pos2 {
@@ -153,7 +167,7 @@ fn push_touches(runner: &mut AppRunner, phase: egui::TouchPhase, event: &web_sys
153167 if let Some ( touch) = event. changed_touches ( ) . item ( touch_idx) {
154168 runner. input . raw . events . push ( egui:: Event :: Touch {
155169 device_id : egui:: TouchDeviceId ( 0 ) ,
156- id : egui:: TouchId ( touch. identifier ( ) as u64 ) ,
170+ id : egui:: TouchId :: from ( touch. identifier ( ) ) ,
157171 phase,
158172 pos : pos_from_touch ( canvas_origin, & touch) ,
159173 force : touch. force ( ) ,
@@ -914,7 +928,10 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
914928 let runner_ref = runner_ref. clone ( ) ;
915929 let closure = Closure :: wrap ( Box :: new ( move |event : web_sys:: TouchEvent | {
916930 let mut runner_lock = runner_ref. 0 . lock ( ) ;
917- let pos = pos_from_touch_event ( runner_lock. canvas_id ( ) , & event) ;
931+ let mut latest_touch_pos_id = runner_lock. input . latest_touch_pos_id ;
932+ let pos =
933+ pos_from_touch_event ( runner_lock. canvas_id ( ) , & event, & mut latest_touch_pos_id) ;
934+ runner_lock. input . latest_touch_pos_id = latest_touch_pos_id;
918935 runner_lock. input . latest_touch_pos = Some ( pos) ;
919936 runner_lock. input . is_touch = true ;
920937 let modifiers = runner_lock. input . raw . modifiers ;
@@ -943,7 +960,10 @@ fn install_canvas_events(runner_ref: &AppRunnerRef) -> Result<(), JsValue> {
943960 let runner_ref = runner_ref. clone ( ) ;
944961 let closure = Closure :: wrap ( Box :: new ( move |event : web_sys:: TouchEvent | {
945962 let mut runner_lock = runner_ref. 0 . lock ( ) ;
946- let pos = pos_from_touch_event ( runner_lock. canvas_id ( ) , & event) ;
963+ let mut latest_touch_pos_id = runner_lock. input . latest_touch_pos_id ;
964+ let pos =
965+ pos_from_touch_event ( runner_lock. canvas_id ( ) , & event, & mut latest_touch_pos_id) ;
966+ runner_lock. input . latest_touch_pos_id = latest_touch_pos_id;
947967 runner_lock. input . latest_touch_pos = Some ( pos) ;
948968 runner_lock. input . is_touch = true ;
949969 runner_lock
0 commit comments