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:
Bi Fuguo 2025-03-03 23:30:57 +08:00 committed by GitHub
parent 5650fa2e79
commit a22f95a6a7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 49 additions and 51 deletions

View file

@ -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);
},
}
},

View file

@ -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;
}
}
}