Desktop: Fix frontend message response dispatch (#3247)

* One annoying debugging session later

Discovered that the editor handles frontend messages differently from other messages.
It requires all frontend messages to be fully processed before dispatching any resulting messages.

In the web frontend, this behavior happened implicitly because message dispatch is queued at the current end of the JavaScript execution queue.
For the desktop frontend, I added a vector to collect all responses until the entire batch of frontend messages is handled, and then dispatch them afterwards.

* Fix double click travel
This commit is contained in:
Timon 2025-10-06 22:04:24 +02:00 committed by GitHub
parent bfba632100
commit 48ac24da14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 24 additions and 15 deletions

View File

@ -82,7 +82,7 @@ impl App {
}
}
fn handle_desktop_frontend_message(&mut self, message: DesktopFrontendMessage) {
fn handle_desktop_frontend_message(&mut self, message: DesktopFrontendMessage, responses: &mut Vec<DesktopWrapperMessage>) {
match message {
DesktopFrontendMessage::ToWeb(messages) => {
let Some(bytes) = serialize_frontend_messages(messages) else {
@ -205,7 +205,7 @@ impl App {
to_front: false,
select_after_open: true,
};
self.dispatch_desktop_wrapper_message(message);
responses.push(message);
}
}
DesktopFrontendMessage::PersistenceLoadRemainingDocuments => {
@ -216,7 +216,7 @@ impl App {
to_front: true,
select_after_open: false,
};
self.dispatch_desktop_wrapper_message(message);
responses.push(message);
}
for (id, document) in self.persistent_data.documents_after_current() {
let message = DesktopWrapperMessage::LoadDocument {
@ -225,11 +225,11 @@ impl App {
to_front: false,
select_after_open: false,
};
self.dispatch_desktop_wrapper_message(message);
responses.push(message);
}
if let Some(id) = self.persistent_data.current_document_id() {
let message = DesktopWrapperMessage::SelectDocument { id };
self.dispatch_desktop_wrapper_message(message);
responses.push(message);
}
}
DesktopFrontendMessage::PersistenceWritePreferences { preferences } => {
@ -238,14 +238,18 @@ impl App {
DesktopFrontendMessage::PersistenceLoadPreferences => {
let preferences = self.persistent_data.load_preferences();
let message = DesktopWrapperMessage::LoadPreferences { preferences };
self.dispatch_desktop_wrapper_message(message);
responses.push(message);
}
}
}
fn handle_desktop_frontend_messages(&mut self, messages: Vec<DesktopFrontendMessage>) {
let mut responses = Vec::new();
for message in messages {
self.handle_desktop_frontend_message(message);
self.handle_desktop_frontend_message(message, &mut responses);
}
for message in responses {
self.dispatch_desktop_wrapper_message(message);
}
}

View File

@ -246,7 +246,8 @@ impl ClickTracker {
return ClickCount::Single;
};
let previous = record.time;
let prev_time = record.time;
let prev_position = record.position;
let now = Instant::now();
record.time = now;
@ -270,10 +271,10 @@ impl ClickTracker {
_ => {}
}
let dx = position.x.abs_diff(record.position.x);
let dy = position.y.abs_diff(record.position.y);
let dx = position.x.abs_diff(prev_position.x);
let dy = position.y.abs_diff(prev_position.y);
let within_dist = dx <= MULTICLICK_ALLOWED_TRAVEL && dy <= MULTICLICK_ALLOWED_TRAVEL;
let within_time = now.saturating_duration_since(previous) <= MULTICLICK_TIMEOUT;
let within_time = now.saturating_duration_since(prev_time) <= MULTICLICK_TIMEOUT;
let count = if within_time && within_dist { ClickCount::Double } else { ClickCount::Single };

View File

@ -71,6 +71,8 @@ impl<'a> DesktopWrapperMessageDispatcher<'a> {
frontend_messages.extend(current_frontend_messages);
}
self.respond(DesktopFrontendMessage::ToWeb(frontend_messages));
if !frontend_messages.is_empty() {
self.respond(DesktopFrontendMessage::ToWeb(frontend_messages));
}
}
}

View File

@ -136,10 +136,12 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
// Messages
PortfolioMessage::Init => {
// Load persistent data from the browser database
responses.add(FrontendMessage::TriggerLoadFirstAutoSaveDocument);
// Tell frontend to load persistent preferences
responses.add(FrontendMessage::TriggerLoadPreferences);
// Tell frontend to load the current document
responses.add(FrontendMessage::TriggerLoadFirstAutoSaveDocument);
// Display the menu bar at the top of the window
responses.add(MenuBarMessage::SendLayout);
@ -149,7 +151,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
node_types: document_node_definitions::collect_node_types(),
});
// Finish loading persistent data from the browser database
// Tell frontend to finish loading persistent documents
responses.add(FrontendMessage::TriggerLoadRestAutoSaveDocuments);
}
PortfolioMessage::DocumentPassMessage { document_id, message } => {