mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Fix the problem that touchmove crashes occasionally. Fix crash when multiple touch cancels occur (#35763)
* Fix the problem that touchmove crashes occasionally. Check whether touchSequenceInfo exists when touch_sequence_map is modified in on_touch_event_processed. Signed-off-by: kongbai1996 <1782765876@qq.com> * Remove outdated todo. We already transition to Finished in `on_touch_cancel` in the Touch handler, so we don't need any logic in the event handler. Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com> --------- Signed-off-by: kongbai1996 <1782765876@qq.com> Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com> Co-authored-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
parent
5650fa2e79
commit
a22f95a6a7
2 changed files with 49 additions and 51 deletions
|
@ -1474,23 +1474,25 @@ impl IOCompositor {
|
|||
},
|
||||
TouchEventType::Move => {
|
||||
// script thread processed the touch move event, mark this false.
|
||||
let info = self.touch_handler.get_touch_sequence_mut(sequence_id);
|
||||
if let Some(info) = self.touch_handler.get_touch_sequence_mut(sequence_id) {
|
||||
info.prevent_move = TouchMoveAllowed::Prevented;
|
||||
if let TouchSequenceState::PendingFling { .. } = info.state {
|
||||
info.state = TouchSequenceState::Finished;
|
||||
}
|
||||
self.touch_handler.prevent_move(sequence_id);
|
||||
self.touch_handler
|
||||
.set_handling_touch_move(self.touch_handler.current_sequence_id, false);
|
||||
self.touch_handler.set_handling_touch_move(
|
||||
self.touch_handler.current_sequence_id,
|
||||
false,
|
||||
);
|
||||
self.touch_handler
|
||||
.remove_pending_touch_move_action(sequence_id);
|
||||
}
|
||||
},
|
||||
TouchEventType::Up => {
|
||||
// Note: We don't have to consider PendingFling here, since we handle that
|
||||
// in the DefaultAllowed case of the touch_move event.
|
||||
// Note: Removing can and should fail, if we still have an active Fling,
|
||||
let Some(info) =
|
||||
&mut self.touch_handler.touch_sequence_map.get_mut(&sequence_id)
|
||||
&mut self.touch_handler.get_touch_sequence_mut(sequence_id)
|
||||
else {
|
||||
// The sequence ID could already be removed, e.g. if Fling finished,
|
||||
// before the touch_up event was handled (since fling can start
|
||||
|
@ -1526,10 +1528,6 @@ impl IOCompositor {
|
|||
// actions, and try to remove the touch sequence.
|
||||
self.touch_handler
|
||||
.remove_pending_touch_move_action(sequence_id);
|
||||
// Todo: Perhaps we need to check how many fingers are still active.
|
||||
self.touch_handler.get_touch_sequence_mut(sequence_id).state =
|
||||
TouchSequenceState::Finished;
|
||||
// Cancel should be the last event for a given sequence_id.
|
||||
self.touch_handler.try_remove_touch_sequence(sequence_id);
|
||||
},
|
||||
}
|
||||
|
@ -1581,15 +1579,17 @@ impl IOCompositor {
|
|||
}
|
||||
self.touch_handler
|
||||
.set_handling_touch_move(self.touch_handler.current_sequence_id, false);
|
||||
let info = self.touch_handler.get_touch_sequence_mut(sequence_id);
|
||||
if let Some(info) = self.touch_handler.get_touch_sequence_mut(sequence_id) {
|
||||
info.prevent_move = TouchMoveAllowed::Allowed;
|
||||
if let TouchSequenceState::PendingFling { velocity, cursor } = info.state {
|
||||
if let TouchSequenceState::PendingFling { velocity, cursor } =
|
||||
info.state
|
||||
{
|
||||
info.state = TouchSequenceState::Flinging { velocity, cursor }
|
||||
}
|
||||
}
|
||||
},
|
||||
TouchEventType::Up => {
|
||||
let Some(info) =
|
||||
self.touch_handler.touch_sequence_map.get_mut(&sequence_id)
|
||||
let Some(info) = self.touch_handler.get_touch_sequence_mut(sequence_id)
|
||||
else {
|
||||
// The sequence was already removed because there is no default action.
|
||||
return;
|
||||
|
@ -1626,7 +1626,7 @@ impl IOCompositor {
|
|||
TouchEventType::Cancel => {
|
||||
self.touch_handler
|
||||
.remove_pending_touch_move_action(sequence_id);
|
||||
self.touch_handler.remove_touch_sequence(sequence_id);
|
||||
self.touch_handler.try_remove_touch_sequence(sequence_id);
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@ const FLING_MAX_SCREEN_PX: f32 = 4000.0;
|
|||
pub struct TouchHandler {
|
||||
pub current_sequence_id: TouchSequenceId,
|
||||
// todo: VecDeque + modulo arithmetic would be more efficient.
|
||||
pub touch_sequence_map: HashMap<TouchSequenceId, TouchSequenceInfo>,
|
||||
touch_sequence_map: HashMap<TouchSequenceId, TouchSequenceInfo>,
|
||||
}
|
||||
|
||||
/// Whether the default move action is allowed or not.
|
||||
|
@ -213,41 +213,39 @@ impl TouchHandler {
|
|||
}
|
||||
|
||||
pub(crate) fn set_handling_touch_move(&mut self, sequence_id: TouchSequenceId, flag: bool) {
|
||||
self.touch_sequence_map
|
||||
.get_mut(&sequence_id)
|
||||
.unwrap()
|
||||
.handling_touch_move = flag;
|
||||
if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
|
||||
sequence.handling_touch_move = flag;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_handling_touch_move(&self, sequence_id: TouchSequenceId) -> bool {
|
||||
self.touch_sequence_map
|
||||
.get(&sequence_id)
|
||||
.unwrap()
|
||||
.handling_touch_move
|
||||
if let Some(sequence) = self.touch_sequence_map.get(&sequence_id) {
|
||||
sequence.handling_touch_move
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn prevent_click(&mut self, sequence_id: TouchSequenceId) {
|
||||
self.touch_sequence_map
|
||||
.get_mut(&sequence_id)
|
||||
.unwrap()
|
||||
.prevent_click = true;
|
||||
if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
|
||||
sequence.prevent_click = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn prevent_move(&mut self, sequence_id: TouchSequenceId) {
|
||||
self.touch_sequence_map
|
||||
.get_mut(&sequence_id)
|
||||
.unwrap()
|
||||
.prevent_move = TouchMoveAllowed::Prevented;
|
||||
if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
|
||||
sequence.prevent_move = TouchMoveAllowed::Prevented;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if default move actions are allowed, false if prevented or the result
|
||||
/// is still pending.,
|
||||
pub(crate) fn move_allowed(&mut self, sequence_id: TouchSequenceId) -> bool {
|
||||
self.touch_sequence_map
|
||||
.get(&sequence_id)
|
||||
.unwrap()
|
||||
.prevent_move ==
|
||||
TouchMoveAllowed::Allowed
|
||||
if let Some(sequence) = self.touch_sequence_map.get_mut(&sequence_id) {
|
||||
sequence.prevent_move == TouchMoveAllowed::Allowed
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn pending_touch_move_action(
|
||||
|
@ -294,10 +292,8 @@ impl TouchHandler {
|
|||
pub(crate) fn get_touch_sequence_mut(
|
||||
&mut self,
|
||||
sequence_id: TouchSequenceId,
|
||||
) -> &mut TouchSequenceInfo {
|
||||
self.touch_sequence_map
|
||||
.get_mut(&sequence_id)
|
||||
.expect("Touch sequence not found.")
|
||||
) -> Option<&mut TouchSequenceInfo> {
|
||||
self.touch_sequence_map.get_mut(&sequence_id)
|
||||
}
|
||||
|
||||
pub fn on_touch_down(&mut self, id: TouchId, point: Point2D<f32, DevicePixel>) {
|
||||
|
@ -377,7 +373,7 @@ impl TouchHandler {
|
|||
id: TouchId,
|
||||
point: Point2D<f32, DevicePixel>,
|
||||
) -> TouchMoveAction {
|
||||
let touch_sequence = self.get_touch_sequence_mut(self.current_sequence_id);
|
||||
let touch_sequence = self.get_current_touch_sequence_mut();
|
||||
let idx = match touch_sequence
|
||||
.active_touch_points
|
||||
.iter_mut()
|
||||
|
@ -454,7 +450,7 @@ impl TouchHandler {
|
|||
}
|
||||
|
||||
pub fn on_touch_up(&mut self, id: TouchId, point: Point2D<f32, DevicePixel>) {
|
||||
let touch_sequence = self.get_touch_sequence_mut(self.current_sequence_id);
|
||||
let touch_sequence = self.get_current_touch_sequence_mut();
|
||||
let old = match touch_sequence
|
||||
.active_touch_points
|
||||
.iter()
|
||||
|
@ -531,7 +527,7 @@ impl TouchHandler {
|
|||
}
|
||||
|
||||
pub fn on_touch_cancel(&mut self, id: TouchId, _point: Point2D<f32, DevicePixel>) {
|
||||
let touch_sequence = self.get_touch_sequence_mut(self.current_sequence_id);
|
||||
let touch_sequence = self.get_current_touch_sequence_mut();
|
||||
match touch_sequence
|
||||
.active_touch_points
|
||||
.iter()
|
||||
|
@ -545,6 +541,8 @@ impl TouchHandler {
|
|||
return;
|
||||
},
|
||||
}
|
||||
if touch_sequence.active_touch_points.is_empty() {
|
||||
touch_sequence.state = Finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue