gpui: Flash menu in menubar on macOS when action is triggered (#38588)
On macOS, traditionally when a keyboard shortcut is activated, the menu in the menu bar flashes to indicate that the action was recognised. <img width="289" height="172" alt="image" src="https://github.com/user-attachments/assets/a03ecd2f-f159-4f82-b4fd-227f34393703" /> This PR adds this functionality to GPUI, where when a keybind is pressed that triggers an action in the menu, the menu flashes. Release Notes: - N/A
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
use gpui::{
|
||||
App, Application, Context, Menu, MenuItem, SystemMenuType, Window, WindowOptions, actions, div,
|
||||
prelude::*, rgb,
|
||||
App, Application, Context, FocusHandle, KeyBinding, Menu, MenuItem, PromptLevel,
|
||||
SystemMenuType, Window, WindowOptions, actions, div, prelude::*, rgb,
|
||||
};
|
||||
|
||||
struct SetMenus;
|
||||
struct SetMenus {
|
||||
focus_handle: FocusHandle,
|
||||
}
|
||||
|
||||
impl Render for SetMenus {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.key_context("root")
|
||||
.track_focus(&self.focus_handle)
|
||||
.flex()
|
||||
.bg(rgb(0x2e7d32))
|
||||
.size_full()
|
||||
@@ -15,6 +19,16 @@ impl Render for SetMenus {
|
||||
.items_center()
|
||||
.text_xl()
|
||||
.text_color(rgb(0xffffff))
|
||||
// Actions can also be registered within elements so they are only active when relevant
|
||||
.on_action(|_: &Open, window, cx| {
|
||||
let _ = window.prompt(PromptLevel::Info, "Open action fired", None, &["OK"], cx);
|
||||
})
|
||||
.on_action(|_: &Copy, window, cx| {
|
||||
let _ = window.prompt(PromptLevel::Info, "Copy action fired", None, &["OK"], cx);
|
||||
})
|
||||
.on_action(|_: &Paste, window, cx| {
|
||||
let _ = window.prompt(PromptLevel::Info, "Paste action fired", None, &["OK"], cx);
|
||||
})
|
||||
.child("Set Menus Example")
|
||||
}
|
||||
}
|
||||
@@ -23,24 +37,47 @@ fn main() {
|
||||
Application::new().run(|cx: &mut App| {
|
||||
// Bring the menu bar to the foreground (so you can see the menu bar)
|
||||
cx.activate(true);
|
||||
// Bind keys to some menu actions
|
||||
cx.bind_keys([
|
||||
KeyBinding::new("secondary-o", Open, None),
|
||||
KeyBinding::new("secondary-c", Copy, None),
|
||||
KeyBinding::new("secondary-v", Paste, None),
|
||||
]);
|
||||
// Register the `quit` function so it can be referenced by the `MenuItem::action` in the menu bar
|
||||
cx.on_action(quit);
|
||||
// Add menu items
|
||||
cx.set_menus(vec![Menu {
|
||||
name: "set_menus".into(),
|
||||
items: vec![
|
||||
MenuItem::os_submenu("Services", SystemMenuType::Services),
|
||||
MenuItem::separator(),
|
||||
MenuItem::action("Quit", Quit),
|
||||
],
|
||||
}]);
|
||||
cx.open_window(WindowOptions::default(), |_, cx| cx.new(|_| SetMenus {}))
|
||||
.unwrap();
|
||||
cx.set_menus(vec![
|
||||
Menu {
|
||||
name: "set_menus".into(),
|
||||
items: vec![
|
||||
MenuItem::os_submenu("Services", SystemMenuType::Services),
|
||||
MenuItem::separator(),
|
||||
MenuItem::action("Quit", Quit),
|
||||
],
|
||||
},
|
||||
Menu {
|
||||
name: "File".into(),
|
||||
items: vec![MenuItem::action("Open", Open)],
|
||||
},
|
||||
Menu {
|
||||
name: "Edit".into(),
|
||||
items: vec![
|
||||
MenuItem::action("Copy", Copy),
|
||||
MenuItem::action("Paste", Paste),
|
||||
],
|
||||
},
|
||||
]);
|
||||
cx.open_window(WindowOptions::default(), |_, cx| {
|
||||
cx.new(|cx| SetMenus {
|
||||
focus_handle: cx.focus_handle(),
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
// Associate actions using the `actions!` macro (or `Action` derive macro)
|
||||
actions!(set_menus, [Quit]);
|
||||
actions!(set_menus, [Quit, Open, Copy, Paste]);
|
||||
|
||||
// Define the quit function that is registered with the App
|
||||
fn quit(_: &Quit, cx: &mut App) {
|
||||
|
||||
Reference in New Issue
Block a user