mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-28 04:06:54 -06:00
fix(macos): a menu-bar command runs at once instead of on the next input (#784)
This commit is contained in:
@@ -129,6 +129,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m
|
||||
|
||||
Newest first.
|
||||
|
||||
- **2026-10-13** · macOS: a command chosen with the mouse in the menu bar runs at once. It used to wait for the next mouse move or key press over the window, so File › Open, Place and Save As seemed to take 10–20 seconds to open their dialogs. No readiness percentage change.
|
||||
- **2026-10-12** · macOS Dock Quit uses the same unsaved-document prompts as window and menu Quit. Repeated requests keep the current answers; Cancel retains every tab and unsaved recovery checkpoint, and completed Save/Don't Save answers exit through the ordinary event loop. No readiness percentage change.
|
||||
- **2026-10-12** · Orderly native exit writes the latest recovery state after finalizing current quit approvals; incomplete or stale plans keep their documents, and Undo to the saved state clears stale recovery. Unavailable or failed recovery is reported. Cancelable macOS Dock Quit remains open (#544). No readiness percentage change.
|
||||
- **2026-10-12** · Recovered documents keep a checkpoint until saved, closed or reverted, including a second crash before autosave. Restarted document IDs and explicit recovery folders preserve other snapshots; failed republishing retains the original. No readiness percentage change.
|
||||
|
||||
@@ -45,7 +45,7 @@ impl eframe::App for App {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
if self.menu.is_none() && std::env::var_os("DESIGNCRAFT_NO_NATIVE_MENU").is_none() {
|
||||
self.menu = Some(native_menu::NativeMenu::install(&mut self.app));
|
||||
self.menu = Some(native_menu::NativeMenu::install(&mut self.app, ctx));
|
||||
}
|
||||
if let Some(m) = &mut self.menu {
|
||||
m.poll(&mut self.app, ctx);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::mpsc::{Receiver, channel};
|
||||
|
||||
use designcraft_ui_egui::DesignApp;
|
||||
use designcraft_ui_egui::menus::{self, Item};
|
||||
@@ -19,6 +20,7 @@ enum Handle {
|
||||
pub struct NativeMenu {
|
||||
_menu: Menu,
|
||||
items: HashMap<String, (String, Value, Handle)>,
|
||||
events: Receiver<MenuEvent>,
|
||||
last_refresh: f64,
|
||||
}
|
||||
|
||||
@@ -31,7 +33,15 @@ fn accel(sc: &str) -> Option<Accelerator> {
|
||||
}
|
||||
|
||||
impl NativeMenu {
|
||||
pub fn install(app: &mut DesignApp) -> Self {
|
||||
pub fn install(app: &mut DesignApp, ctx: &egui::Context) -> Self {
|
||||
// A click in the menu bar reaches the app with no input over the window, so nothing would
|
||||
// draw the frame that runs the command until the pointer or a key comes back: wake egui.
|
||||
let (tx, events) = channel();
|
||||
let repaint = ctx.clone();
|
||||
MenuEvent::set_event_handler(Some(move |e: MenuEvent| {
|
||||
let _ = tx.send(e);
|
||||
repaint.request_repaint();
|
||||
}));
|
||||
let menu = Menu::new();
|
||||
let mut items = HashMap::new();
|
||||
let mut counter = 0usize;
|
||||
@@ -72,11 +82,11 @@ impl NativeMenu {
|
||||
(p.is_null() && accel(sc).is_some()).then(|| id.clone())
|
||||
})
|
||||
.collect();
|
||||
Self { _menu: menu, items, last_refresh: 0.0 }
|
||||
Self { _menu: menu, items, events, last_refresh: 0.0 }
|
||||
}
|
||||
|
||||
pub fn poll(&mut self, app: &mut DesignApp, ctx: &egui::Context) {
|
||||
while let Ok(ev) = MenuEvent::receiver().try_recv() {
|
||||
while let Ok(ev) = self.events.try_recv() {
|
||||
if let Some((cmd, params, _)) = self.items.get(ev.id.as_ref()) {
|
||||
menus::activate_native(app, ctx, &cmd.clone(), ¶ms.clone());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user