Skip to content

Commit

Permalink
feat(core): add ContextMenu::hpopupmenu on Windows (#11354)
Browse files Browse the repository at this point in the history
* feat(core): add `ContextMenu::hpopupmenu` on Windows

closes #11339

* Update crates/tauri/src/menu/mod.rs

---------

Co-authored-by: Lucas Fernandes Nogueira <[email protected]>
  • Loading branch information
amrbashir and lucasfernog authored Oct 14, 2024
1 parent 68d4460 commit bcf2792
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changes/hpopupmenu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri": "patch:feat"
---

On Windows, Add `ContextMenu::hpopupmenu` method to get the [`HMENU`](https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types#HMENU) used for popups and tray icon menu.
2 changes: 1 addition & 1 deletion crates/tauri-cli/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@
]
},
"Capability": {
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"type": "object",
"required": [
"identifier",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Capability",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"type": "object",
"required": [
"identifier",
Expand Down
2 changes: 1 addition & 1 deletion crates/tauri-schema-generator/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@
]
},
"Capability": {
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"type": "object",
"required": [
"identifier",
Expand Down
5 changes: 5 additions & 0 deletions crates/tauri/src/menu/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ pub const WINDOW_SUBMENU_ID: &str = "__tauri_window_menu__";
pub const HELP_SUBMENU_ID: &str = "__tauri_help_menu__";

impl<R: Runtime> super::ContextMenu for Menu<R> {
#[cfg(target_os = "windows")]
fn hpopupmenu(&self) -> crate::Result<isize> {
run_item_main_thread!(self, |self_: Self| (*self_.0).as_ref().hpopupmenu())
}

fn popup<T: Runtime>(&self, window: Window<T>) -> crate::Result<()> {
self.popup_inner(window, None::<Position>)
}
Expand Down
9 changes: 9 additions & 0 deletions crates/tauri/src/menu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,15 @@ pub trait IsMenuItem<R: Runtime>: sealed::IsMenuItemBase {
///
/// This trait is ONLY meant to be implemented internally by the crate.
pub trait ContextMenu: sealed::ContextMenuBase + Send + Sync {
/// Get the popup [`HMENU`] for this menu.
///
/// The returned [`HMENU`] is valid as long as the [`ContextMenu`] is.
///
/// [`HMENU`]: https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types#HMENU
#[cfg(windows)]
#[cfg_attr(docsrs, doc(cfg(windows)))]
fn hpopupmenu(&self) -> crate::Result<isize>;

/// Popup this menu as a context menu on the specified window at the cursor position.
fn popup<R: crate::Runtime>(&self, window: crate::Window<R>) -> crate::Result<()>;

Expand Down
5 changes: 5 additions & 0 deletions crates/tauri/src/menu/submenu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ use crate::{AppHandle, Manager, Position, Runtime, Window};
use muda::{ContextMenu, MenuId};

impl<R: Runtime> super::ContextMenu for Submenu<R> {
#[cfg(target_os = "windows")]
fn hpopupmenu(&self) -> crate::Result<isize> {
run_item_main_thread!(self, |self_: Self| (*self_.0).as_ref().hpopupmenu())
}

fn popup<T: Runtime>(&self, window: Window<T>) -> crate::Result<()> {
self.popup_inner(window, None::<Position>)
}
Expand Down

0 comments on commit bcf2792

Please sign in to comment.