2022-12-09 05:50:24 +11:00
|
|
|
// Copyright 2022-2022 Tauri Programme within The Commons Conservancy
|
2023-08-05 05:17:58 +10:00
|
|
|
// SPDX-License-Identifier: Apache-2.inner
|
2022-12-09 05:50:24 +11:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2023-07-18 10:44:52 +10:00
|
|
|
use std::{cell::RefCell, rc::Rc};
|
|
|
|
|
2023-08-05 05:17:58 +10:00
|
|
|
use crate::{util::AddOp, ContextMenu, IsMenuItem, MenuId, MenuItemKind, Position};
|
2022-11-24 03:29:52 +11:00
|
|
|
|
|
|
|
/// A root menu that can be added to a Window on Windows and Linux
|
|
|
|
/// and used as the app global menu on macOS.
|
|
|
|
#[derive(Clone)]
|
2023-08-05 05:17:58 +10:00
|
|
|
pub struct Menu {
|
|
|
|
id: MenuId,
|
|
|
|
inner: Rc<RefCell<crate::platform_impl::Menu>>,
|
|
|
|
}
|
2022-11-24 03:29:52 +11:00
|
|
|
|
|
|
|
impl Default for Menu {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Menu {
|
|
|
|
/// Creates a new menu.
|
|
|
|
pub fn new() -> Self {
|
2023-08-05 05:17:58 +10:00
|
|
|
let menu = crate::platform_impl::Menu::new(None);
|
|
|
|
Self {
|
|
|
|
id: menu.id().clone(),
|
|
|
|
inner: Rc::new(RefCell::new(menu)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new menu with the specified id.
|
|
|
|
pub fn with_id<I: Into<MenuId>>(id: I) -> Self {
|
|
|
|
let id = id.into();
|
|
|
|
Self {
|
|
|
|
id: id.clone(),
|
|
|
|
inner: Rc::new(RefCell::new(crate::platform_impl::Menu::new(Some(id)))),
|
|
|
|
}
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new menu with given `items`. It calls [`Menu::new`] and [`Menu::append_items`] internally.
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn with_items(items: &[&dyn IsMenuItem]) -> crate::Result<Self> {
|
2022-11-24 03:29:52 +11:00
|
|
|
let menu = Self::new();
|
2023-07-18 10:44:52 +10:00
|
|
|
menu.append_items(items)?;
|
|
|
|
Ok(menu)
|
|
|
|
}
|
|
|
|
|
2023-08-05 05:17:58 +10:00
|
|
|
/// Creates a new menu with the specified id and given `items`. It calls [`Menu::new`] and [`Menu::append_items`] internally.
|
|
|
|
pub fn with_id_and_items<I: Into<MenuId>>(
|
|
|
|
id: I,
|
|
|
|
items: &[&dyn IsMenuItem],
|
|
|
|
) -> crate::Result<Self> {
|
|
|
|
let menu = Self::with_id(id);
|
|
|
|
menu.append_items(items)?;
|
|
|
|
Ok(menu)
|
|
|
|
}
|
|
|
|
|
2023-07-18 10:44:52 +10:00
|
|
|
/// Returns a unique identifier associated with this menu.
|
2023-08-05 05:17:58 +10:00
|
|
|
pub fn id(&self) -> &MenuId {
|
|
|
|
&self.id
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Add a menu item to the end of this menu.
|
|
|
|
///
|
|
|
|
/// ## Platform-spcific:
|
|
|
|
///
|
|
|
|
/// - **macOS:** Only [`Submenu`] can be added to the menu
|
|
|
|
///
|
|
|
|
/// [`Submenu`]: crate::Submenu
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn append(&self, item: &dyn IsMenuItem) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().add_menu_item(item, AddOp::Append)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Add menu items to the end of this menu. It calls [`Menu::append`] in a loop internally.
|
|
|
|
///
|
|
|
|
/// ## Platform-spcific:
|
|
|
|
///
|
|
|
|
/// - **macOS:** Only [`Submenu`] can be added to the menu
|
|
|
|
///
|
|
|
|
/// [`Submenu`]: crate::Submenu
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn append_items(&self, items: &[&dyn IsMenuItem]) -> crate::Result<()> {
|
2022-11-24 03:29:52 +11:00
|
|
|
for item in items {
|
2023-07-18 10:44:52 +10:00
|
|
|
self.append(*item)?
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
2023-07-18 10:44:52 +10:00
|
|
|
|
|
|
|
Ok(())
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Add a menu item to the beginning of this menu.
|
|
|
|
///
|
|
|
|
/// ## Platform-spcific:
|
|
|
|
///
|
|
|
|
/// - **macOS:** Only [`Submenu`] can be added to the menu
|
|
|
|
///
|
|
|
|
/// [`Submenu`]: crate::Submenu
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn prepend(&self, item: &dyn IsMenuItem) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner
|
|
|
|
.borrow_mut()
|
|
|
|
.add_menu_item(item, AddOp::Insert(0))
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Add menu items to the beginning of this menu. It calls [`Menu::insert_items`] with position of `0` internally.
|
|
|
|
///
|
|
|
|
/// ## Platform-spcific:
|
|
|
|
///
|
|
|
|
/// - **macOS:** Only [`Submenu`] can be added to the menu
|
|
|
|
///
|
|
|
|
/// [`Submenu`]: crate::Submenu
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn prepend_items(&self, items: &[&dyn IsMenuItem]) -> crate::Result<()> {
|
|
|
|
self.insert_items(items, 0)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Insert a menu item at the specified `postion` in the menu.
|
|
|
|
///
|
|
|
|
/// ## Platform-spcific:
|
|
|
|
///
|
|
|
|
/// - **macOS:** Only [`Submenu`] can be added to the menu
|
|
|
|
///
|
|
|
|
/// [`Submenu`]: crate::Submenu
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn insert(&self, item: &dyn IsMenuItem, position: usize) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner
|
2023-07-18 10:44:52 +10:00
|
|
|
.borrow_mut()
|
|
|
|
.add_menu_item(item, AddOp::Insert(position))
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Insert menu items at the specified `postion` in the menu.
|
|
|
|
///
|
|
|
|
/// ## Platform-spcific:
|
|
|
|
///
|
|
|
|
/// - **macOS:** Only [`Submenu`] can be added to the menu
|
|
|
|
///
|
|
|
|
/// [`Submenu`]: crate::Submenu
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn insert_items(&self, items: &[&dyn IsMenuItem], position: usize) -> crate::Result<()> {
|
2022-11-24 03:29:52 +11:00
|
|
|
for (i, item) in items.iter().enumerate() {
|
2023-07-18 10:44:52 +10:00
|
|
|
self.insert(*item, position + i)?
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
2023-07-18 10:44:52 +10:00
|
|
|
|
|
|
|
Ok(())
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove a menu item from this menu.
|
2023-07-18 10:44:52 +10:00
|
|
|
pub fn remove(&self, item: &dyn IsMenuItem) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().remove(item)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
2023-08-20 00:27:39 +10:00
|
|
|
/// Remove the menu item at the specified position from this menu and returns it.
|
2023-08-09 00:53:15 +10:00
|
|
|
pub fn remove_at(&self, position: usize) -> Option<MenuItemKind> {
|
|
|
|
let mut items = self.items();
|
|
|
|
if items.len() > position {
|
|
|
|
let item = items.remove(position);
|
|
|
|
let _ = self.remove(item.as_ref());
|
|
|
|
Some(item)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-24 03:29:52 +11:00
|
|
|
/// Returns a list of menu items that has been added to this menu.
|
2023-07-28 02:58:51 +10:00
|
|
|
pub fn items(&self) -> Vec<MenuItemKind> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().items()
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Adds this menu to a [`gtk::ApplicationWindow`]
|
|
|
|
///
|
2023-07-26 05:01:35 +10:00
|
|
|
/// - `container`: this is an optional paramter to specify a container for the [`gtk::MenuBar`],
|
|
|
|
/// it is highly recommended to pass a container, otherwise the menubar will be added directly to the window,
|
|
|
|
/// which is usually not the desired behavior.
|
2022-11-24 03:29:52 +11:00
|
|
|
///
|
2023-07-26 05:01:35 +10:00
|
|
|
/// ## Example:
|
|
|
|
/// ```no_run
|
|
|
|
/// let window = gtk::ApplicationWindow::builder().build();
|
|
|
|
/// let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
|
|
|
/// let menu = muda::Menu::new();
|
|
|
|
/// // -- snip, add your menu items --
|
|
|
|
/// menu.init_for_gtk_window(&window, Some(&vbox));
|
|
|
|
/// // then proceed to add your widgets to the `vbox`
|
|
|
|
/// ```
|
2022-11-24 03:29:52 +11:00
|
|
|
///
|
|
|
|
/// ## Panics:
|
|
|
|
///
|
|
|
|
/// Panics if the gtk event loop hasn't been initialized on the thread.
|
|
|
|
#[cfg(target_os = "linux")]
|
2023-07-26 05:01:35 +10:00
|
|
|
pub fn init_for_gtk_window<W, C>(&self, window: &W, container: Option<&C>) -> crate::Result<()>
|
2022-11-24 03:29:52 +11:00
|
|
|
where
|
|
|
|
W: gtk::prelude::IsA<gtk::ApplicationWindow>,
|
|
|
|
W: gtk::prelude::IsA<gtk::Window>,
|
2023-07-26 05:01:35 +10:00
|
|
|
W: gtk::prelude::IsA<gtk::Container>,
|
|
|
|
C: gtk::prelude::IsA<gtk::Container>,
|
2023-08-04 04:54:08 +10:00
|
|
|
C: gtk::prelude::IsA<gtk::Box>,
|
2022-11-24 03:29:52 +11:00
|
|
|
{
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner
|
|
|
|
.borrow_mut()
|
|
|
|
.init_for_gtk_window(window, container)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Adds this menu to a win32 window.
|
|
|
|
///
|
|
|
|
/// ## Note about accelerators:
|
|
|
|
///
|
|
|
|
/// For accelerators to work, the event loop needs to call
|
|
|
|
/// [`TranslateAcceleratorW`](windows_sys::Win32::UI::WindowsAndMessaging::TranslateAcceleratorW)
|
|
|
|
/// with the [`HACCEL`](windows_sys::Win32::UI::WindowsAndMessaging::HACCEL) returned from [`Menu::haccel`]
|
|
|
|
///
|
|
|
|
/// #### Example:
|
|
|
|
/// ```no_run
|
|
|
|
/// # use muda::Menu;
|
|
|
|
/// # use windows_sys::Win32::UI::WindowsAndMessaging::{MSG, GetMessageW, TranslateMessage, DispatchMessageW, TranslateAcceleratorW};
|
|
|
|
/// let menu = Menu::new();
|
|
|
|
/// unsafe {
|
|
|
|
/// let mut msg: MSG = std::mem::zeroed();
|
|
|
|
/// while GetMessageW(&mut msg, 0, 0, 0) == 1 {
|
|
|
|
/// let translated = TranslateAcceleratorW(msg.hwnd, menu.haccel(), &msg as *const _);
|
|
|
|
/// if translated != 1{
|
|
|
|
/// TranslateMessage(&msg);
|
|
|
|
/// DispatchMessageW(&msg);
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[cfg(target_os = "windows")]
|
2022-12-05 22:32:34 +11:00
|
|
|
pub fn init_for_hwnd(&self, hwnd: isize) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().init_for_hwnd(hwnd)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns The [`HACCEL`](windows_sys::Win32::UI::WindowsAndMessaging::HACCEL) associated with this menu
|
|
|
|
/// It can be used with [`TranslateAcceleratorW`](windows_sys::Win32::UI::WindowsAndMessaging::TranslateAcceleratorW)
|
|
|
|
/// in the event loop to enable accelerators
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
pub fn haccel(&self) -> windows_sys::Win32::UI::WindowsAndMessaging::HACCEL {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().haccel()
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes this menu from a [`gtk::ApplicationWindow`]
|
|
|
|
#[cfg(target_os = "linux")]
|
2023-07-26 05:01:35 +10:00
|
|
|
pub fn remove_for_gtk_window<W>(&self, window: &W) -> crate::Result<()>
|
2022-11-24 03:29:52 +11:00
|
|
|
where
|
|
|
|
W: gtk::prelude::IsA<gtk::ApplicationWindow>,
|
|
|
|
W: gtk::prelude::IsA<gtk::Window>,
|
|
|
|
{
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().remove_for_gtk_window(window)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes this menu from a win32 window
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
pub fn remove_for_hwnd(&self, hwnd: isize) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().remove_for_hwnd(hwnd)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Hides this menu from a [`gtk::ApplicationWindow`]
|
|
|
|
#[cfg(target_os = "linux")]
|
2023-07-26 05:01:35 +10:00
|
|
|
pub fn hide_for_gtk_window<W>(&self, window: &W) -> crate::Result<()>
|
2022-11-24 03:29:52 +11:00
|
|
|
where
|
|
|
|
W: gtk::prelude::IsA<gtk::ApplicationWindow>,
|
|
|
|
{
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().hide_for_gtk_window(window)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Hides this menu from a win32 window
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
pub fn hide_for_hwnd(&self, hwnd: isize) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().hide_for_hwnd(hwnd)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Shows this menu on a [`gtk::ApplicationWindow`]
|
|
|
|
#[cfg(target_os = "linux")]
|
2023-07-26 05:01:35 +10:00
|
|
|
pub fn show_for_gtk_window<W>(&self, window: &W) -> crate::Result<()>
|
2022-11-24 03:29:52 +11:00
|
|
|
where
|
|
|
|
W: gtk::prelude::IsA<gtk::ApplicationWindow>,
|
|
|
|
{
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().show_for_gtk_window(window)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Shows this menu on a win32 window
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
pub fn show_for_hwnd(&self, hwnd: isize) -> crate::Result<()> {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().show_for_hwnd(hwnd)
|
2023-07-18 10:44:52 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns whether this menu visible on a [`gtk::ApplicationWindow`]
|
|
|
|
#[cfg(target_os = "linux")]
|
2023-07-26 05:01:35 +10:00
|
|
|
pub fn is_visible_on_gtk_window<W>(&self, window: &W) -> bool
|
2023-07-18 10:44:52 +10:00
|
|
|
where
|
|
|
|
W: gtk::prelude::IsA<gtk::ApplicationWindow>,
|
|
|
|
{
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().is_visible_on_gtk_window(window)
|
2023-07-18 10:44:52 +10:00
|
|
|
}
|
|
|
|
|
2023-07-27 21:56:01 +10:00
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
/// Returns the [`gtk::MenuBar`] that is associated with this window if it exists.
|
|
|
|
/// This is useful to get information about the menubar for example its height.
|
|
|
|
pub fn gtk_menubar_for_gtk_window<W>(self, window: &W) -> Option<gtk::MenuBar>
|
|
|
|
where
|
|
|
|
W: gtk::prelude::IsA<gtk::ApplicationWindow>,
|
|
|
|
{
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().gtk_menubar_for_gtk_window(window)
|
2023-07-27 21:56:01 +10:00
|
|
|
}
|
|
|
|
|
2023-07-18 10:44:52 +10:00
|
|
|
/// Returns whether this menu visible on a on a win32 window
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
pub fn is_visible_on_hwnd(&self, hwnd: isize) -> bool {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().is_visible_on_hwnd(hwnd)
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Adds this menu to an NSApp.
|
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
pub fn init_for_nsapp(&self) {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().init_for_nsapp()
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes this menu from an NSApp.
|
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
pub fn remove_for_nsapp(&self) {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().remove_for_nsapp()
|
2022-11-24 03:29:52 +11:00
|
|
|
}
|
|
|
|
}
|
2022-12-05 22:32:34 +11:00
|
|
|
|
|
|
|
impl ContextMenu for Menu {
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
fn hpopupmenu(&self) -> windows_sys::Win32::UI::WindowsAndMessaging::HMENU {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().hpopupmenu()
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "windows")]
|
2023-07-27 21:56:01 +10:00
|
|
|
fn show_context_menu_for_hwnd(&self, hwnd: isize, position: Option<Position>) {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner
|
|
|
|
.borrow()
|
|
|
|
.show_context_menu_for_hwnd(hwnd, position)
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
fn attach_menu_subclass_for_hwnd(&self, hwnd: isize) {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().attach_menu_subclass_for_hwnd(hwnd)
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
fn detach_menu_subclass_from_hwnd(&self, hwnd: isize) {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().detach_menu_subclass_from_hwnd(hwnd)
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
2023-07-27 21:56:01 +10:00
|
|
|
fn show_context_menu_for_gtk_window(
|
|
|
|
&self,
|
|
|
|
window: >k::ApplicationWindow,
|
|
|
|
position: Option<Position>,
|
|
|
|
) {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner
|
2023-07-18 10:44:52 +10:00
|
|
|
.borrow_mut()
|
2023-07-27 21:56:01 +10:00
|
|
|
.show_context_menu_for_gtk_window(window, position)
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
fn gtk_context_menu(&self) -> gtk::Menu {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow_mut().gtk_context_menu()
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "macos")]
|
2023-07-27 21:56:01 +10:00
|
|
|
fn show_context_menu_for_nsview(&self, view: cocoa::base::id, position: Option<Position>) {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner
|
2023-07-27 21:56:01 +10:00
|
|
|
.borrow_mut()
|
|
|
|
.show_context_menu_for_nsview(view, position)
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
fn ns_menu(&self) -> *mut std::ffi::c_void {
|
2023-08-05 05:17:58 +10:00
|
|
|
self.inner.borrow().ns_menu()
|
2022-12-05 22:32:34 +11:00
|
|
|
}
|
|
|
|
}
|