diff --git a/examples/custom_menu.rs b/examples/custom_menu.rs index 796b62114..9c4508d05 100644 --- a/examples/custom_menu.rs +++ b/examples/custom_menu.rs @@ -84,7 +84,7 @@ fn main() { window.set_menu(Some(vec![Menu::new( "File", vec![ - MenuItem::new("Add Todo").with_accelerators("+"), + MenuItem::new("Add Todo").with_accelerators("T"), MenuItem::Separator, MenuItem::CloseWindow, ], diff --git a/src/platform_impl/linux/event_loop.rs b/src/platform_impl/linux/event_loop.rs index 8f2c4a54a..c088951a0 100644 --- a/src/platform_impl/linux/event_loop.rs +++ b/src/platform_impl/linux/event_loop.rs @@ -29,6 +29,7 @@ use crate::{ }; use super::{ + menu, monitor::MonitorHandle, window::{WindowId, WindowRequest}, DeviceId, @@ -468,7 +469,6 @@ impl EventLoop { } WindowRequest::Redraw => window.queue_draw(), WindowRequest::Menu(m) => { - // TODO other MenuItem variant match m { MenuItem::Custom(c) => { if let Err(e) = event_tx.send(Event::MenuEvent { @@ -552,6 +552,19 @@ impl EventLoop { _ => {} } } + WindowRequest::SetMenu((menus, accel_group, menu)) => { + for i in menu.get_children() { + menu.remove(&i); + } + + if let Some(menus) = menus { + let menubar = + menu::initialize(id, menus, &window_target.p.window_requests_tx, &accel_group); + dbg!("gell"); + menu.pack_start(&menubar, false, false, 0); + menu.show_all(); + } + } } } } diff --git a/src/platform_impl/linux/menu.rs b/src/platform_impl/linux/menu.rs index 61c157b44..cbf3066f6 100644 --- a/src/platform_impl/linux/menu.rs +++ b/src/platform_impl/linux/menu.rs @@ -1,9 +1,6 @@ use std::sync::mpsc::Sender; -use gtk::{ - prelude::*, AccelFlags, AccelGroup, ApplicationWindow, Menu, MenuBar, MenuItem, Orientation, - SeparatorMenuItem, -}; +use gtk::{prelude::*, AccelFlags, AccelGroup, Menu, MenuBar, MenuItem, SeparatorMenuItem}; use super::window::{WindowId, WindowRequest}; use crate::menu::{Menu as RootMenu, MenuItem as RootMenuItem}; @@ -12,22 +9,18 @@ macro_rules! menuitem { ( $description:expr, $key:expr, $accel_group:ident ) => {{ let item = MenuItem::with_label($description); let (key, mods) = gtk::accelerator_parse($key); - item.add_accelerator("activate", &$accel_group, key, mods, AccelFlags::VISIBLE); + item.add_accelerator("activate", $accel_group, key, mods, AccelFlags::VISIBLE); Some(item) }}; } pub fn initialize( - window: &ApplicationWindow, + id: WindowId, menus: Vec, - tx: Sender<(WindowId, WindowRequest)>, - accel_group: AccelGroup, -) { - let id = WindowId(window.get_id()); - let vbox = gtk::Box::new(Orientation::Vertical, 0); + tx: &Sender<(WindowId, WindowRequest)>, + accel_group: &AccelGroup, +) -> MenuBar { let menubar = MenuBar::new(); - window.add(&vbox); - for menu in menus { let title = MenuItem::with_label(&menu.title); let submenu = Menu::new(); @@ -72,5 +65,5 @@ pub fn initialize( menubar.append(&title); } - vbox.pack_start(&menubar, false, false, 0); + menubar } diff --git a/src/platform_impl/linux/window.rs b/src/platform_impl/linux/window.rs index ac2eb0417..b78b587d0 100644 --- a/src/platform_impl/linux/window.rs +++ b/src/platform_impl/linux/window.rs @@ -15,7 +15,7 @@ use std::{ use gdk::{Cursor, EventMask, WindowEdge, WindowExt, WindowState}; use gdk_pixbuf::Pixbuf; -use gtk::{prelude::*, AccelGroup, ApplicationWindow}; +use gtk::{prelude::*, AccelGroup, ApplicationWindow, Orientation}; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, @@ -94,6 +94,10 @@ pub struct Window { pub(crate) window: gtk::ApplicationWindow, /// Window requests sender pub(crate) window_requests_tx: Sender<(WindowId, WindowRequest)>, + /// Gtk Acceleration Group + pub(crate) accel_group: AccelGroup, + /// Gtk Menu + pub(crate) menu: gtk::Box, scale_factor: Rc, position: Rc<(AtomicI32, AtomicI32)>, size: Rc<(AtomicI32, AtomicI32)>, @@ -116,8 +120,8 @@ impl Window { .borrow_mut() .insert(window_id); - let group = AccelGroup::new(); - window.add_accel_group(&group); + let accel_group = AccelGroup::new(); + window.add_accel_group(&accel_group); // Set Width/Height & Resizable let win_scale_factor = window.get_scale_factor(); @@ -193,8 +197,11 @@ impl Window { } // Set Menu Bar + let menu = gtk::Box::new(Orientation::Vertical, 0); if let Some(menus) = attributes.window_menu { - menu::initialize(&window, menus, window_requests_tx.clone(), group); + window.add(&menu); + let menubar = menu::initialize(window_id, menus, &window_requests_tx, &accel_group); + menu.pack_start(&menubar, false, false, 0); } // Rest attributes @@ -292,6 +299,8 @@ impl Window { window_id, window, window_requests_tx, + accel_group, + menu, scale_factor, position, size, @@ -410,9 +419,13 @@ impl Window { } } - // TODO - pub fn set_menu(&self, _menu: Option>) { - debug!("`Window::set_menu` is ignored on linux") + pub fn set_menu(&self, menu: Option>) { + if let Err(e) = self.window_requests_tx.send(( + self.window_id, + WindowRequest::SetMenu((menu, self.accel_group.clone(), self.menu.clone())), + )) { + log::warn!("Fail to send menu request: {}", e); + } } pub fn set_visible(&self, visible: bool) { @@ -603,6 +616,7 @@ pub enum WindowRequest { WireUpEvents, Redraw, Menu(MenuItem), + SetMenu((Option>, AccelGroup, gtk::Box)), } pub fn hit_test(window: &gdk::Window, cx: f64, cy: f64) -> WindowEdge {