From ecca4c31aaf072df081380f354c65f5ff232e54f Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:54:31 +0330 Subject: [PATCH 01/14] Implement dynamic inset positions and re-structure files --- Cargo.toml | 1 + examples/tauri-app/src-tauri/src/main.rs | 4 +- permissions/autogenerated/reference.md | 2 +- src/lib.rs | 132 +++++++++++++----- src/macos/mod.rs | 59 ++++++++ .../nswindow_delegates.rs} | 93 +++--------- 6 files changed, 184 insertions(+), 107 deletions(-) create mode 100644 src/macos/mod.rs rename src/{traffic.rs => macos/nswindow_delegates.rs} (78%) diff --git a/Cargo.toml b/Cargo.toml index 7e88551..9941856 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ repository = "https://github.com/clearlysid/tauri-plugin-decorum" tauri = { version = "2.0.0-rc" } serde = "1.0" anyhow = "1.0" +parking_lot = "0.12.3" [target.'cfg(target_os = "macos")'.dependencies] rand = "^0.8" diff --git a/examples/tauri-app/src-tauri/src/main.rs b/examples/tauri-app/src-tauri/src/main.rs index 9e61d19..428a22b 100644 --- a/examples/tauri-app/src-tauri/src/main.rs +++ b/examples/tauri-app/src-tauri/src/main.rs @@ -1,7 +1,7 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use tauri::Manager; +use tauri::{LogicalPosition, Manager}; use tauri_plugin_decorum::WebviewWindowExt; fn main() { @@ -15,7 +15,7 @@ fn main() { main_window.create_overlay_titlebar().unwrap(); #[cfg(target_os = "macos")] - main_window.set_traffic_lights_inset(16.0, 20.0).unwrap(); + let _ = main_window.set_traffic_lights_inset(Some(LogicalPosition::new(16.0, 20.0))); Ok(()) }) .run(tauri::generate_context!()) diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md index 20a102e..54503c0 100644 --- a/permissions/autogenerated/reference.md +++ b/permissions/autogenerated/reference.md @@ -1,5 +1,5 @@ -## Permission Table +### Permission Table diff --git a/src/lib.rs b/src/lib.rs index b280ce6..0d93c72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,24 +1,62 @@ +use std::collections::HashMap; +use std::sync::Arc; + +use macos::nswindow_delegates; +use parking_lot::RwLock; use tauri::plugin::{Builder, TauriPlugin}; -use tauri::{Emitter, Error, Listener, Runtime, WebviewWindow}; +use tauri::{Emitter, Error, Listener, LogicalPosition, Manager, Runtime, WebviewWindow}; #[cfg(target_os = "macos")] -mod traffic; +#[macro_use] +extern crate objc; mod commands; #[cfg(target_os = "macos")] -#[macro_use] -extern crate objc; +mod macos; + +#[repr(u32)] +pub enum NSWindowLevel { + NSNormalWindowLevel = 0, + NSFloatingOrSubmenuOrTornOffMenuWindowLevel = 3, + NSMainMenuWindowLevel = 24, + NSStatusWindowLevel = 25, + NSModalPanelWindowLevel = 8, + NSPopUpMenuWindowLevel = 101, + NSScreenSaverWindowLevel = 1000, +} + +impl From for NSWindowLevel { + fn from(s: String) -> Self { + match s.as_str() { + "NSNormalWindowLevel" => NSWindowLevel::NSNormalWindowLevel, + "NSFloatingWindowLevel" => NSWindowLevel::NSFloatingOrSubmenuOrTornOffMenuWindowLevel, + "NSSubmenuWindowLevel" => NSWindowLevel::NSFloatingOrSubmenuOrTornOffMenuWindowLevel, + "NSTornOffMenuWindowLevel" => { + NSWindowLevel::NSFloatingOrSubmenuOrTornOffMenuWindowLevel + } + "NSMainMenuWindowLevel" => NSWindowLevel::NSMainMenuWindowLevel, + "NSStatusWindowLevel" => NSWindowLevel::NSStatusWindowLevel, + "NSModalPanelWindowLevel" => NSWindowLevel::NSModalPanelWindowLevel, + "NSPopUpMenuWindowLevel" => NSWindowLevel::NSPopUpMenuWindowLevel, + "NSScreenSaverWindowLevel" => NSWindowLevel::NSScreenSaverWindowLevel, + _ => panic!("Unknown NSWindowLevel string: {}", s), + } + } +} /// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the decorum APIs. pub trait WebviewWindowExt { fn create_overlay_titlebar(&self) -> Result<&WebviewWindow, Error>; #[cfg(target_os = "macos")] - fn set_traffic_lights_inset(&self, x: f32, y: f32) -> Result<&WebviewWindow, Error>; + fn set_traffic_lights_inset( + &self, + inset: Option>, + ) -> Result<&WebviewWindow, Error>; #[cfg(target_os = "macos")] fn make_transparent(&self) -> Result<&WebviewWindow, Error>; #[cfg(target_os = "macos")] - fn set_window_level(&self, level: u32) -> Result<&WebviewWindow, Error>; + fn set_window_level(&self, level: NSWindowLevel) -> Result<&WebviewWindow, Error>; } impl<'a> WebviewWindowExt for WebviewWindow { @@ -88,15 +126,36 @@ impl<'a> WebviewWindowExt for WebviewWindow { /// This will move the traffic lights to the specified position. /// This is only available on macOS. #[cfg(target_os = "macos")] - fn set_traffic_lights_inset(&self, x: f32, y: f32) -> Result<&WebviewWindow, Error> { - ensure_main_thread(self, move |win| { - let ns_window = win.ns_window()?; - let ns_window_handle = traffic::UnsafeWindowHandle(ns_window); + fn set_traffic_lights_inset( + &self, + inset: Option>, + ) -> Result<&WebviewWindow, Error> { + let insets_state = &self.state::(); + let mut insets_map = insets_state.0.write(); - traffic::position_traffic_lights(ns_window_handle, x.into(), y.into()); + let window_label = self.label().to_string(); - Ok(win) - }) + match inset { + Some(inset) => { + if insets_map.insert(window_label, inset.clone()).is_none() { + self.on_window_event(move |event| match event { + tauri::WindowEvent::ThemeChanged(_) => { + // TODO: Update + } + _ => (), + }); + } + + ensure_main_thread(self, move |win| { + // macos::update_traffic_lights_inset(win); + Ok(win) + }) + } + None => { + insets_map.remove(&window_label); + Ok(self) + } + } } /// Set the window background to transparent. @@ -105,7 +164,6 @@ impl<'a> WebviewWindowExt for WebviewWindow { #[cfg(target_os = "macos")] fn make_transparent(&self) -> Result<&WebviewWindow, Error> { use cocoa::{ - appkit::NSColor, base::{id, nil}, foundation::NSString, }; @@ -118,24 +176,15 @@ impl<'a> WebviewWindowExt for WebviewWindow { msg_send![id, setValue:no forKey: NSString::alloc(nil).init_str("drawsBackground")]; })?; - // Make window background transparent - ensure_main_thread(self, move |win| { - let ns_win = win.ns_window()? as id; - unsafe { - let win_bg_color = - NSColor::colorWithSRGBRed_green_blue_alpha_(nil, 0.0, 0.0, 0.0, 0.0); - let _: id = msg_send![ns_win, setBackgroundColor: win_bg_color]; - } - Ok(win) - }) + Ok(self) } /// Set the window level. /// This will set the window level to the specified value. - /// NSWindowLevel values can be found [here](https://developer.apple.com/documentation/appkit/nswindowlevel?language=objc). + /// NSWindowLevel values can be found [here](https://developer.apple.com/documentation/appkit/NSWindowLevel?language=objc). /// This is only available on macOS. #[cfg(target_os = "macos")] - fn set_window_level(&self, level: u32) -> Result<&WebviewWindow, Error> { + fn set_window_level(&self, level: NSWindowLevel) -> Result<&WebviewWindow, Error> { ensure_main_thread(self, move |win| { let ns_win = win.ns_window()? as cocoa::base::id; unsafe { @@ -146,21 +195,36 @@ impl<'a> WebviewWindowExt for WebviewWindow { } } +#[cfg(target_os = "macos")] +struct TrafficLightsInsetsState(Arc>>>); + pub fn init() -> TauriPlugin { - Builder::new("decorum") + let mut builder = Builder::new("decorum") .invoke_handler(tauri::generate_handler![commands::show_snap_overlay]) + .setup(move |app, _api| { + #[cfg(target_os = "macos")] + app.manage(TrafficLightsInsetsState(Arc::new(RwLock::new( + HashMap::new(), + )))); + + Ok(()) + }) .on_page_load(|win, _payload: &tauri::webview::PageLoadPayload| { match win.emit("decorum-page-load", ()) { Ok(_) => {} Err(e) => println!("decorum error: {:?}", e), } - }) - .on_window_ready(|_win| { - #[cfg(target_os = "macos")] - traffic::setup_traffic_light_positioner(_win); - return; - }) - .build() + }); + + #[cfg(target_os = "macos")] + { + builder = builder.on_window_ready(|window| { + // TODO: Only setup if the inset is defined in the config. + nswindow_delegates::setup(window); + }); + } + + builder.build() } #[cfg(target_os = "macos")] diff --git a/src/macos/mod.rs b/src/macos/mod.rs new file mode 100644 index 0000000..54674f0 --- /dev/null +++ b/src/macos/mod.rs @@ -0,0 +1,59 @@ +use nswindow_delegates::UnsafeWindowHandle; +// use objc::{msg_send, sel, sel_impl}; +// use rand::{distributions::Alphanumeric, Rng}; +use tauri::{LogicalPosition, Manager, Runtime, Window}; + +use crate::TrafficLightsInsetsState; + +pub mod nswindow_delegates; + +const DEFAULT_TRAFFIC_LIGHTS_INSET: LogicalPosition = LogicalPosition::new(12.0, 16.0); + +pub fn update_traffic_lights_inset(window: &Window) { + let insets_state = &window.state::(); + let insets_map = insets_state.0.read(); + let inset = insets_map + .get(&window.label().to_string()) + .unwrap_or(&DEFAULT_TRAFFIC_LIGHTS_INSET); + + position_traffic_lights( + UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), + inset.x, + inset.y, + ); +} + +fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { + use cocoa::appkit::{NSView, NSWindow, NSWindowButton}; + use cocoa::foundation::NSRect; + let ns_window = ns_window_handle.0 as cocoa::base::id; + unsafe { + let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); + let miniaturize = + ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); + let zoom = ns_window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); + + let title_bar_container_view = close.superview().superview(); + + let close_rect: NSRect = msg_send![close, frame]; + let button_height = close_rect.size.height; + + let title_bar_frame_height = button_height + y; + let mut title_bar_rect = NSView::frame(title_bar_container_view); + title_bar_rect.size.height = title_bar_frame_height; + title_bar_rect.origin.y = NSView::frame(ns_window).size.height - title_bar_frame_height; + let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; + + let window_buttons = vec![close, miniaturize, zoom]; + let space_between = 20.0; // Fixed space between buttons + let vertical_offset = 4.0; // Adjust this value to push buttons down + + for (i, button) in window_buttons.into_iter().enumerate() { + let mut rect: NSRect = NSView::frame(button); + rect.origin.x = x + (i as f64 * space_between); + // Adjust vertical positioning + rect.origin.y = ((title_bar_frame_height - button_height) / 2.0) - vertical_offset; + button.setFrameOrigin(rect.origin); + } + } +} diff --git a/src/traffic.rs b/src/macos/nswindow_delegates.rs similarity index 78% rename from src/traffic.rs rename to src/macos/nswindow_delegates.rs index 115a7d0..d7c509c 100644 --- a/src/traffic.rs +++ b/src/macos/nswindow_delegates.rs @@ -1,75 +1,44 @@ -// Most contents of this file are taken from Hoppscotch's tauri app. -// I think there is work to be done to improve it, but I'm happy with it for now. -// Reference source code is linked below. -// https://github.com/hoppscotch/hoppscotch/blob/286fcd2bb08a84f027b10308d1e18da368f95ebf/packages/hoppscotch-selfhost-desktop/src-tauri/src/mac/window.rs - +/// +/// Credit to @haasal, @charrondev and Hoppscotch +/// This is also similar to how it is implemented in Zed.dev editor +/// +/// https://github.com/haasal +/// https://gist.github.com/charrondev +/// https://github.com/hoppscotch/hoppscotch +/// https://github.com/clearlysid/tauri-plugin-decorum/ +/// (Issue) https://github.com/tauri-apps/tauri/issues/4789 +/// (Gist) https://gist.github.com/charrondev/43150e940bd2771b1ea88256d491c7a9 +/// (Hoppscotch) https://github.com/hoppscotch/hoppscotch/blob/286fcd2bb08a84f027b10308d1e18da368f95ebf/packages/hoppscotch-selfhost-desktop/src-tauri/src/mac/window.rs +/// use objc::{msg_send, sel, sel_impl}; use rand::{distributions::Alphanumeric, Rng}; use tauri::{Emitter, Runtime, Window}; -const WINDOW_CONTROL_PAD_X: f64 = 12.0; -const WINDOW_CONTROL_PAD_Y: f64 = 16.0; - pub struct UnsafeWindowHandle(pub *mut std::ffi::c_void); unsafe impl Send for UnsafeWindowHandle {} unsafe impl Sync for UnsafeWindowHandle {} -#[cfg(target_os = "macos")] -pub fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { - use cocoa::appkit::{NSView, NSWindow, NSWindowButton}; - use cocoa::foundation::NSRect; - let ns_window = ns_window_handle.0 as cocoa::base::id; - unsafe { - let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let miniaturize = - ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let zoom = ns_window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - - let title_bar_container_view = close.superview().superview(); - - let close_rect: NSRect = msg_send![close, frame]; - let button_height = close_rect.size.height; - - let title_bar_frame_height = button_height + y; - let mut title_bar_rect = NSView::frame(title_bar_container_view); - title_bar_rect.size.height = title_bar_frame_height; - title_bar_rect.origin.y = NSView::frame(ns_window).size.height - title_bar_frame_height; - let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; - - let window_buttons = vec![close, miniaturize, zoom]; - let space_between = 20.0; // Fixed space between buttons - let vertical_offset = 4.0; // Adjust this value to push buttons down - - for (i, button) in window_buttons.into_iter().enumerate() { - let mut rect: NSRect = NSView::frame(button); - rect.origin.x = x + (i as f64 * space_between); - // Adjust vertical positioning - rect.origin.y = ((title_bar_frame_height - button_height) / 2.0) - vertical_offset; - button.setFrameOrigin(rect.origin); - } - } -} - -#[cfg(target_os = "macos")] #[derive(Debug)] struct WindowState { window: Window, } -#[cfg(target_os = "macos")] -pub fn setup_traffic_light_positioner(window: Window) { +pub fn setup(window: Window) { use cocoa::appkit::NSWindow; use cocoa::base::{id, BOOL}; use cocoa::foundation::NSUInteger; use objc::runtime::{Object, Sel}; use std::ffi::c_void; + use crate::macos::update_traffic_lights_inset; + // Do the initial positioning - position_traffic_lights( - UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), - WINDOW_CONTROL_PAD_X, - WINDOW_CONTROL_PAD_Y, - ); + // position_traffic_lights( + // UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), + // WINDOW_CONTROL_PAD_X, + // WINDOW_CONTROL_PAD_Y, + // ); + // update_traffic_lights_inset(&window); // Ensure they stay in place while resizing the window. fn with_window_state) -> T, T>( @@ -106,18 +75,7 @@ pub fn setup_traffic_light_positioner(window: Window) { extern "C" fn on_window_did_resize(this: &Object, _cmd: Sel, notification: id) { unsafe { with_window_state(&*this, |state: &mut WindowState| { - let id = state - .window - .ns_window() - .expect("NS window should exist on state to handle resize") - as id; - - #[cfg(target_os = "macos")] - position_traffic_lights( - UnsafeWindowHandle(id as *mut std::ffi::c_void), - WINDOW_CONTROL_PAD_X, - WINDOW_CONTROL_PAD_Y, - ); + update_traffic_lights_inset(&state.window); }); let super_del: id = *this.get_ivar("super_delegate"); @@ -243,12 +201,7 @@ pub fn setup_traffic_light_positioner(window: Window) { .emit("did-exit-fullscreen", ()) .expect("Failed to emit event"); - let id = state.window.ns_window().expect("Failed to emit event") as id; - position_traffic_lights( - UnsafeWindowHandle(id as *mut std::ffi::c_void), - WINDOW_CONTROL_PAD_X, - WINDOW_CONTROL_PAD_Y, - ); + update_traffic_lights_inset(&state.window); }); let super_del: id = *this.get_ivar("super_delegate"); From a75f01e3d6ba63a2fd482f250c8a12819414214d Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:55:21 +0330 Subject: [PATCH 02/14] Switch to PNPM --- examples/tauri-app/src-tauri/tauri.conf.json | 6 +++--- package.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/tauri-app/src-tauri/tauri.conf.json b/examples/tauri-app/src-tauri/tauri.conf.json index b4d22b5..5e703e9 100644 --- a/examples/tauri-app/src-tauri/tauri.conf.json +++ b/examples/tauri-app/src-tauri/tauri.conf.json @@ -3,8 +3,8 @@ "version": "0.0.0", "identifier": "com.tauritempplugin.dev", "build": { - "beforeDevCommand": "yarn dev", - "beforeBuildCommand": "yarn build", + "beforeDevCommand": "pnpm dev", + "beforeBuildCommand": "pnpm build", "devUrl": "http://localhost:1420", "frontendDist": "../dist" }, @@ -36,4 +36,4 @@ "icons/icon.ico" ] } -} \ No newline at end of file +} diff --git a/package.json b/package.json index d8a1bad..82f77b4 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ ], "scripts": { "build": "rollup -c", - "prepublishOnly": "yarn build", - "pretest": "yarn build" + "prepublishOnly": "pnpm build", + "pretest": "pnpm build" }, "dependencies": { "@tauri-apps/api": ">=2.0.0-beta.24" @@ -30,4 +30,4 @@ "typescript": "^5.3.3", "tslib": "^2.6.2" } -} \ No newline at end of file +} From eaa1762641d96c67052180e2b83b815aa7f4b574 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:04:55 +0330 Subject: [PATCH 03/14] update example app --- .../src-tauri/gen/schemas/acl-manifests.json | 2 +- .../src-tauri/gen/schemas/capabilities.json | 2 +- examples/tauri-app/src-tauri/tauri.conf.json | 40 +++++++++++-------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json b/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json index 0be3dca..0334785 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json +++ b/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"decorum":{"default_permission":null,"permissions":{"allow-show-snap-overlay":{"identifier":"allow-show-snap-overlay","description":"Enables the show_snap_overlay command without any pre-configured scope.","commands":{"allow":["show_snap_overlay"],"deny":[]}},"deny-show-snap-overlay":{"identifier":"deny-show-snap-overlay","description":"Denies the show_snap_overlay command without any pre-configured scope.","commands":{"allow":[],"deny":["show_snap_overlay"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"decorum":{"default_permission":null,"permissions":{"allow-show-snap-overlay":{"identifier":"allow-show-snap-overlay","description":"Enables the show_snap_overlay command without any pre-configured scope.","commands":{"allow":["show_snap_overlay"],"deny":[]}},"deny-show-snap-overlay":{"identifier":"deny-show-snap-overlay","description":"Denies the show_snap_overlay command without any pre-configured scope.","commands":{"allow":[],"deny":["show_snap_overlay"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/examples/tauri-app/src-tauri/gen/schemas/capabilities.json b/examples/tauri-app/src-tauri/gen/schemas/capabilities.json index 2c92d48..124da7c 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/capabilities.json +++ b/examples/tauri-app/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:app:default","core:path:default","core:menu:default","core:tray:default","core:image:default","core:event:default","core:window:default","core:resources:default","core:window:allow-close","core:window:allow-center","core:window:allow-minimize","core:window:allow-maximize","core:window:allow-set-size","core:window:allow-set-focus","core:window:allow-start-dragging","core:window:allow-toggle-maximize","decorum:allow-show-snap-overlay"]}} \ No newline at end of file +{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:app:default","core:path:default","core:menu:default","core:tray:default","core:image:default","core:event:default","core:window:default","core:resources:default","core:window:allow-close","core:window:allow-center","core:window:allow-minimize","core:window:allow-maximize","core:window:allow-set-size","core:window:allow-set-focus","core:window:allow-is-maximized","core:window:allow-start-dragging","core:window:allow-toggle-maximize","decorum:allow-show-snap-overlay"]}} \ No newline at end of file diff --git a/examples/tauri-app/src-tauri/tauri.conf.json b/examples/tauri-app/src-tauri/tauri.conf.json index 5e703e9..b2f250e 100644 --- a/examples/tauri-app/src-tauri/tauri.conf.json +++ b/examples/tauri-app/src-tauri/tauri.conf.json @@ -1,33 +1,41 @@ { - "productName": "tauri-app", - "version": "0.0.0", - "identifier": "com.tauritempplugin.dev", + "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "productName": "Plugin Decorum Example", + "identifier": "com.github/clearlysid/tauri-plugin-decorum", "build": { "beforeDevCommand": "pnpm dev", + "devUrl": "http://localhost:3000", "beforeBuildCommand": "pnpm build", - "devUrl": "http://localhost:1420", - "frontendDist": "../dist" + "frontendDist": "../.output/public" }, + "plugins": {}, "app": { - "withGlobalTauri": true, - "security": { - "csp": null - }, "windows": [ { - "fullscreen": false, - "resizable": true, - "title": "tauri-app", - "width": 600, + "title": "Decorum", + "minHeight": 500, + "minWidth": 300, + "width": 580, "height": 400, + "hiddenTitle": false, + "zoomHotkeysEnabled": true, "titleBarStyle": "Overlay", - "hiddenTitle": true + "windowEffects": { + "effects": ["underWindowBackground", "mica"] + } } - ] + ], + "security": { + "csp": null + }, + "withGlobalTauri": false }, "bundle": { + "macOS": { + "signingIdentity": "-" + }, "active": true, - "targets": "all", + "targets": ["app", "nsis"], "icon": [ "icons/32x32.png", "icons/128x128.png", From 71344a0f46ff9b0c3b5380ac4f8fca51d761c660 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 29 Aug 2024 22:48:42 +0330 Subject: [PATCH 04/14] significant re-structuring, fixes --- Cargo.toml | 6 +- build.rs | 2 +- .../src-tauri/capabilities/default.json | 9 +- .../src-tauri/gen/schemas/acl-manifests.json | 2 +- .../src-tauri/gen/schemas/capabilities.json | 2 +- .../src-tauri/gen/schemas/desktop-schema.json | 42 +-- .../src-tauri/gen/schemas/macOS-schema.json | 14 + examples/tauri-app/src-tauri/src/main.rs | 10 +- examples/tauri-app/src-tauri/tauri.conf.json | 2 +- examples/tauri-app/src/App.tsx | 24 +- examples/tauri-app/src/styles.css | 142 ++++---- guest-js/index.ts | 13 +- .../commands/set_window_buttons_inset.toml | 13 + permissions/autogenerated/reference.md | 52 +++ permissions/schemas/schema.json | 28 ++ pnpm-lock.yaml | 307 ++++++++++++++++++ src/commands.rs | 26 +- src/lib.rs | 174 +++++----- src/macos/mod.rs | 41 ++- src/macos/nswindow_delegates.rs | 20 +- yarn.lock | 198 ----------- 21 files changed, 686 insertions(+), 441 deletions(-) create mode 100644 permissions/autogenerated/commands/set_window_buttons_inset.toml create mode 100644 pnpm-lock.yaml delete mode 100644 yarn.lock diff --git a/Cargo.toml b/Cargo.toml index 9941856..bb6d620 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Siddharth "] description = "Opnionated window decoration controls for Tauri apps." edition = "2021" rust-version = "1.70" -exclude = ["/examples", "/webview-dist", "/webview-src", "/node_modules"] +exclude = ["/examples", "/dist-js", "/guest-js", "/node_modules"] links = "tauri-plugin-decorum" license = "MIT" homepage = "https://github.com/clearlysid/tauri-plugin-decorum" @@ -15,12 +15,12 @@ repository = "https://github.com/clearlysid/tauri-plugin-decorum" tauri = { version = "2.0.0-rc" } serde = "1.0" anyhow = "1.0" -parking_lot = "0.12.3" [target.'cfg(target_os = "macos")'.dependencies] rand = "^0.8" -cocoa = "0.25" +cocoa = "0.26" objc = "0.2" +parking_lot = "0.12.3" [target.'cfg(target_os = "windows")'.dependencies] enigo = "0.1.3" diff --git a/build.rs b/build.rs index 4d2ff8a..486ac92 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,4 @@ -const COMMANDS: &[&str] = &["show_snap_overlay"]; +const COMMANDS: &[&str] = &["show_snap_overlay", "set_window_buttons_inset"]; fn main() { tauri_plugin::Builder::new(COMMANDS).build(); diff --git a/examples/tauri-app/src-tauri/capabilities/default.json b/examples/tauri-app/src-tauri/capabilities/default.json index 0517d99..c41a82e 100644 --- a/examples/tauri-app/src-tauri/capabilities/default.json +++ b/examples/tauri-app/src-tauri/capabilities/default.json @@ -2,9 +2,7 @@ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "Capability for the main window", - "windows": [ - "main" - ], + "windows": ["main"], "permissions": [ "core:app:default", "core:path:default", @@ -23,6 +21,7 @@ "core:window:allow-is-maximized", "core:window:allow-start-dragging", "core:window:allow-toggle-maximize", - "decorum:allow-show-snap-overlay" + "decorum:allow-show-snap-overlay", + "decorum:allow-set-window-buttons-inset" ] -} \ No newline at end of file +} diff --git a/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json b/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json index 0334785..c6d8dbf 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json +++ b/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"decorum":{"default_permission":null,"permissions":{"allow-show-snap-overlay":{"identifier":"allow-show-snap-overlay","description":"Enables the show_snap_overlay command without any pre-configured scope.","commands":{"allow":["show_snap_overlay"],"deny":[]}},"deny-show-snap-overlay":{"identifier":"deny-show-snap-overlay","description":"Denies the show_snap_overlay command without any pre-configured scope.","commands":{"allow":[],"deny":["show_snap_overlay"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"decorum":{"default_permission":null,"permissions":{"allow-set-window-buttons-inset":{"identifier":"allow-set-window-buttons-inset","description":"Enables the set_window_buttons_inset command without any pre-configured scope.","commands":{"allow":["set_window_buttons_inset"],"deny":[]}},"allow-show-snap-overlay":{"identifier":"allow-show-snap-overlay","description":"Enables the show_snap_overlay command without any pre-configured scope.","commands":{"allow":["show_snap_overlay"],"deny":[]}},"deny-set-window-buttons-inset":{"identifier":"deny-set-window-buttons-inset","description":"Denies the set_window_buttons_inset command without any pre-configured scope.","commands":{"allow":[],"deny":["set_window_buttons_inset"]}},"deny-show-snap-overlay":{"identifier":"deny-show-snap-overlay","description":"Denies the show_snap_overlay command without any pre-configured scope.","commands":{"allow":[],"deny":["show_snap_overlay"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/examples/tauri-app/src-tauri/gen/schemas/capabilities.json b/examples/tauri-app/src-tauri/gen/schemas/capabilities.json index 124da7c..eadb002 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/capabilities.json +++ b/examples/tauri-app/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:app:default","core:path:default","core:menu:default","core:tray:default","core:image:default","core:event:default","core:window:default","core:resources:default","core:window:allow-close","core:window:allow-center","core:window:allow-minimize","core:window:allow-maximize","core:window:allow-set-size","core:window:allow-set-focus","core:window:allow-is-maximized","core:window:allow-start-dragging","core:window:allow-toggle-maximize","decorum:allow-show-snap-overlay"]}} \ No newline at end of file +{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:app:default","core:path:default","core:menu:default","core:tray:default","core:image:default","core:event:default","core:window:default","core:resources:default","core:window:allow-close","core:window:allow-center","core:window:allow-minimize","core:window:allow-maximize","core:window:allow-set-size","core:window:allow-set-focus","core:window:allow-is-maximized","core:window:allow-start-dragging","core:window:allow-toggle-maximize","decorum:allow-show-snap-overlay","decorum:allow-set-window-buttons-inset"]}} \ No newline at end of file diff --git a/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json b/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json index 402bf1e..fac3235 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json +++ b/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json @@ -1039,13 +1039,6 @@ "core:webview:allow-create-webview-window" ] }, - { - "description": "core:webview:allow-get-all-webviews -> Enables the get_all_webviews command without any pre-configured scope.", - "type": "string", - "enum": [ - "core:webview:allow-get-all-webviews" - ] - }, { "description": "core:webview:allow-internal-toggle-devtools -> Enables the internal_toggle_devtools command without any pre-configured scope.", "type": "string", @@ -1130,13 +1123,6 @@ "core:webview:deny-create-webview-window" ] }, - { - "description": "core:webview:deny-get-all-webviews -> Denies the get_all_webviews command without any pre-configured scope.", - "type": "string", - "enum": [ - "core:webview:deny-get-all-webviews" - ] - }, { "description": "core:webview:deny-internal-toggle-devtools -> Denies the internal_toggle_devtools command without any pre-configured scope.", "type": "string", @@ -1263,13 +1249,6 @@ "core:window:allow-destroy" ] }, - { - "description": "core:window:allow-get-all-windows -> Enables the get_all_windows command without any pre-configured scope.", - "type": "string", - "enum": [ - "core:window:allow-get-all-windows" - ] - }, { "description": "core:window:allow-hide -> Enables the hide command without any pre-configured scope.", "type": "string", @@ -1725,13 +1704,6 @@ "core:window:deny-destroy" ] }, - { - "description": "core:window:deny-get-all-windows -> Denies the get_all_windows command without any pre-configured scope.", - "type": "string", - "enum": [ - "core:window:deny-get-all-windows" - ] - }, { "description": "core:window:deny-hide -> Denies the hide command without any pre-configured scope.", "type": "string", @@ -2144,6 +2116,13 @@ "decorum:default" ] }, + { + "description": "decorum:allow-set-window-buttons-inset -> Enables the set_window_buttons_inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "decorum:allow-set-window-buttons-inset" + ] + }, { "description": "decorum:allow-show-snap-overlay -> Enables the show_snap_overlay command without any pre-configured scope.", "type": "string", @@ -2151,6 +2130,13 @@ "decorum:allow-show-snap-overlay" ] }, + { + "description": "decorum:deny-set-window-buttons-inset -> Denies the set_window_buttons_inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "decorum:deny-set-window-buttons-inset" + ] + }, { "description": "decorum:deny-show-snap-overlay -> Denies the show_snap_overlay command without any pre-configured scope.", "type": "string", diff --git a/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json b/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json index cedb605..fac3235 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json +++ b/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json @@ -2116,6 +2116,13 @@ "decorum:default" ] }, + { + "description": "decorum:allow-set-window-buttons-inset -> Enables the set_window_buttons_inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "decorum:allow-set-window-buttons-inset" + ] + }, { "description": "decorum:allow-show-snap-overlay -> Enables the show_snap_overlay command without any pre-configured scope.", "type": "string", @@ -2123,6 +2130,13 @@ "decorum:allow-show-snap-overlay" ] }, + { + "description": "decorum:deny-set-window-buttons-inset -> Denies the set_window_buttons_inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "decorum:deny-set-window-buttons-inset" + ] + }, { "description": "decorum:deny-show-snap-overlay -> Denies the show_snap_overlay command without any pre-configured scope.", "type": "string", diff --git a/examples/tauri-app/src-tauri/src/main.rs b/examples/tauri-app/src-tauri/src/main.rs index 428a22b..036e1a0 100644 --- a/examples/tauri-app/src-tauri/src/main.rs +++ b/examples/tauri-app/src-tauri/src/main.rs @@ -12,10 +12,16 @@ fn main() { // On Windows this will hide decoration and render custom window controls // On macOS it expects a hiddenTitle: true and titleBarStyle: overlay let main_window = app.get_webview_window("main").unwrap(); - main_window.create_overlay_titlebar().unwrap(); + // main_window.create_overlay_titlebar().unwrap(); #[cfg(target_os = "macos")] - let _ = main_window.set_traffic_lights_inset(Some(LogicalPosition::new(16.0, 20.0))); + { + let _ = main_window.make_transparent(); + let _ = main_window.create_overlay_titlebar(); + let _ = + main_window.set_window_buttons_inset(Some(LogicalPosition::new(15.0, 25.0))); + } + Ok(()) }) .run(tauri::generate_context!()) diff --git a/examples/tauri-app/src-tauri/tauri.conf.json b/examples/tauri-app/src-tauri/tauri.conf.json index b2f250e..3064605 100644 --- a/examples/tauri-app/src-tauri/tauri.conf.json +++ b/examples/tauri-app/src-tauri/tauri.conf.json @@ -4,7 +4,7 @@ "identifier": "com.github/clearlysid/tauri-plugin-decorum", "build": { "beforeDevCommand": "pnpm dev", - "devUrl": "http://localhost:3000", + "devUrl": "http://localhost:1420", "beforeBuildCommand": "pnpm build", "frontendDist": "../.output/public" }, diff --git a/examples/tauri-app/src/App.tsx b/examples/tauri-app/src/App.tsx index 82dd01a..7a174eb 100644 --- a/examples/tauri-app/src/App.tsx +++ b/examples/tauri-app/src/App.tsx @@ -1,16 +1,16 @@ function App() { - return ( -
-

Welcome to Tauri!

+ return ( +
+

Welcome to Tauri!

-
- - Tauri logo - -
-

Click on the Tauri logo to learn more.

-
- ); +
+ + Tauri logo + +
+

Click on the Tauri logo to learn more.

+
+ ); } -export default App; \ No newline at end of file +export default App; diff --git a/examples/tauri-app/src/styles.css b/examples/tauri-app/src/styles.css index 4c85ddf..3df6665 100644 --- a/examples/tauri-app/src/styles.css +++ b/examples/tauri-app/src/styles.css @@ -1,116 +1,116 @@ :root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - - color: #222222; - background-color: #f6f6f6; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color: #222222; + background-color: none !important; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; } .container { - margin: 0; - height: 100vh; - display: flex; - text-align: center; - flex-direction: column; - justify-content: center; + margin: 0; + height: 100vh; + display: flex; + text-align: center; + flex-direction: column; + justify-content: center; } .logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: 0.75s; + height: 6em; + padding: 1.5em; + will-change: filter; + transition: 0.75s; } .logo.tauri:hover { - filter: drop-shadow(0 0 2em #24c8db); + filter: drop-shadow(0 0 2em #24c8db); } .row { - display: flex; - justify-content: center; + display: flex; + justify-content: center; } a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; + font-weight: 500; + color: #646cff; + text-decoration: inherit; } a:hover { - color: #535bf2; + color: #535bf2; } h1 { - text-align: center; + text-align: center; } input, button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - color: #0f0f0f; - background-color: #ffffff; - transition: border-color 0.25s; - box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + color: #0f0f0f; + background-color: #ffffff; + transition: border-color 0.25s; + box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); } button { - cursor: pointer; + cursor: pointer; } button:hover { - border-color: #396cd8; + border-color: #396cd8; } button:active { - border-color: #396cd8; - background-color: #e8e8e8; + border-color: #396cd8; + background-color: #e8e8e8; } input, button { - outline: none; + outline: none; } #greet-input { - margin-right: 5px; + margin-right: 5px; } @media (prefers-color-scheme: dark) { - :root { - color: #f6f6f6; - background-image: linear-gradient(180deg, #350042 0%, #1f003b 100%); - background-size: cover; - } - - body { - height: 100vh; - overscroll-behavior: none; - overflow: hidden; - } - - a:hover { - color: #24c8db; - } - - input, - button { - color: #ffffff; - background-color: #0f0f0f98; - } - button:active { - background-color: #0f0f0f69; - } + :root { + color: #f6f6f6; + background-image: linear-gradient(180deg, #350042 0%, #1f003b 100%); + background-size: cover; + } + + body { + height: 100vh; + overscroll-behavior: none; + overflow: hidden; + } + + a:hover { + color: #24c8db; + } + + input, + button { + color: #ffffff; + background-color: #0f0f0f98; + } + button:active { + background-color: #0f0f0f69; + } } diff --git a/guest-js/index.ts b/guest-js/index.ts index e99cf6f..a0cfe5d 100644 --- a/guest-js/index.ts +++ b/guest-js/index.ts @@ -1,5 +1,16 @@ import { invoke } from "@tauri-apps/api/core"; +import { LogicalPosition } from "@tauri-apps/api/dpi"; export async function show_snap_overlay() { - await invoke("plugin:decorum|show_snap_overlay"); + await invoke("plugin:decorum|show_snap_overlay"); +} + +export async function setWindowButtonsInset( + inset: LogicalPosition | null, + targetLabel: string | null = null +) { + await invoke("plugin:decorum|set_window_buttons_inset", { + inset, + target_label: targetLabel, + }); } diff --git a/permissions/autogenerated/commands/set_window_buttons_inset.toml b/permissions/autogenerated/commands/set_window_buttons_inset.toml new file mode 100644 index 0000000..153e48b --- /dev/null +++ b/permissions/autogenerated/commands/set_window_buttons_inset.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-set-window-buttons-inset" +description = "Enables the set_window_buttons_inset command without any pre-configured scope." +commands.allow = ["set_window_buttons_inset"] + +[[permission]] +identifier = "deny-set-window-buttons-inset" +description = "Denies the set_window_buttons_inset command without any pre-configured scope." +commands.deny = ["set_window_buttons_inset"] diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md index 54503c0..53abc37 100644 --- a/permissions/autogenerated/reference.md +++ b/permissions/autogenerated/reference.md @@ -8,6 +8,58 @@
+ + + + + + + + + + + + + + + + + + + +
+ +`decorum:allow-set-window-buttons-inset` + + + +Enables the set-window-buttons-inset command without any pre-configured scope. + +
+ +`decorum:deny-set-window-buttons-inset` + + + +Denies the set-window-buttons-inset command without any pre-configured scope. + +
+ +`decorum:allow-set-window-buttons-inset` + + + +Enables the set_window_buttons_inset command without any pre-configured scope. + +
+ +`decorum:deny-set-window-buttons-inset` + + + +Denies the set_window_buttons_inset command without any pre-configured scope. + +
diff --git a/permissions/schemas/schema.json b/permissions/schemas/schema.json index b88a821..7b4fcc2 100644 --- a/permissions/schemas/schema.json +++ b/permissions/schemas/schema.json @@ -294,6 +294,34 @@ "PermissionKind": { "type": "string", "oneOf": [ + { + "description": "allow-set-window-buttons-inset -> Enables the set-window-buttons-inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "allow-set-window-buttons-inset" + ] + }, + { + "description": "deny-set-window-buttons-inset -> Denies the set-window-buttons-inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "deny-set-window-buttons-inset" + ] + }, + { + "description": "allow-set-window-buttons-inset -> Enables the set_window_buttons_inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "allow-set-window-buttons-inset" + ] + }, + { + "description": "deny-set-window-buttons-inset -> Denies the set_window_buttons_inset command without any pre-configured scope.", + "type": "string", + "enum": [ + "deny-set-window-buttons-inset" + ] + }, { "description": "allow-show-snap-overlay -> Enables the show_snap_overlay command without any pre-configured scope.", "type": "string", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..2befe8c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,307 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@tauri-apps/api': + specifier: '>=2.0.0-beta.24' + version: 2.0.0-rc.3 + devDependencies: + '@rollup/plugin-typescript': + specifier: ^11.1.6 + version: 11.1.6(rollup@4.21.1)(tslib@2.7.0)(typescript@5.5.4) + rollup: + specifier: ^4.9.6 + version: 4.21.1 + tslib: + specifier: ^2.6.2 + version: 2.7.0 + typescript: + specifier: ^5.3.3 + version: 5.5.4 + +packages: + + '@rollup/plugin-typescript@11.1.6': + resolution: {integrity: sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0||^4.0.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + + '@rollup/pluginutils@5.1.0': + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.21.1': + resolution: {integrity: sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.21.1': + resolution: {integrity: sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.21.1': + resolution: {integrity: sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.21.1': + resolution: {integrity: sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.21.1': + resolution: {integrity: sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.21.1': + resolution: {integrity: sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.21.1': + resolution: {integrity: sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.21.1': + resolution: {integrity: sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': + resolution: {integrity: sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.21.1': + resolution: {integrity: sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.21.1': + resolution: {integrity: sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.21.1': + resolution: {integrity: sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.21.1': + resolution: {integrity: sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.21.1': + resolution: {integrity: sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.21.1': + resolution: {integrity: sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.21.1': + resolution: {integrity: sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==} + cpu: [x64] + os: [win32] + + '@tauri-apps/api@2.0.0-rc.3': + resolution: {integrity: sha512-k1erUfnoOFJwL5VNFZz0BQZ2agNstG7CNOjwpdWMl1vOaVuSn4DhJtXB0Deh9lZaaDlfrykKOyZs9c3XXpMi5Q==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + rollup@4.21.1: + resolution: {integrity: sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + +snapshots: + + '@rollup/plugin-typescript@11.1.6(rollup@4.21.1)(tslib@2.7.0)(typescript@5.5.4)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.21.1) + resolve: 1.22.8 + typescript: 5.5.4 + optionalDependencies: + rollup: 4.21.1 + tslib: 2.7.0 + + '@rollup/pluginutils@5.1.0(rollup@4.21.1)': + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 4.21.1 + + '@rollup/rollup-android-arm-eabi@4.21.1': + optional: true + + '@rollup/rollup-android-arm64@4.21.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.21.1': + optional: true + + '@rollup/rollup-darwin-x64@4.21.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.21.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.21.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.21.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.21.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.21.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.21.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.21.1': + optional: true + + '@tauri-apps/api@2.0.0-rc.3': {} + + '@types/estree@1.0.5': {} + + estree-walker@2.0.2: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + path-parse@1.0.7: {} + + picomatch@2.3.1: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + rollup@4.21.1: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.21.1 + '@rollup/rollup-android-arm64': 4.21.1 + '@rollup/rollup-darwin-arm64': 4.21.1 + '@rollup/rollup-darwin-x64': 4.21.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.1 + '@rollup/rollup-linux-arm-musleabihf': 4.21.1 + '@rollup/rollup-linux-arm64-gnu': 4.21.1 + '@rollup/rollup-linux-arm64-musl': 4.21.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.1 + '@rollup/rollup-linux-riscv64-gnu': 4.21.1 + '@rollup/rollup-linux-s390x-gnu': 4.21.1 + '@rollup/rollup-linux-x64-gnu': 4.21.1 + '@rollup/rollup-linux-x64-musl': 4.21.1 + '@rollup/rollup-win32-arm64-msvc': 4.21.1 + '@rollup/rollup-win32-ia32-msvc': 4.21.1 + '@rollup/rollup-win32-x64-msvc': 4.21.1 + fsevents: 2.3.3 + + supports-preserve-symlinks-flag@1.0.0: {} + + tslib@2.7.0: {} + + typescript@5.5.4: {} diff --git a/src/commands.rs b/src/commands.rs index 97df025..a1415b2 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,4 +1,6 @@ -use tauri; +use tauri::{LogicalPosition, Manager, Result, Runtime, WebviewWindow}; + +use crate::WebviewWindowExt; #[tauri::command] pub async fn show_snap_overlay() { @@ -19,3 +21,25 @@ pub async fn show_snap_overlay() { enigo.key_click(Key::Alt); } } + +#[tauri::command] +pub async fn set_window_buttons_inset( + window: WebviewWindow, + inset: Option>, + target_label: Option, +) -> Result<()> { + #[cfg(target_os = "macos")] + { + let target = match target_label { + Some(label) => window + .get_webview_window(&label) + .ok_or_else(|| tauri::Error::WindowNotFound)?, + None => window, + }; + + target.set_window_buttons_inset(inset) + } + + #[cfg(not(target_os = "macos"))] + "This command is only supported on macOS." +} diff --git a/src/lib.rs b/src/lib.rs index 0d93c72..2d51ff9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,8 @@ use std::collections::HashMap; use std::sync::Arc; use macos::nswindow_delegates; -use parking_lot::RwLock; use tauri::plugin::{Builder, TauriPlugin}; -use tauri::{Emitter, Error, Listener, LogicalPosition, Manager, Runtime, WebviewWindow}; +use tauri::{Emitter, Listener, LogicalPosition, Manager, Runtime, WebviewWindow}; #[cfg(target_os = "macos")] #[macro_use] @@ -15,6 +14,7 @@ mod commands; #[cfg(target_os = "macos")] mod macos; +#[cfg(target_os = "macos")] #[repr(u32)] pub enum NSWindowLevel { NSNormalWindowLevel = 0, @@ -26,6 +26,7 @@ pub enum NSWindowLevel { NSScreenSaverWindowLevel = 1000, } +#[cfg(target_os = "macos")] impl From for NSWindowLevel { fn from(s: String) -> Self { match s.as_str() { @@ -47,23 +48,23 @@ impl From for NSWindowLevel { /// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the decorum APIs. pub trait WebviewWindowExt { - fn create_overlay_titlebar(&self) -> Result<&WebviewWindow, Error>; + fn create_overlay_titlebar(&self) -> tauri::Result<()>; + #[cfg(target_os = "macos")] - fn set_traffic_lights_inset( - &self, - inset: Option>, - ) -> Result<&WebviewWindow, Error>; + fn set_window_buttons_inset(&self, options: Option>) -> tauri::Result<()>; + #[cfg(target_os = "macos")] - fn make_transparent(&self) -> Result<&WebviewWindow, Error>; + fn make_transparent(&self) -> tauri::Result<()>; + #[cfg(target_os = "macos")] - fn set_window_level(&self, level: NSWindowLevel) -> Result<&WebviewWindow, Error>; + fn set_window_level(&self, level: NSWindowLevel) -> tauri::Result<()>; } -impl<'a> WebviewWindowExt for WebviewWindow { +impl WebviewWindowExt for WebviewWindow { /// Create a custom titlebar overlay. /// This will remove the default titlebar and create a draggable area for the titlebar. /// On Windows, it will also create custom window controls. - fn create_overlay_titlebar(&self) -> Result<&WebviewWindow, Error> { + fn create_overlay_titlebar(&self) -> tauri::Result<()> { #[cfg(target_os = "windows")] self.set_decorations(false)?; @@ -119,93 +120,116 @@ impl<'a> WebviewWindowExt for WebviewWindow { } }); - Ok(self) + Ok(()) + } + + /// Set the window background to transparent. + /// This helper function is different from Tauri's default + /// as it doesn't use the `transparent` flag or macOS Private APIs. + #[cfg(target_os = "macos")] + fn make_transparent(&self) -> tauri::Result<()> { + use cocoa::{ + base::{id, nil}, + foundation::NSString, + }; + + // Make webview background transparent + self.with_webview(|webview| unsafe { + let id = webview.inner(); + let no: id = msg_send![class!(NSNumber), numberWithBool:0]; + let _: id = + msg_send![id, setValue:no forKey: NSString::alloc(nil).init_str("drawsBackground")]; + })?; + + Ok(()) } /// Set the inset of the traffic lights. /// This will move the traffic lights to the specified position. /// This is only available on macOS. + /// TODO: Also Implement for Windows 11 (>=22H2) #[cfg(target_os = "macos")] - fn set_traffic_lights_inset( + fn set_window_buttons_inset( &self, - inset: Option>, - ) -> Result<&WebviewWindow, Error> { - let insets_state = &self.state::(); - let mut insets_map = insets_state.0.write(); + inset_option: Option>, + ) -> tauri::Result<()> { + let styles_state = &self.state::(); + let mut styles_map = styles_state.0.write(); let window_label = self.label().to_string(); - match inset { + match inset_option { Some(inset) => { - if insets_map.insert(window_label, inset.clone()).is_none() { + if styles_map + .insert(window_label, Some(inset.clone())) + .is_none() + { + let c_insets_map = styles_map.clone(); + let c_win = self.clone(); + self.on_window_event(move |event| match event { - tauri::WindowEvent::ThemeChanged(_) => { - // TODO: Update + tauri::WindowEvent::ThemeChanged(..) => { + if c_insets_map.contains_key(c_win.label()) { + let _ = ensure_main_thread(&c_win, move |win| { + macos::update_window_controls_inset(&win.as_ref().window()); + Ok(()) + }); + } } _ => (), }); } - - ensure_main_thread(self, move |win| { - // macos::update_traffic_lights_inset(win); - Ok(win) - }) } None => { - insets_map.remove(&window_label); - Ok(self) + styles_map.remove(&window_label); } } - } - /// Set the window background to transparent. - /// This helper function is different from Tauri's default - /// as it doesn't use the `transparent` flag or macOS Private APIs. - #[cfg(target_os = "macos")] - fn make_transparent(&self) -> Result<&WebviewWindow, Error> { - use cocoa::{ - base::{id, nil}, - foundation::NSString, - }; + ensure_main_thread(self, move |win| { + let inset = inset_option.unwrap_or(macos::DEFAULT_TRAFFIC_LIGHTS_INSET); - // Make webview background transparent - self.with_webview(|webview| unsafe { - let id = webview.inner(); - let no: id = msg_send![class!(NSNumber), numberWithBool:0]; - let _: id = - msg_send![id, setValue:no forKey: NSString::alloc(nil).init_str("drawsBackground")]; - })?; + macos::draw_window_controls( + macos::nswindow_delegates::UnsafeWindowHandle( + win.ns_window().expect("Failed to create window handle"), + ), + inset.x, + inset.y, + ); - Ok(self) + Ok(()) + }) } - /// Set the window level. + /// Set the window level. /// This will set the window level to the specified value. /// NSWindowLevel values can be found [here](https://developer.apple.com/documentation/appkit/NSWindowLevel?language=objc). /// This is only available on macOS. #[cfg(target_os = "macos")] - fn set_window_level(&self, level: NSWindowLevel) -> Result<&WebviewWindow, Error> { - ensure_main_thread(self, move |win| { + fn set_window_level(&self, level: NSWindowLevel) -> tauri::Result<()> { + ensure_main_thread(self, move |win| unsafe { let ns_win = win.ns_window()? as cocoa::base::id; - unsafe { - let _: () = msg_send![ns_win, setLevel: level]; - } - Ok(win) + let _: () = msg_send![ns_win, setLevel: level]; + Ok(()) }) } } -#[cfg(target_os = "macos")] -struct TrafficLightsInsetsState(Arc>>>); +#[cfg(not(target_os = "linux"))] +struct WindowButtonsInsetsState( + Arc>>>>, +); pub fn init() -> TauriPlugin { let mut builder = Builder::new("decorum") - .invoke_handler(tauri::generate_handler![commands::show_snap_overlay]) + .invoke_handler(tauri::generate_handler![ + commands::set_window_buttons_inset, + commands::show_snap_overlay, + ]) .setup(move |app, _api| { - #[cfg(target_os = "macos")] - app.manage(TrafficLightsInsetsState(Arc::new(RwLock::new( - HashMap::new(), - )))); + #[cfg(not(target_os = "linux"))] + app.manage(WindowButtonsInsetsState(Arc::new( + parking_lot::RwLock::new(HashMap::new()), + ))); Ok(()) }) @@ -228,32 +252,18 @@ pub fn init() -> TauriPlugin { } #[cfg(target_os = "macos")] -fn is_main_thread() -> bool { - std::thread::current().name() == Some("main") -} - -#[cfg(target_os = "macos")] -fn ensure_main_thread( - win: &WebviewWindow, +pub(crate) fn ensure_main_thread( + win: &WebviewWindow, main_action: F, -) -> Result<&WebviewWindow, tauri::Error> +) -> tauri::Result<()> where - F: FnOnce(&WebviewWindow) -> Result<&WebviewWindow, Error> + Send + 'static, + F: FnOnce(&WebviewWindow) -> tauri::Result<()> + Send + 'static, { - match is_main_thread() { - true => { - main_action(win)?; - Ok(win) - } + match std::thread::current().name() == Some("main") { + true => main_action(win), false => { - let win2 = win.clone(); - - match win.run_on_main_thread(move || { - main_action(&win2).unwrap(); - }) { - Ok(_) => Ok(win), - Err(e) => Err(e), - } + let c_win = win.clone(); + win.run_on_main_thread(move || main_action(&c_win).unwrap()) } } } diff --git a/src/macos/mod.rs b/src/macos/mod.rs index 54674f0..489d0ea 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,36 +1,36 @@ use nswindow_delegates::UnsafeWindowHandle; -// use objc::{msg_send, sel, sel_impl}; -// use rand::{distributions::Alphanumeric, Rng}; use tauri::{LogicalPosition, Manager, Runtime, Window}; -use crate::TrafficLightsInsetsState; +use crate::WindowButtonsInsetsState; pub mod nswindow_delegates; -const DEFAULT_TRAFFIC_LIGHTS_INSET: LogicalPosition = LogicalPosition::new(12.0, 16.0); +pub const DEFAULT_TRAFFIC_LIGHTS_INSET: LogicalPosition = LogicalPosition::new(10.0, 15.0); -pub fn update_traffic_lights_inset(window: &Window) { - let insets_state = &window.state::(); - let insets_map = insets_state.0.read(); - let inset = insets_map - .get(&window.label().to_string()) - .unwrap_or(&DEFAULT_TRAFFIC_LIGHTS_INSET); +pub fn update_window_controls_inset(window: &Window) { + let styles_state = window.state::(); + let styles_map_rw = styles_state.0.try_read(); + if let Some(map) = styles_map_rw { + if let Some(inset_option) = map.get(&window.label().to_string()) { + let inset = inset_option.unwrap_or(DEFAULT_TRAFFIC_LIGHTS_INSET); - position_traffic_lights( - UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), - inset.x, - inset.y, - ); + draw_window_controls( + UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), + inset.x, + inset.y, + ); + } + } } -fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { +pub fn draw_window_controls(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { use cocoa::appkit::{NSView, NSWindow, NSWindowButton}; use cocoa::foundation::NSRect; + let ns_window = ns_window_handle.0 as cocoa::base::id; unsafe { let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let miniaturize = - ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); + let minimize = ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); let zoom = ns_window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); let title_bar_container_view = close.superview().superview(); @@ -44,14 +44,13 @@ fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) title_bar_rect.origin.y = NSView::frame(ns_window).size.height - title_bar_frame_height; let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; - let window_buttons = vec![close, miniaturize, zoom]; - let space_between = 20.0; // Fixed space between buttons + let window_buttons = vec![close, minimize, zoom]; + let space_between = NSView::frame(minimize).origin.x - NSView::frame(close).origin.x; let vertical_offset = 4.0; // Adjust this value to push buttons down for (i, button) in window_buttons.into_iter().enumerate() { let mut rect: NSRect = NSView::frame(button); rect.origin.x = x + (i as f64 * space_between); - // Adjust vertical positioning rect.origin.y = ((title_bar_frame_height - button_height) / 2.0) - vertical_offset; button.setFrameOrigin(rect.origin); } diff --git a/src/macos/nswindow_delegates.rs b/src/macos/nswindow_delegates.rs index d7c509c..67f0aa8 100644 --- a/src/macos/nswindow_delegates.rs +++ b/src/macos/nswindow_delegates.rs @@ -1,6 +1,5 @@ /// -/// Credit to @haasal, @charrondev and Hoppscotch -/// This is also similar to how it is implemented in Zed.dev editor +/// Credit to @haasal, @charrondev, Hoppscotch app, Electron, Zed Editor /// /// https://github.com/haasal /// https://gist.github.com/charrondev @@ -9,6 +8,7 @@ /// (Issue) https://github.com/tauri-apps/tauri/issues/4789 /// (Gist) https://gist.github.com/charrondev/43150e940bd2771b1ea88256d491c7a9 /// (Hoppscotch) https://github.com/hoppscotch/hoppscotch/blob/286fcd2bb08a84f027b10308d1e18da368f95ebf/packages/hoppscotch-selfhost-desktop/src-tauri/src/mac/window.rs +/// (Electron) https://github.com/electron/electron/blob/38512efd25a159ddc64a54c22ef9eb6dd60064ec/shell/browser/native_window_mac.mm#L1454 /// use objc::{msg_send, sel, sel_impl}; use rand::{distributions::Alphanumeric, Rng}; @@ -30,15 +30,10 @@ pub fn setup(window: Window) { use objc::runtime::{Object, Sel}; use std::ffi::c_void; - use crate::macos::update_traffic_lights_inset; + use crate::macos::update_window_controls_inset; // Do the initial positioning - // position_traffic_lights( - // UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), - // WINDOW_CONTROL_PAD_X, - // WINDOW_CONTROL_PAD_Y, - // ); - // update_traffic_lights_inset(&window); + update_window_controls_inset(&window); // Ensure they stay in place while resizing the window. fn with_window_state) -> T, T>( @@ -75,7 +70,7 @@ pub fn setup(window: Window) { extern "C" fn on_window_did_resize(this: &Object, _cmd: Sel, notification: id) { unsafe { with_window_state(&*this, |state: &mut WindowState| { - update_traffic_lights_inset(&state.window); + update_window_controls_inset(&state.window); }); let super_del: id = *this.get_ivar("super_delegate"); @@ -201,7 +196,7 @@ pub fn setup(window: Window) { .emit("did-exit-fullscreen", ()) .expect("Failed to emit event"); - update_traffic_lights_inset(&state.window); + update_window_controls_inset(&state.window); }); let super_del: id = *this.get_ivar("super_delegate"); @@ -259,7 +254,6 @@ pub fn setup(window: Window) { } } - // Are we deallocing this properly ? (I miss safe Rust :( ) let window_label = window.label().to_string(); let app_state = WindowState { window }; @@ -272,7 +266,7 @@ pub fn setup(window: Window) { // We need to ensure we have a unique delegate name, otherwise we will panic while trying to create a duplicate // delegate with the same name. - let delegate_name = format!("windowDelegate_{}_{}", window_label, random_str); + let delegate_name = format!("windowDelegate_decorum_{}_{}", window_label, random_str); ns_win.setDelegate_(cocoa::delegate!(&delegate_name, { window: id = ns_win, diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 1e497e6..0000000 --- a/yarn.lock +++ /dev/null @@ -1,198 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@rollup/plugin-typescript@^11.1.6": - version "11.1.6" - resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz#724237d5ec12609ec01429f619d2a3e7d4d1b22b" - integrity sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA== - dependencies: - "@rollup/pluginutils" "^5.1.0" - resolve "^1.22.1" - -"@rollup/pluginutils@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" - integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^2.0.2" - picomatch "^2.3.1" - -"@rollup/rollup-android-arm-eabi@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz#1a32112822660ee104c5dd3a7c595e26100d4c2d" - integrity sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ== - -"@rollup/rollup-android-arm64@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz#5aeef206d65ff4db423f3a93f71af91b28662c5b" - integrity sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw== - -"@rollup/rollup-darwin-arm64@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz#6b66aaf003c70454c292cd5f0236ebdc6ffbdf1a" - integrity sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw== - -"@rollup/rollup-darwin-x64@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz#f64fc51ed12b19f883131ccbcea59fc68cbd6c0b" - integrity sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ== - -"@rollup/rollup-linux-arm-gnueabihf@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz#1a7641111be67c10111f7122d1e375d1226cbf14" - integrity sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A== - -"@rollup/rollup-linux-arm-musleabihf@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz#c93fd632923e0fee25aacd2ae414288d0b7455bb" - integrity sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg== - -"@rollup/rollup-linux-arm64-gnu@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz#fa531425dd21d058a630947527b4612d9d0b4a4a" - integrity sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A== - -"@rollup/rollup-linux-arm64-musl@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz#8acc16f095ceea5854caf7b07e73f7d1802ac5af" - integrity sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA== - -"@rollup/rollup-linux-powerpc64le-gnu@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz#94e69a8499b5cf368911b83a44bb230782aeb571" - integrity sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ== - -"@rollup/rollup-linux-riscv64-gnu@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz#7ef1c781c7e59e85a6ce261cc95d7f1e0b56db0f" - integrity sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg== - -"@rollup/rollup-linux-s390x-gnu@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz#f15775841c3232fca9b78cd25a7a0512c694b354" - integrity sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g== - -"@rollup/rollup-linux-x64-gnu@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz#b521d271798d037ad70c9f85dd97d25f8a52e811" - integrity sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ== - -"@rollup/rollup-linux-x64-musl@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz#9254019cc4baac35800991315d133cc9fd1bf385" - integrity sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q== - -"@rollup/rollup-win32-arm64-msvc@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz#27f65a89f6f52ee9426ec11e3571038e4671790f" - integrity sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA== - -"@rollup/rollup-win32-ia32-msvc@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz#a2fbf8246ed0bb014f078ca34ae6b377a90cb411" - integrity sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ== - -"@rollup/rollup-win32-x64-msvc@4.17.2": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz#5a2d08b81e8064b34242d5cc9973ef8dd1e60503" - integrity sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w== - -"@tauri-apps/api@>=2.0.0-beta.24": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@tauri-apps/api/-/api-2.0.0-beta.15.tgz#41d5fbeaccf3926b6f9f3f9fb5137ba2e272e5c1" - integrity sha512-H9w6iISmR+NvH4XuyCZB4zDN10tf9RFt6i/9JHEjaRhAowdAaJ+oiXq/3kedizNClHMtbTQ5j0oqDVPkZDAI8g== - -"@types/estree@1.0.5", "@types/estree@^1.0.0": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -estree-walker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -hasown@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -resolve@^1.22.1: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -rollup@^4.9.6: - version "4.17.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.17.2.tgz#26d1785d0144122277fdb20ab3a24729ae68301f" - integrity sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ== - dependencies: - "@types/estree" "1.0.5" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.17.2" - "@rollup/rollup-android-arm64" "4.17.2" - "@rollup/rollup-darwin-arm64" "4.17.2" - "@rollup/rollup-darwin-x64" "4.17.2" - "@rollup/rollup-linux-arm-gnueabihf" "4.17.2" - "@rollup/rollup-linux-arm-musleabihf" "4.17.2" - "@rollup/rollup-linux-arm64-gnu" "4.17.2" - "@rollup/rollup-linux-arm64-musl" "4.17.2" - "@rollup/rollup-linux-powerpc64le-gnu" "4.17.2" - "@rollup/rollup-linux-riscv64-gnu" "4.17.2" - "@rollup/rollup-linux-s390x-gnu" "4.17.2" - "@rollup/rollup-linux-x64-gnu" "4.17.2" - "@rollup/rollup-linux-x64-musl" "4.17.2" - "@rollup/rollup-win32-arm64-msvc" "4.17.2" - "@rollup/rollup-win32-ia32-msvc" "4.17.2" - "@rollup/rollup-win32-x64-msvc" "4.17.2" - fsevents "~2.3.2" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -typescript@^5.3.3: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== From 8425b9a842b07befc407dc50471cc4ea2d454754 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:13:02 +0330 Subject: [PATCH 05/14] Update usage in README.md --- README.md | 22 ++++++++++++------- examples/tauri-app/src-tauri/src/main.rs | 4 ++++ permissions/autogenerated/reference.md | 28 +----------------------- permissions/schemas/schema.json | 14 ------------ 4 files changed, 19 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 1eb16f9..ce2d9c9 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ You'll need to set these for your window in `src-tauri/capabilities/default.json "core:window:allow-start-dragging", "core:window:allow-toggle-maximize", "decorum:allow-show-snap-overlay", +"decorum:allow-set-window-buttons-inset", ``` And ensure the `withGlobalTauri` in your `tauri.conf.json` is set to `true`. @@ -44,7 +45,7 @@ And ensure the `withGlobalTauri` in your `tauri.conf.json` is set to `true`. ```rust use tauri::Manager; -use tauri_plugin_decorum::WebviewWindowExt; // adds helper methods to WebviewWindow +use tauri_plugin_decorum::{WebviewWindowExt, NSWindowLevel}; fn main() { tauri::Builder::default() @@ -58,15 +59,20 @@ fn main() { // Some macOS-specific helpers #[cfg(target_os = "macos")] { - // Set a custom inset to the traffic lights - main_window.set_traffic_lights_inset(12.0, 16.0).unwrap(); - - // Make window transparent without privateApi - main_window.make_transparent().unwrap() - + use tauri_plugin_decorum::NSWindowLevel; + // Set window level // NSWindowLevel: https://developer.apple.com/documentation/appkit/nswindowlevel - main_window.set_window_level(25).unwrap() + let _ = main_window.set_window_level(NSWindowLevel::NSStatusWindowLevel); + + // Set a custom inset to the traffic lights + let _ = main_window.set_window_buttons_inset(Some(LogicalPosition::new(12.0, 16.0))); + + // Applies transparency to the webview. + // Note that this still uses internal/private APIs. + // This differs from Tauri's implementation as it doesn't make the window itself transparent + // Allowing for shadows to be enabled without artifacts or large performance hits. + let _ = main_window.apply_transparency(); } Ok(()) diff --git a/examples/tauri-app/src-tauri/src/main.rs b/examples/tauri-app/src-tauri/src/main.rs index 036e1a0..d671e76 100644 --- a/examples/tauri-app/src-tauri/src/main.rs +++ b/examples/tauri-app/src-tauri/src/main.rs @@ -16,10 +16,14 @@ fn main() { #[cfg(target_os = "macos")] { + use tauri_plugin_decorum::NSWindowLevel; + let _ = main_window.make_transparent(); let _ = main_window.create_overlay_titlebar(); let _ = main_window.set_window_buttons_inset(Some(LogicalPosition::new(15.0, 25.0))); + + let _ = main_window.set_window_level(NSWindowLevel::NSStatusWindowLevel); } Ok(()) diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md index 53abc37..d9c8b72 100644 --- a/permissions/autogenerated/reference.md +++ b/permissions/autogenerated/reference.md @@ -1,5 +1,5 @@ -### Permission Table +## Permission Table @@ -8,32 +8,6 @@ - - - - - - - - - -
- -`decorum:allow-set-window-buttons-inset` - - - -Enables the set-window-buttons-inset command without any pre-configured scope. - -
- -`decorum:deny-set-window-buttons-inset` - - - -Denies the set-window-buttons-inset command without any pre-configured scope. - -
diff --git a/permissions/schemas/schema.json b/permissions/schemas/schema.json index 7b4fcc2..e9eeae6 100644 --- a/permissions/schemas/schema.json +++ b/permissions/schemas/schema.json @@ -294,20 +294,6 @@ "PermissionKind": { "type": "string", "oneOf": [ - { - "description": "allow-set-window-buttons-inset -> Enables the set-window-buttons-inset command without any pre-configured scope.", - "type": "string", - "enum": [ - "allow-set-window-buttons-inset" - ] - }, - { - "description": "deny-set-window-buttons-inset -> Denies the set-window-buttons-inset command without any pre-configured scope.", - "type": "string", - "enum": [ - "deny-set-window-buttons-inset" - ] - }, { "description": "allow-set-window-buttons-inset -> Enables the set_window_buttons_inset command without any pre-configured scope.", "type": "string", From d0a0ef5c6e513a9be74c1483a77907e4189d60e2 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Fri, 30 Aug 2024 03:02:19 +0330 Subject: [PATCH 06/14] from u32 for NSWindowLevel, update example --- examples/tauri-app/src-tauri/src/main.rs | 4 ++-- src/lib.rs | 28 ++++++++++-------------- src/macos/mod.rs | 16 +++++++++----- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/examples/tauri-app/src-tauri/src/main.rs b/examples/tauri-app/src-tauri/src/main.rs index d671e76..91545a5 100644 --- a/examples/tauri-app/src-tauri/src/main.rs +++ b/examples/tauri-app/src-tauri/src/main.rs @@ -21,9 +21,9 @@ fn main() { let _ = main_window.make_transparent(); let _ = main_window.create_overlay_titlebar(); let _ = - main_window.set_window_buttons_inset(Some(LogicalPosition::new(15.0, 25.0))); + main_window.set_window_buttons_inset(Some(LogicalPosition::new(15.0, 20.0))); - let _ = main_window.set_window_level(NSWindowLevel::NSStatusWindowLevel); + let _ = main_window.set_window_level(NSWindowLevel::NSNormalWindowLevel); } Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 2d51ff9..9969686 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,21 +27,17 @@ pub enum NSWindowLevel { } #[cfg(target_os = "macos")] -impl From for NSWindowLevel { - fn from(s: String) -> Self { - match s.as_str() { - "NSNormalWindowLevel" => NSWindowLevel::NSNormalWindowLevel, - "NSFloatingWindowLevel" => NSWindowLevel::NSFloatingOrSubmenuOrTornOffMenuWindowLevel, - "NSSubmenuWindowLevel" => NSWindowLevel::NSFloatingOrSubmenuOrTornOffMenuWindowLevel, - "NSTornOffMenuWindowLevel" => { - NSWindowLevel::NSFloatingOrSubmenuOrTornOffMenuWindowLevel - } - "NSMainMenuWindowLevel" => NSWindowLevel::NSMainMenuWindowLevel, - "NSStatusWindowLevel" => NSWindowLevel::NSStatusWindowLevel, - "NSModalPanelWindowLevel" => NSWindowLevel::NSModalPanelWindowLevel, - "NSPopUpMenuWindowLevel" => NSWindowLevel::NSPopUpMenuWindowLevel, - "NSScreenSaverWindowLevel" => NSWindowLevel::NSScreenSaverWindowLevel, - _ => panic!("Unknown NSWindowLevel string: {}", s), +impl From for NSWindowLevel { + fn from(n: u32) -> Self { + match n { + 0 => NSWindowLevel::NSNormalWindowLevel, + 3 => NSWindowLevel::NSFloatingOrSubmenuOrTornOffMenuWindowLevel, + 8 => NSWindowLevel::NSModalPanelWindowLevel, + 24 => NSWindowLevel::NSMainMenuWindowLevel, + 25 => NSWindowLevel::NSStatusWindowLevel, + 101 => NSWindowLevel::NSPopUpMenuWindowLevel, + 1000 => NSWindowLevel::NSScreenSaverWindowLevel, + _ => NSWindowLevel::NSNormalWindowLevel, } } } @@ -188,7 +184,7 @@ impl WebviewWindowExt for WebviewWindow { ensure_main_thread(self, move |win| { let inset = inset_option.unwrap_or(macos::DEFAULT_TRAFFIC_LIGHTS_INSET); - macos::draw_window_controls( + macos::position_window_controls( macos::nswindow_delegates::UnsafeWindowHandle( win.ns_window().expect("Failed to create window handle"), ), diff --git a/src/macos/mod.rs b/src/macos/mod.rs index 489d0ea..ce31f6a 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,3 +1,4 @@ +use cocoa::appkit::NSToolbar; use nswindow_delegates::UnsafeWindowHandle; use tauri::{LogicalPosition, Manager, Runtime, Window}; @@ -14,7 +15,7 @@ pub fn update_window_controls_inset(window: &Window) { if let Some(inset_option) = map.get(&window.label().to_string()) { let inset = inset_option.unwrap_or(DEFAULT_TRAFFIC_LIGHTS_INSET); - draw_window_controls( + position_window_controls( UnsafeWindowHandle(window.ns_window().expect("Failed to create window handle")), inset.x, inset.y, @@ -23,11 +24,16 @@ pub fn update_window_controls_inset(window: &Window) { } } -pub fn draw_window_controls(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { - use cocoa::appkit::{NSView, NSWindow, NSWindowButton}; - use cocoa::foundation::NSRect; +// TODO: Respect RTL display language +// https://developer.apple.com/documentation/appkit/nsapplication/1428556-userinterfacelayoutdirection?language=objc +pub fn position_window_controls(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { + use cocoa::{ + appkit::{NSView, NSWindow, NSWindowButton}, + base::id, + foundation::NSRect, + }; - let ns_window = ns_window_handle.0 as cocoa::base::id; + let ns_window = ns_window_handle.0 as id; unsafe { let close = ns_window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); let minimize = ns_window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); From 3d3da161db00bb25b5d96d1c72640f276ac87dea Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 31 Aug 2024 03:58:36 +0330 Subject: [PATCH 07/14] Add more documentation --- examples/tauri-app/src/styles.css | 2 +- src/lib.rs | 101 +++++++++++++++++------------- 2 files changed, 57 insertions(+), 46 deletions(-) diff --git a/examples/tauri-app/src/styles.css b/examples/tauri-app/src/styles.css index 3df6665..d1bdf81 100644 --- a/examples/tauri-app/src/styles.css +++ b/examples/tauri-app/src/styles.css @@ -91,7 +91,7 @@ button { @media (prefers-color-scheme: dark) { :root { color: #f6f6f6; - background-image: linear-gradient(180deg, #350042 0%, #1f003b 100%); + /* background-image: linear-gradient(180deg, #350042 0%, #1f003b 100%); */ background-size: cover; } diff --git a/src/lib.rs b/src/lib.rs index 9969686..bfbcb31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,8 @@ use std::collections::HashMap; use std::sync::Arc; -use macos::nswindow_delegates; use tauri::plugin::{Builder, TauriPlugin}; -use tauri::{Emitter, Listener, LogicalPosition, Manager, Runtime, WebviewWindow}; +use tauri::{Emitter, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; #[cfg(target_os = "macos")] #[macro_use] @@ -44,23 +43,26 @@ impl From for NSWindowLevel { /// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the decorum APIs. pub trait WebviewWindowExt { - fn create_overlay_titlebar(&self) -> tauri::Result<()>; + fn create_overlay_titlebar(&self) -> Result<()>; #[cfg(target_os = "macos")] - fn set_window_buttons_inset(&self, options: Option>) -> tauri::Result<()>; + fn set_window_buttons_inset(&self, options: Option>) -> Result<()>; #[cfg(target_os = "macos")] - fn make_transparent(&self) -> tauri::Result<()>; + fn make_transparent(&self) -> Result<()>; #[cfg(target_os = "macos")] - fn set_window_level(&self, level: NSWindowLevel) -> tauri::Result<()>; + fn set_window_level(&self, level: NSWindowLevel) -> Result<()>; } impl WebviewWindowExt for WebviewWindow { /// Create a custom titlebar overlay. /// This will remove the default titlebar and create a draggable area for the titlebar. - /// On Windows, it will also create custom window controls. - fn create_overlay_titlebar(&self) -> tauri::Result<()> { + /// + /// ## Platform-specific: + /// + /// - **Windows:** On Windows, it will also create custom window controls. + fn create_overlay_titlebar(&self) -> Result<()> { #[cfg(target_os = "windows")] self.set_decorations(false)?; @@ -119,36 +121,14 @@ impl WebviewWindowExt for WebviewWindow { Ok(()) } - /// Set the window background to transparent. - /// This helper function is different from Tauri's default - /// as it doesn't use the `transparent` flag or macOS Private APIs. + /// Sets the window controls (Traffic lights) inset + /// + /// ## Platform-specific: + /// + /// - **macOS:** Only supported on macOS. + // TODO: Also Implement for Windows 11 (>=22H2) #[cfg(target_os = "macos")] - fn make_transparent(&self) -> tauri::Result<()> { - use cocoa::{ - base::{id, nil}, - foundation::NSString, - }; - - // Make webview background transparent - self.with_webview(|webview| unsafe { - let id = webview.inner(); - let no: id = msg_send![class!(NSNumber), numberWithBool:0]; - let _: id = - msg_send![id, setValue:no forKey: NSString::alloc(nil).init_str("drawsBackground")]; - })?; - - Ok(()) - } - - /// Set the inset of the traffic lights. - /// This will move the traffic lights to the specified position. - /// This is only available on macOS. - /// TODO: Also Implement for Windows 11 (>=22H2) - #[cfg(target_os = "macos")] - fn set_window_buttons_inset( - &self, - inset_option: Option>, - ) -> tauri::Result<()> { + fn set_window_buttons_inset(&self, inset_option: Option>) -> Result<()> { let styles_state = &self.state::(); let mut styles_map = styles_state.0.write(); @@ -196,12 +176,43 @@ impl WebviewWindowExt for WebviewWindow { }) } + /// Makes the background of the WKWebView layer transparent. + /// This differs from Tauri's implementation as it does not change the window background which causes performance performance issues and artifacts when shadows are enabled on the window. + /// Use Tauri's implementation to make the window itself transparent. + /// + /// ## Platform-specific: + /// + /// - **macOS:** Only supported on macOS. + /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + #[cfg(target_os = "macos")] + fn make_transparent(&self) -> Result<()> { + use cocoa::{ + base::{id, nil}, + foundation::NSString, + }; + + self.with_webview(|webview| unsafe { + let wkwebview = webview.inner(); + // `NO` is disallowed, use [NSNumber numberWithBool:NO] + let no: id = msg_send![class!(NSNumber), numberWithBool:0]; + // Deprecated since OS X 10.14 + // [https://developer.apple.com/documentation/webkit/webview/1408486-drawsbackground] + let _: id = + msg_send![wkwebview, setValue:no forKey: NSString::alloc(nil).init_str("drawsBackground")]; + })?; + + Ok(()) + } + /// Set the window level. /// This will set the window level to the specified value. - /// NSWindowLevel values can be found [here](https://developer.apple.com/documentation/appkit/NSWindowLevel?language=objc). - /// This is only available on macOS. + /// NSWindowLevel values can be found [here](https://developer.apple.com/documentation/appkit/NSWindowLevel). + /// + /// ## Platform-specific: + /// + /// - **macOS:** Only supported on macOS. #[cfg(target_os = "macos")] - fn set_window_level(&self, level: NSWindowLevel) -> tauri::Result<()> { + fn set_window_level(&self, level: NSWindowLevel) -> Result<()> { ensure_main_thread(self, move |win| unsafe { let ns_win = win.ns_window()? as cocoa::base::id; let _: () = msg_send![ns_win, setLevel: level]; @@ -210,7 +221,7 @@ impl WebviewWindowExt for WebviewWindow { } } -#[cfg(not(target_os = "linux"))] +#[cfg(any(target_os = "macos", target_os = "windows"))] struct WindowButtonsInsetsState( Arc>>>>, ); @@ -222,7 +233,7 @@ pub fn init() -> TauriPlugin { commands::show_snap_overlay, ]) .setup(move |app, _api| { - #[cfg(not(target_os = "linux"))] + #[cfg(any(target_os = "macos", target_os = "windows"))] app.manage(WindowButtonsInsetsState(Arc::new( parking_lot::RwLock::new(HashMap::new()), ))); @@ -240,7 +251,7 @@ pub fn init() -> TauriPlugin { { builder = builder.on_window_ready(|window| { // TODO: Only setup if the inset is defined in the config. - nswindow_delegates::setup(window); + macos::nswindow_delegates::setup(window); }); } @@ -251,9 +262,9 @@ pub fn init() -> TauriPlugin { pub(crate) fn ensure_main_thread( win: &WebviewWindow, main_action: F, -) -> tauri::Result<()> +) -> Result<()> where - F: FnOnce(&WebviewWindow) -> tauri::Result<()> + Send + 'static, + F: FnOnce(&WebviewWindow) -> Result<()> + Send + 'static, { match std::thread::current().name() == Some("main") { true => main_action(win), From c179c33518f09a391931a631c9cfb2078889cd6b Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 31 Aug 2024 10:11:52 +0330 Subject: [PATCH 08/14] Fix command error --- src/commands.rs | 7 +++++-- src/lib.rs | 7 +++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index a1415b2..0bca148 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,4 +1,5 @@ -use tauri::{LogicalPosition, Manager, Result, Runtime, WebviewWindow}; +use anyhow::anyhow; +use tauri::{Error, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; use crate::WebviewWindowExt; @@ -41,5 +42,7 @@ pub async fn set_window_buttons_inset( } #[cfg(not(target_os = "macos"))] - "This command is only supported on macOS." + Err(Error::Anyhow(anyhow!( + "This command is only supported on macOS." + ))) } diff --git a/src/lib.rs b/src/lib.rs index bfbcb31..29263e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,9 @@ use std::collections::HashMap; use std::sync::Arc; +use anyhow::anyhow; use tauri::plugin::{Builder, TauriPlugin}; -use tauri::{Emitter, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; +use tauri::{Emitter, Error, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; #[cfg(target_os = "macos")] #[macro_use] @@ -199,9 +200,7 @@ impl WebviewWindowExt for WebviewWindow { // [https://developer.apple.com/documentation/webkit/webview/1408486-drawsbackground] let _: id = msg_send![wkwebview, setValue:no forKey: NSString::alloc(nil).init_str("drawsBackground")]; - })?; - - Ok(()) + }) } /// Set the window level. From 6090b46f5d05021aa95aace0c969d7f9e7799638 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 31 Aug 2024 12:54:19 +0330 Subject: [PATCH 09/14] (WIP) Introduce: Decorum Config --- Cargo.toml | 2 +- src/config.rs | 91 +++++++++++++++++++++++++++++++++ src/lib.rs | 64 ++++++++++++++++++----- src/macos/nswindow_delegates.rs | 22 ++++---- 4 files changed, 153 insertions(+), 26 deletions(-) create mode 100644 src/config.rs diff --git a/Cargo.toml b/Cargo.toml index bb6d620..838b381 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,12 +15,12 @@ repository = "https://github.com/clearlysid/tauri-plugin-decorum" tauri = { version = "2.0.0-rc" } serde = "1.0" anyhow = "1.0" +parking_lot = "0.12.3" [target.'cfg(target_os = "macos")'.dependencies] rand = "^0.8" cocoa = "0.26" objc = "0.2" -parking_lot = "0.12.3" [target.'cfg(target_os = "windows")'.dependencies] enigo = "0.1.3" diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..13da056 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,91 @@ +use serde::{Deserialize, Serialize}; + +/// +/// Configuration for windows in the application. +/// +/// Default JSON configuration: +/// ```json +/// { +/// "windows": [ +/// { +/// "label": "main", +/// "windowButtons": { +/// "insetX": 15.0, +/// "insetY": 20.0, +/// "supportRTL": true, +/// "hide": [] +/// }, +/// "transparentWebViews": true, +/// "createOverlayTitlebar": true +/// } +/// ] +/// } +/// ``` +/// +/// # Note: +/// - "hide" can include "zoom/maximize", "minimize", "close" +/// - "transparentWebViews" can be a boolean or an array of string, each representing a webview label (e.g., ["main", "other_webview"]) +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct DecorumConfig { + #[serde(default)] + pub windows: Vec, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WindowConfig { + #[serde(default)] + pub label: String, + #[serde(default)] + pub window_buttons: Option, + #[serde(default)] + pub create_overlay_titlebar: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct WindowButtons { + #[serde(default)] + pub inset_x: Option, + #[serde(default)] + pub inset_y: Option, + #[serde(default)] + pub support_rtl: Option, + #[serde(default)] + pub hide: Option, + #[serde(default)] + pub transparent_webviews: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(untagged)] +pub enum BoolOrVec { + Bool(bool), + Items(Vec), +} + +impl Default for WindowConfig { + fn default() -> Self { + WindowConfig { + label: String::new(), + window_buttons: Some(WindowButtons::default()), + create_overlay_titlebar: Some(false), + } + } +} + +impl Default for WindowButtons { + fn default() -> Self { + WindowButtons { + inset_x: Some(10.0), + inset_y: Some(15.0), + support_rtl: Some(false), + hide: Some(BoolOrVec::default()), + transparent_webviews: Some(BoolOrVec::default()), + } + } +} + +impl Default for BoolOrVec { + fn default() -> Self { + BoolOrVec::Bool(false) + } +} diff --git a/src/lib.rs b/src/lib.rs index 29263e1..4465f6e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,17 @@ use std::collections::HashMap; use std::sync::Arc; -use anyhow::anyhow; +use config::{DecorumConfig, WindowConfig}; +use parking_lot::RwLock; use tauri::plugin::{Builder, TauriPlugin}; -use tauri::{Emitter, Error, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; +use tauri::{Emitter, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; #[cfg(target_os = "macos")] #[macro_use] extern crate objc; mod commands; +mod config; #[cfg(target_os = "macos")] mod macos; @@ -221,21 +223,51 @@ impl WebviewWindowExt for WebviewWindow { } #[cfg(any(target_os = "macos", target_os = "windows"))] -struct WindowButtonsInsetsState( - Arc>>>>, -); +struct WindowButtonsInsetsState(Arc>>>>); -pub fn init() -> TauriPlugin { - let mut builder = Builder::new("decorum") +#[allow(dead_code)] +struct WindowConfigs(Arc>>); + +pub fn init() -> TauriPlugin { + let mut builder = Builder::::new("decorum") .invoke_handler(tauri::generate_handler![ commands::set_window_buttons_inset, commands::show_snap_overlay, ]) - .setup(move |app, _api| { + .setup(move |app, api| { + let window_configs: HashMap = api + .config() + .windows + .iter() + .map(|win_config| (win_config.label.clone(), win_config.clone())) + .collect(); + + let c_window_configs = window_configs.clone(); + app.manage(WindowConfigs(Arc::new(RwLock::new(c_window_configs)))); + #[cfg(any(target_os = "macos", target_os = "windows"))] - app.manage(WindowButtonsInsetsState(Arc::new( - parking_lot::RwLock::new(HashMap::new()), - ))); + { + let insets_map = window_configs + .iter() + .filter_map(|(label, config)| { + config.window_buttons.as_ref().and_then(|buttons| { + if buttons.inset_x.is_some() || buttons.inset_y.is_some() { + Some(( + label.clone(), + Some(LogicalPosition::new( + buttons.inset_x.unwrap_or_default(), + buttons.inset_y.unwrap_or_default(), + )), + )) + } else { + None + } + }) + }) + .collect(); + + app.manage(WindowButtonsInsetsState(Arc::new(RwLock::new(insets_map)))); + } Ok(()) }) @@ -246,11 +278,15 @@ pub fn init() -> TauriPlugin { } }); - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "windows"))] { builder = builder.on_window_ready(|window| { - // TODO: Only setup if the inset is defined in the config. - macos::nswindow_delegates::setup(window); + let insets_state = window.state::(); + let insets_map = insets_state.0.read(); + + if let Some(Some(insets)) = insets_map.get(window.label()) { + macos::nswindow_delegates::setup(window.clone(), insets.to_owned()); + } }); } diff --git a/src/macos/nswindow_delegates.rs b/src/macos/nswindow_delegates.rs index 67f0aa8..663adff 100644 --- a/src/macos/nswindow_delegates.rs +++ b/src/macos/nswindow_delegates.rs @@ -12,7 +12,9 @@ /// use objc::{msg_send, sel, sel_impl}; use rand::{distributions::Alphanumeric, Rng}; -use tauri::{Emitter, Runtime, Window}; +use tauri::{Emitter, LogicalPosition, Runtime, Window}; + +use crate::macos::position_window_controls; pub struct UnsafeWindowHandle(pub *mut std::ffi::c_void); unsafe impl Send for UnsafeWindowHandle {} @@ -23,7 +25,7 @@ struct WindowState { window: Window, } -pub fn setup(window: Window) { +pub fn setup(window: Window, initial: LogicalPosition) { use cocoa::appkit::NSWindow; use cocoa::base::{id, BOOL}; use cocoa::foundation::NSUInteger; @@ -32,8 +34,10 @@ pub fn setup(window: Window) { use crate::macos::update_window_controls_inset; + let ns_win = window.ns_window().expect("Failed to create window handle"); + // Do the initial positioning - update_window_controls_inset(&window); + position_window_controls(UnsafeWindowHandle(ns_win), initial.x, initial.y); // Ensure they stay in place while resizing the window. fn with_window_state) -> T, T>( @@ -48,12 +52,8 @@ pub fn setup(window: Window) { } unsafe { - let ns_win = window - .ns_window() - .expect("NS Window should exist to mount traffic light delegate.") - as id; - - let current_delegate: id = ns_win.delegate(); + let ns_win_id = ns_win as id; + let current_delegate: id = ns_win_id.delegate(); extern "C" fn on_window_should_close(this: &Object, _cmd: Sel, sender: id) -> BOOL { unsafe { @@ -268,8 +268,8 @@ pub fn setup(window: Window) { // delegate with the same name. let delegate_name = format!("windowDelegate_decorum_{}_{}", window_label, random_str); - ns_win.setDelegate_(cocoa::delegate!(&delegate_name, { - window: id = ns_win, + ns_win_id.setDelegate_(cocoa::delegate!(&delegate_name, { + window: id = ns_win_id, app_box: *mut c_void = app_box, toolbar: id = cocoa::base::nil, super_delegate: id = current_delegate, From a42957808b17347df4a01956ee3613d8d1947571 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:14:42 +0330 Subject: [PATCH 10/14] config strucure change, small clean-ups --- src/config.rs | 15 +++++++-------- src/lib.rs | 11 ++++++----- src/macos/mod.rs | 1 - 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/config.rs b/src/config.rs index 13da056..f095883 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,5 @@ use serde::{Deserialize, Serialize}; -/// /// Configuration for windows in the application. /// /// Default JSON configuration: @@ -16,7 +15,7 @@ use serde::{Deserialize, Serialize}; /// "hide": [] /// }, /// "transparentWebViews": true, -/// "createOverlayTitlebar": true +/// "createOverlayTitlebar": ["main"] /// } /// ] /// } @@ -24,7 +23,7 @@ use serde::{Deserialize, Serialize}; /// /// # Note: /// - "hide" can include "zoom/maximize", "minimize", "close" -/// - "transparentWebViews" can be a boolean or an array of string, each representing a webview label (e.g., ["main", "other_webview"]) +/// - "transparentWebViews" and "createOverlayTitlebar" can be a boolean or an array of string, each representing a webview label (e.g., ["main", "other_webview"]) #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DecorumConfig { #[serde(default)] @@ -38,7 +37,9 @@ pub struct WindowConfig { #[serde(default)] pub window_buttons: Option, #[serde(default)] - pub create_overlay_titlebar: Option, + pub create_overlay_titlebar: Option, + #[serde(default)] + pub transparent_webviews: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -51,8 +52,6 @@ pub struct WindowButtons { pub support_rtl: Option, #[serde(default)] pub hide: Option, - #[serde(default)] - pub transparent_webviews: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -67,7 +66,8 @@ impl Default for WindowConfig { WindowConfig { label: String::new(), window_buttons: Some(WindowButtons::default()), - create_overlay_titlebar: Some(false), + create_overlay_titlebar: Some(BoolOrVec::default()), + transparent_webviews: Some(BoolOrVec::default()), } } } @@ -79,7 +79,6 @@ impl Default for WindowButtons { inset_y: Some(15.0), support_rtl: Some(false), hide: Some(BoolOrVec::default()), - transparent_webviews: Some(BoolOrVec::default()), } } } diff --git a/src/lib.rs b/src/lib.rs index 4465f6e..c5c7bab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,18 +132,18 @@ impl WebviewWindowExt for WebviewWindow { // TODO: Also Implement for Windows 11 (>=22H2) #[cfg(target_os = "macos")] fn set_window_buttons_inset(&self, inset_option: Option>) -> Result<()> { - let styles_state = &self.state::(); - let mut styles_map = styles_state.0.write(); + let insets_state = &self.state::(); + let mut insets_map = insets_state.0.write(); let window_label = self.label().to_string(); match inset_option { Some(inset) => { - if styles_map + if insets_map .insert(window_label, Some(inset.clone())) .is_none() { - let c_insets_map = styles_map.clone(); + let c_insets_map = insets_map.clone(); let c_win = self.clone(); self.on_window_event(move |event| match event { @@ -160,7 +160,7 @@ impl WebviewWindowExt for WebviewWindow { } } None => { - styles_map.remove(&window_label); + insets_map.remove(&window_label); } } @@ -285,6 +285,7 @@ pub fn init() -> TauriPlugin { let insets_map = insets_state.0.read(); if let Some(Some(insets)) = insets_map.get(window.label()) { + #[cfg(target_os = "macos")] macos::nswindow_delegates::setup(window.clone(), insets.to_owned()); } }); diff --git a/src/macos/mod.rs b/src/macos/mod.rs index ce31f6a..4d0459e 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,4 +1,3 @@ -use cocoa::appkit::NSToolbar; use nswindow_delegates::UnsafeWindowHandle; use tauri::{LogicalPosition, Manager, Runtime, Window}; From a5876acdbb39f2c68a07b19024cdd7d9225b07e3 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:40:18 +0330 Subject: [PATCH 11/14] Improve plugin config, merge defaults with specifics --- src/config.rs | 177 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 23 +++---- 2 files changed, 181 insertions(+), 19 deletions(-) diff --git a/src/config.rs b/src/config.rs index f095883..d82e7fe 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,24 @@ +use std::collections::HashMap; + use serde::{Deserialize, Serialize}; /// Configuration for windows in the application. /// -/// Default JSON configuration: +/// JSON configuration example: /// ```json /// { +/// "all": { +/// { +/// "windowButtons": { +/// "insetX": 15.0, +/// "insetY": 20.0, +/// "supportRTL": true, +/// "hide": [] +/// }, +/// "transparentWebViews": ["main"], +/// "createOverlayTitlebar": ["onboarding"] +/// } +/// }, /// "windows": [ /// { /// "label": "main", @@ -20,6 +34,8 @@ use serde::{Deserialize, Serialize}; /// ] /// } /// ``` +/// The "all" config applies to all windows and only the specified webviews specified. +/// /// /// # Note: /// - "hide" can include "zoom/maximize", "minimize", "close" @@ -27,13 +43,15 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DecorumConfig { #[serde(default)] - pub windows: Vec, + pub all: WindowConfig, + #[serde(default)] + pub windows: Vec, + #[serde(skip)] + pub merged: HashMap, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct WindowConfig { - #[serde(default)] - pub label: String, #[serde(default)] pub window_buttons: Option, #[serde(default)] @@ -42,6 +60,13 @@ pub struct WindowConfig { pub transparent_webviews: Option, } +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct LabeledWindowConfig { + pub label: String, + #[serde(flatten)] + pub config: WindowConfig, +} + #[derive(Debug, Serialize, Deserialize, Clone)] pub struct WindowButtons { #[serde(default)] @@ -64,7 +89,6 @@ pub enum BoolOrVec { impl Default for WindowConfig { fn default() -> Self { WindowConfig { - label: String::new(), window_buttons: Some(WindowButtons::default()), create_overlay_titlebar: Some(BoolOrVec::default()), transparent_webviews: Some(BoolOrVec::default()), @@ -88,3 +112,146 @@ impl Default for BoolOrVec { BoolOrVec::Bool(false) } } + +impl DecorumConfig { + /// Creates a new `DecorumConfig` with the given configurations and merges them. + /// + /// This constructor immediately calls `merge_configurations()` to ensure + /// that the `merged` field is populated with the combined configurations. + /// + /// # Arguments + /// + /// * `all` - The default configuration applied to all windows + /// * `windows` - A vector of labeled window-specific configurations + /// + /// # Returns + /// + /// A new `DecorumConfig` instance with merged configurations + pub fn new(all: WindowConfig, windows: Vec) -> Self { + let mut config = DecorumConfig { + all, + windows, + merged: HashMap::new(), + }; + config.merge_configurations(); + config + } + + /// Merges the default "all" configuration with individual window configurations. + /// + /// This method populates the `merged` field with configurations for each window, + /// combining window-specific settings with the default "all" settings. + /// Window-specific settings take priority over the default settings. + fn merge_configurations(&mut self) { + let default_config = self.all.clone(); + let mut merged = HashMap::new(); + + for LabeledWindowConfig { label, config } in &self.windows { + let merged_config = WindowConfig { + window_buttons: config + .window_buttons + .clone() + .or_else(|| default_config.window_buttons.clone()), + create_overlay_titlebar: merge_bool_or_vec( + &config.create_overlay_titlebar, + &default_config.create_overlay_titlebar, + ), + transparent_webviews: merge_bool_or_vec( + &config.transparent_webviews, + &default_config.transparent_webviews, + ), + }; + merged.insert(label.clone(), merged_config); + } + + // Add default config for any window not explicitly defined + for label in self.get_all_window_labels() { + merged + .entry(label) + .or_insert_with(|| default_config.clone()); + } + + self.merged = merged; + } + + /// Retrieves all unique window labels mentioned in the configuration. + /// + /// This method collects labels from both the "all" section (for `create_overlay_titlebar` and `transparent_webviews`) + /// and the individual window configurations. + /// + /// # Returns + /// + /// Returns a `HashSet` containing all unique window labels. + pub fn get_all_window_labels(&self) -> std::collections::HashSet { + let mut labels = std::collections::HashSet::new(); + + // Collect labels from "all" section + if let Some(BoolOrVec::Items(items)) = &self.all.create_overlay_titlebar { + labels.extend(items.iter().cloned()); + } + if let Some(BoolOrVec::Items(items)) = &self.all.transparent_webviews { + labels.extend(items.iter().cloned()); + } + + // Collect labels from individual window configs + labels.extend(self.windows.iter().map(|w| w.label.clone())); + + labels + } + + /// Retrieves the merged configuration for a specific window. + /// + /// # Arguments + /// + /// * `label` - The label of the window to retrieve the configuration for + /// + /// # Returns + /// + /// Returns an `Option<&WindowConfig>` containing the merged configuration for the specified window, + /// or `None` if no configuration exists for the given label. + pub fn get_window_config(&self, label: &str) -> Option<&WindowConfig> { + self.merged.get(label) + } +} + +/// Merges two `BoolOrVec` options, prioritizing the specific configuration over the default. +/// +/// This is used to combine window-specific settings with the default "all" settings. +/// +/// # Arguments +/// +/// * `specific` - The `Option` from a specific window configuration +/// * `default` - The `Option` from the default "all" configuration +/// +/// # Returns +/// +/// Returns an `Option` that represents the merged configuration: +/// - If `specific` is `Some(BoolOrVec::Bool(true))`, it returns that. +/// - If `specific` is `Some(BoolOrVec::Items(items))` with non-empty items, it returns that. +/// - If `specific` is `None` and `default` is `Some`, it returns the `default` value. +/// - Otherwise, it returns `None`. +pub fn merge_bool_or_vec( + specific: &Option, + default: &Option, +) -> Option { + match (specific, default) { + (Some(BoolOrVec::Bool(true)), _) => Some(BoolOrVec::Bool(true)), + (Some(BoolOrVec::Items(items)), _) if !items.is_empty() => { + Some(BoolOrVec::Items(items.clone())) + } + (None, Some(default_value)) => Some(default_value.clone()), + _ => None, + } +} + +impl Default for DecorumConfig { + fn default() -> Self { + let mut config = DecorumConfig { + all: WindowConfig::default(), + windows: Vec::new(), + merged: HashMap::new(), + }; + config.merge_configurations(); + config + } +} diff --git a/src/lib.rs b/src/lib.rs index c5c7bab..0cd876b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::sync::Arc; -use config::{DecorumConfig, WindowConfig}; +use config::DecorumConfig; use parking_lot::RwLock; use tauri::plugin::{Builder, TauriPlugin}; use tauri::{Emitter, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; @@ -225,8 +225,8 @@ impl WebviewWindowExt for WebviewWindow { #[cfg(any(target_os = "macos", target_os = "windows"))] struct WindowButtonsInsetsState(Arc>>>>); -#[allow(dead_code)] -struct WindowConfigs(Arc>>); +// #[allow(dead_code)] +// struct DecorumConfigState(DecorumConfig); pub fn init() -> TauriPlugin { let mut builder = Builder::::new("decorum") @@ -235,21 +235,15 @@ pub fn init() -> TauriPlugin { commands::show_snap_overlay, ]) .setup(move |app, api| { - let window_configs: HashMap = api - .config() - .windows - .iter() - .map(|win_config| (win_config.label.clone(), win_config.clone())) - .collect(); + let decorum_config = api.config().clone(); - let c_window_configs = window_configs.clone(); - app.manage(WindowConfigs(Arc::new(RwLock::new(c_window_configs)))); - - #[cfg(any(target_os = "macos", target_os = "windows"))] + #[cfg(target_os = "macos")] { - let insets_map = window_configs + let insets_map: HashMap>> = decorum_config + .merged .iter() .filter_map(|(label, config)| { + // Make sure there's at least one inset defined. config.window_buttons.as_ref().and_then(|buttons| { if buttons.inset_x.is_some() || buttons.inset_y.is_some() { Some(( @@ -269,6 +263,7 @@ pub fn init() -> TauriPlugin { app.manage(WindowButtonsInsetsState(Arc::new(RwLock::new(insets_map)))); } + // app.manage(DecorumConfigState(c_config)); Ok(()) }) .on_page_load(|win, _payload: &tauri::webview::PageLoadPayload| { From cbd84d3459dbae03e239d701cf4d077f02306e14 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sun, 1 Sep 2024 13:29:01 +0330 Subject: [PATCH 12/14] Respect default insets, --- examples/tauri-app/src-tauri/src/main.rs | 6 +- examples/tauri-app/src-tauri/tauri.conf.json | 25 +++- src/commands.rs | 5 +- src/config.rs | 150 +++++++------------ src/lib.rs | 31 ++-- 5 files changed, 104 insertions(+), 113 deletions(-) diff --git a/examples/tauri-app/src-tauri/src/main.rs b/examples/tauri-app/src-tauri/src/main.rs index 91545a5..d91859e 100644 --- a/examples/tauri-app/src-tauri/src/main.rs +++ b/examples/tauri-app/src-tauri/src/main.rs @@ -1,7 +1,7 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use tauri::{LogicalPosition, Manager}; +use tauri::Manager; use tauri_plugin_decorum::WebviewWindowExt; fn main() { @@ -20,8 +20,8 @@ fn main() { let _ = main_window.make_transparent(); let _ = main_window.create_overlay_titlebar(); - let _ = - main_window.set_window_buttons_inset(Some(LogicalPosition::new(15.0, 20.0))); + // let _ = + // main_window.set_window_buttons_inset(Some(LogicalPosition::new(15.0, 20.0))); let _ = main_window.set_window_level(NSWindowLevel::NSNormalWindowLevel); } diff --git a/examples/tauri-app/src-tauri/tauri.conf.json b/examples/tauri-app/src-tauri/tauri.conf.json index 3064605..baf639e 100644 --- a/examples/tauri-app/src-tauri/tauri.conf.json +++ b/examples/tauri-app/src-tauri/tauri.conf.json @@ -8,7 +8,30 @@ "beforeBuildCommand": "pnpm build", "frontendDist": "../.output/public" }, - "plugins": {}, + "plugins": { + "decorum": { + "default": { + "windowButtons": { + "insetX": 20.0, + "insetY": 20.0 + } + }, + "windows": [ + { + "label": "other", + "windowButtons": { + "insetX": 14.0 + } + }, + { + "label": "main", + "windowButtons": { + "insetY": 15.0 + } + } + ] + } + }, "app": { "windows": [ { diff --git a/src/commands.rs b/src/commands.rs index 0bca148..3b7adeb 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,5 +1,4 @@ -use anyhow::anyhow; -use tauri::{Error, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; +use tauri::{LogicalPosition, Manager, Result, Runtime, WebviewWindow}; use crate::WebviewWindowExt; @@ -42,7 +41,7 @@ pub async fn set_window_buttons_inset( } #[cfg(not(target_os = "macos"))] - Err(Error::Anyhow(anyhow!( + Err(tauri::Error::Anyhow(anyhow::anyhow!( "This command is only supported on macOS." ))) } diff --git a/src/config.rs b/src/config.rs index d82e7fe..912417b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -46,8 +46,6 @@ pub struct DecorumConfig { pub all: WindowConfig, #[serde(default)] pub windows: Vec, - #[serde(skip)] - pub merged: HashMap, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -113,105 +111,66 @@ impl Default for BoolOrVec { } } -impl DecorumConfig { - /// Creates a new `DecorumConfig` with the given configurations and merges them. - /// - /// This constructor immediately calls `merge_configurations()` to ensure - /// that the `merged` field is populated with the combined configurations. - /// - /// # Arguments - /// - /// * `all` - The default configuration applied to all windows - /// * `windows` - A vector of labeled window-specific configurations - /// - /// # Returns - /// - /// A new `DecorumConfig` instance with merged configurations - pub fn new(all: WindowConfig, windows: Vec) -> Self { - let mut config = DecorumConfig { - all, - windows, - merged: HashMap::new(), +/// Merges the default "all" configuration with individual window configurations. +/// +/// This method populates the `merged` field with configurations for each window, +/// combining window-specific settings with the default "all" settings. +/// Window-specific settings take priority over the default settings. +pub fn merge(config: DecorumConfig) -> HashMap { + let default_config = config.all.clone(); + let mut merged = HashMap::new(); + + for LabeledWindowConfig { label, config } in &config.windows { + let merged_config = WindowConfig { + window_buttons: config + .window_buttons + .clone() + .or_else(|| default_config.window_buttons.clone()), + create_overlay_titlebar: merge_bool_or_vec( + &config.create_overlay_titlebar, + &default_config.create_overlay_titlebar, + ), + transparent_webviews: merge_bool_or_vec( + &config.transparent_webviews, + &default_config.transparent_webviews, + ), }; - config.merge_configurations(); - config + merged.insert(label.clone(), merged_config); } - /// Merges the default "all" configuration with individual window configurations. - /// - /// This method populates the `merged` field with configurations for each window, - /// combining window-specific settings with the default "all" settings. - /// Window-specific settings take priority over the default settings. - fn merge_configurations(&mut self) { - let default_config = self.all.clone(); - let mut merged = HashMap::new(); - - for LabeledWindowConfig { label, config } in &self.windows { - let merged_config = WindowConfig { - window_buttons: config - .window_buttons - .clone() - .or_else(|| default_config.window_buttons.clone()), - create_overlay_titlebar: merge_bool_or_vec( - &config.create_overlay_titlebar, - &default_config.create_overlay_titlebar, - ), - transparent_webviews: merge_bool_or_vec( - &config.transparent_webviews, - &default_config.transparent_webviews, - ), - }; - merged.insert(label.clone(), merged_config); - } - - // Add default config for any window not explicitly defined - for label in self.get_all_window_labels() { - merged - .entry(label) - .or_insert_with(|| default_config.clone()); - } - - self.merged = merged; + // Add default config for any window not explicitly defined + for label in get_all_window_labels(config) { + merged + .entry(label) + .or_insert_with(|| default_config.clone()); } - /// Retrieves all unique window labels mentioned in the configuration. - /// - /// This method collects labels from both the "all" section (for `create_overlay_titlebar` and `transparent_webviews`) - /// and the individual window configurations. - /// - /// # Returns - /// - /// Returns a `HashSet` containing all unique window labels. - pub fn get_all_window_labels(&self) -> std::collections::HashSet { - let mut labels = std::collections::HashSet::new(); - - // Collect labels from "all" section - if let Some(BoolOrVec::Items(items)) = &self.all.create_overlay_titlebar { - labels.extend(items.iter().cloned()); - } - if let Some(BoolOrVec::Items(items)) = &self.all.transparent_webviews { - labels.extend(items.iter().cloned()); - } + merged +} - // Collect labels from individual window configs - labels.extend(self.windows.iter().map(|w| w.label.clone())); +/// Retrieves all unique window labels mentioned in the configuration. +/// +/// This method collects labels from both the "all" section (for `create_overlay_titlebar` and `transparent_webviews`) +/// and the individual window configurations. +/// +/// # Returns +/// +/// Returns a `HashSet` containing all unique window labels. +pub fn get_all_window_labels(config: DecorumConfig) -> std::collections::HashSet { + let mut labels = std::collections::HashSet::new(); - labels + // Collect labels from "all" section + if let Some(BoolOrVec::Items(items)) = &config.all.create_overlay_titlebar { + labels.extend(items.iter().cloned()); } - - /// Retrieves the merged configuration for a specific window. - /// - /// # Arguments - /// - /// * `label` - The label of the window to retrieve the configuration for - /// - /// # Returns - /// - /// Returns an `Option<&WindowConfig>` containing the merged configuration for the specified window, - /// or `None` if no configuration exists for the given label. - pub fn get_window_config(&self, label: &str) -> Option<&WindowConfig> { - self.merged.get(label) + if let Some(BoolOrVec::Items(items)) = &config.all.transparent_webviews { + labels.extend(items.iter().cloned()); } + + // Collect labels from individual window configs + labels.extend(config.windows.iter().map(|w| w.label.clone())); + + labels } /// Merges two `BoolOrVec` options, prioritizing the specific configuration over the default. @@ -246,12 +205,9 @@ pub fn merge_bool_or_vec( impl Default for DecorumConfig { fn default() -> Self { - let mut config = DecorumConfig { + DecorumConfig { all: WindowConfig::default(), windows: Vec::new(), - merged: HashMap::new(), - }; - config.merge_configurations(); - config + } } } diff --git a/src/lib.rs b/src/lib.rs index 0cd876b..e00483c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::sync::Arc; -use config::DecorumConfig; use parking_lot::RwLock; use tauri::plugin::{Builder, TauriPlugin}; use tauri::{Emitter, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; @@ -225,22 +224,36 @@ impl WebviewWindowExt for WebviewWindow { #[cfg(any(target_os = "macos", target_os = "windows"))] struct WindowButtonsInsetsState(Arc>>>>); -// #[allow(dead_code)] -// struct DecorumConfigState(DecorumConfig); +#[cfg(any(target_os = "macos", target_os = "windows"))] +struct DefaultInsets(LogicalPosition); + +struct DecorumConfigState(HashMap); -pub fn init() -> TauriPlugin { - let mut builder = Builder::::new("decorum") +pub fn init() -> TauriPlugin { + let mut builder = Builder::::new("decorum") .invoke_handler(tauri::generate_handler![ commands::set_window_buttons_inset, commands::show_snap_overlay, ]) .setup(move |app, api| { - let decorum_config = api.config().clone(); + let config = api.config().clone(); + + #[cfg(any(target_os = "macos", target_os = "windows"))] + if let Some(buttons) = &config.all.window_buttons { + app.manage(DefaultInsets(match (buttons.inset_x, buttons.inset_y) { + (Some(x), Some(y)) => LogicalPosition::new(x, y), + _ => macos::DEFAULT_TRAFFIC_LIGHTS_INSET, + })); + } + + let merged = config::merge(config); + + println!("-CONFIG: \n{:#?}", api.config().clone()); + println!("-MERGED CONFIG: \n{:#?}", merged); #[cfg(target_os = "macos")] { - let insets_map: HashMap>> = decorum_config - .merged + let insets_map: HashMap>> = merged .iter() .filter_map(|(label, config)| { // Make sure there's at least one inset defined. @@ -263,7 +276,7 @@ pub fn init() -> TauriPlugin { app.manage(WindowButtonsInsetsState(Arc::new(RwLock::new(insets_map)))); } - // app.manage(DecorumConfigState(c_config)); + app.manage(DecorumConfigState(merged)); Ok(()) }) .on_page_load(|win, _payload: &tauri::webview::PageLoadPayload| { From 8d66e30fcf7e2fed9a8cc605953f99e98db34fb3 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:26:12 +0330 Subject: [PATCH 13/14] Use a better merge method. New option --- Cargo.toml | 1 + examples/tauri-app/src-tauri/tauri.conf.json | 12 +- src/config.rs | 216 +++++++++---------- src/lib.rs | 75 +++++-- src/macos/mod.rs | 4 +- 5 files changed, 165 insertions(+), 143 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 838b381..baff079 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ tauri = { version = "2.0.0-rc" } serde = "1.0" anyhow = "1.0" parking_lot = "0.12.3" +serde_json = "1.0.127" [target.'cfg(target_os = "macos")'.dependencies] rand = "^0.8" diff --git a/examples/tauri-app/src-tauri/tauri.conf.json b/examples/tauri-app/src-tauri/tauri.conf.json index baf639e..dffd818 100644 --- a/examples/tauri-app/src-tauri/tauri.conf.json +++ b/examples/tauri-app/src-tauri/tauri.conf.json @@ -10,19 +10,13 @@ }, "plugins": { "decorum": { - "default": { + "all": { + "createOverlayTitlebar": true, "windowButtons": { - "insetX": 20.0, - "insetY": 20.0 + "insetX": 12.0 } }, "windows": [ - { - "label": "other", - "windowButtons": { - "insetX": 14.0 - } - }, { "label": "main", "windowButtons": { diff --git a/src/config.rs b/src/config.rs index 912417b..269aecf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,7 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use serde::{Deserialize, Serialize}; +use serde_json::Value; /// Configuration for windows in the application. /// @@ -8,16 +9,15 @@ use serde::{Deserialize, Serialize}; /// ```json /// { /// "all": { -/// { -/// "windowButtons": { -/// "insetX": 15.0, -/// "insetY": 20.0, -/// "supportRTL": true, -/// "hide": [] -/// }, -/// "transparentWebViews": ["main"], -/// "createOverlayTitlebar": ["onboarding"] -/// } +/// "windowButtons": { +/// "insetX": 15.0, +/// "insetY": 20.0, +/// "supportRTL": true, +/// "hide": [], +/// }, +/// "clickCloseToHide": true +/// "transparentWebViews": ["main"], +/// "createOverlayTitlebar": ["onboarding"] /// }, /// "windows": [ /// { @@ -28,8 +28,9 @@ use serde::{Deserialize, Serialize}; /// "supportRTL": true, /// "hide": [] /// }, +/// "clickCloseToHide": false /// "transparentWebViews": true, -/// "createOverlayTitlebar": ["main"] +/// "createOverlayTitlebar": ["main"], /// } /// ] /// } @@ -38,10 +39,11 @@ use serde::{Deserialize, Serialize}; /// /// /// # Note: +/// - "clickCloseToHide" (macOS Only) hides the window instead of quitting /// - "hide" can include "zoom/maximize", "minimize", "close" -/// - "transparentWebViews" and "createOverlayTitlebar" can be a boolean or an array of string, each representing a webview label (e.g., ["main", "other_webview"]) +/// - "transparentWebViews" and "createOverlayTitlebar" can be a boolean or an array of string, each representing a webview label (e.g., "main", "other_webview") #[derive(Debug, Serialize, Deserialize, Clone)] -pub struct DecorumConfig { +pub struct DecorumPluginConfig { #[serde(default)] pub all: WindowConfig, #[serde(default)] @@ -49,6 +51,7 @@ pub struct DecorumConfig { } #[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] pub struct WindowConfig { #[serde(default)] pub window_buttons: Option, @@ -56,6 +59,8 @@ pub struct WindowConfig { pub create_overlay_titlebar: Option, #[serde(default)] pub transparent_webviews: Option, + #[serde(default)] + pub click_close_to_hide: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -66,6 +71,7 @@ pub struct LabeledWindowConfig { } #[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] pub struct WindowButtons { #[serde(default)] pub inset_x: Option, @@ -87,127 +93,111 @@ pub enum BoolOrVec { impl Default for WindowConfig { fn default() -> Self { WindowConfig { - window_buttons: Some(WindowButtons::default()), - create_overlay_titlebar: Some(BoolOrVec::default()), - transparent_webviews: Some(BoolOrVec::default()), + window_buttons: None, + create_overlay_titlebar: None, + transparent_webviews: None, + click_close_to_hide: None, } } } -impl Default for WindowButtons { +impl Default for DecorumPluginConfig { fn default() -> Self { - WindowButtons { - inset_x: Some(10.0), - inset_y: Some(15.0), - support_rtl: Some(false), - hide: Some(BoolOrVec::default()), + DecorumPluginConfig { + all: WindowConfig::default(), + windows: Vec::new(), } } } -impl Default for BoolOrVec { - fn default() -> Self { - BoolOrVec::Bool(false) - } -} +impl DecorumPluginConfig { + /// Merges the default "all" configuration with individual window configurations. + /// + /// This method populates the `merged` field with configurations for each window, + /// combining window-specific settings with the default "all" settings. + /// Window-specific settings take priority over the default settings. + pub fn merged(&self) -> HashMap { + let mut merged = HashMap::new(); + + for LabeledWindowConfig { label, config } in &self.windows { + match merge(&self.all, config) { + Ok(config) => { + merged.insert(label.clone(), config); + } + Err(err) => { + eprintln!("Plugin Decorum - Skipping configs for window \"{}\" due to failure during merge: {}", label, err); + } + }; + } -/// Merges the default "all" configuration with individual window configurations. -/// -/// This method populates the `merged` field with configurations for each window, -/// combining window-specific settings with the default "all" settings. -/// Window-specific settings take priority over the default settings. -pub fn merge(config: DecorumConfig) -> HashMap { - let default_config = config.all.clone(); - let mut merged = HashMap::new(); - - for LabeledWindowConfig { label, config } in &config.windows { - let merged_config = WindowConfig { - window_buttons: config - .window_buttons - .clone() - .or_else(|| default_config.window_buttons.clone()), - create_overlay_titlebar: merge_bool_or_vec( - &config.create_overlay_titlebar, - &default_config.create_overlay_titlebar, - ), - transparent_webviews: merge_bool_or_vec( - &config.transparent_webviews, - &default_config.transparent_webviews, - ), - }; - merged.insert(label.clone(), merged_config); - } + // Add default config for any window not explicitly defined + for label in self.get_all_window_labels() { + merged.entry(label).or_insert_with(|| self.all.clone()); + } - // Add default config for any window not explicitly defined - for label in get_all_window_labels(config) { merged - .entry(label) - .or_insert_with(|| default_config.clone()); } - merged -} - -/// Retrieves all unique window labels mentioned in the configuration. -/// -/// This method collects labels from both the "all" section (for `create_overlay_titlebar` and `transparent_webviews`) -/// and the individual window configurations. -/// -/// # Returns -/// -/// Returns a `HashSet` containing all unique window labels. -pub fn get_all_window_labels(config: DecorumConfig) -> std::collections::HashSet { - let mut labels = std::collections::HashSet::new(); + /// Retrieves all unique window labels mentioned in the configuration. + /// + /// This method collects labels from both the "all" section (for `create_overlay_titlebar` and `transparent_webviews`) + /// and the individual window configurations. + /// + /// # Returns + /// + /// Returns a `HashSet` containing all unique window labels. + pub fn get_all_window_labels(&self) -> HashSet { + let mut labels = HashSet::new(); + + if let Some(BoolOrVec::Items(items)) = &self.all.create_overlay_titlebar { + labels.extend(items.iter().cloned()); + } + if let Some(BoolOrVec::Items(items)) = &self.all.transparent_webviews { + labels.extend(items.iter().cloned()); + } - // Collect labels from "all" section - if let Some(BoolOrVec::Items(items)) = &config.all.create_overlay_titlebar { - labels.extend(items.iter().cloned()); - } - if let Some(BoolOrVec::Items(items)) = &config.all.transparent_webviews { - labels.extend(items.iter().cloned()); + labels.extend(self.windows.iter().map(|w| w.label.clone())); + labels } +} - // Collect labels from individual window configs - labels.extend(config.windows.iter().map(|w| w.label.clone())); +// Credits: https://github.com/jondot/merge-struct/ +fn to_value(value: &T) -> Result { + serde_json::to_value(value) +} - labels +fn from_value( + value: serde_json::Value, +) -> Result { + serde_json::from_value(value) } -/// Merges two `BoolOrVec` options, prioritizing the specific configuration over the default. -/// -/// This is used to combine window-specific settings with the default "all" settings. -/// -/// # Arguments -/// -/// * `specific` - The `Option` from a specific window configuration -/// * `default` - The `Option` from the default "all" configuration -/// -/// # Returns -/// -/// Returns an `Option` that represents the merged configuration: -/// - If `specific` is `Some(BoolOrVec::Bool(true))`, it returns that. -/// - If `specific` is `Some(BoolOrVec::Items(items))` with non-empty items, it returns that. -/// - If `specific` is `None` and `default` is `Some`, it returns the `default` value. -/// - Otherwise, it returns `None`. -pub fn merge_bool_or_vec( - specific: &Option, - default: &Option, -) -> Option { - match (specific, default) { - (Some(BoolOrVec::Bool(true)), _) => Some(BoolOrVec::Bool(true)), - (Some(BoolOrVec::Items(items)), _) if !items.is_empty() => { - Some(BoolOrVec::Items(items.clone())) - } - (None, Some(default_value)) => Some(default_value.clone()), - _ => None, - } +fn merge( + base: &T, + overrides: &T, +) -> Result { + let mut left = to_value(base)?; + let right = to_value(overrides)?; + merge_value(&mut left, &right); + from_value(left) } -impl Default for DecorumConfig { - fn default() -> Self { - DecorumConfig { - all: WindowConfig::default(), - windows: Vec::new(), +fn merge_value(a: &mut Value, b: &Value) { + match (a, b) { + (Value::Object(ref mut a), &Value::Object(ref b)) => { + for (k, v) in b { + merge_value(a.entry(k).or_insert(Value::Null), v); + } + } + (Value::Array(ref mut a), &Value::Array(ref b)) => { + a.extend(b.clone()); + } + (Value::Array(ref mut a), &Value::Object(ref b)) => { + a.extend([Value::Object(b.clone())]); + } + (_, Value::Null) => {} // do nothing + (a, b) => { + *a = b.clone(); } } } diff --git a/src/lib.rs b/src/lib.rs index e00483c..bac0c02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::sync::Arc; +use config::{DecorumPluginConfig, WindowConfig}; use parking_lot::RwLock; use tauri::plugin::{Builder, TauriPlugin}; use tauri::{Emitter, Listener, LogicalPosition, Manager, Result, Runtime, WebviewWindow}; @@ -131,7 +132,7 @@ impl WebviewWindowExt for WebviewWindow { // TODO: Also Implement for Windows 11 (>=22H2) #[cfg(target_os = "macos")] fn set_window_buttons_inset(&self, inset_option: Option>) -> Result<()> { - let insets_state = &self.state::(); + let insets_state = &self.state::(); let mut insets_map = insets_state.0.write(); let window_label = self.label().to_string(); @@ -222,15 +223,34 @@ impl WebviewWindowExt for WebviewWindow { } #[cfg(any(target_os = "macos", target_os = "windows"))] -struct WindowButtonsInsetsState(Arc>>>>); +struct WindowButtonsInsetState(Arc>>>>); #[cfg(any(target_os = "macos", target_os = "windows"))] -struct DefaultInsets(LogicalPosition); +struct DefaultInset(Option>); -struct DecorumConfigState(HashMap); +struct DecorumConfigState { + all: WindowConfig, + merged: HashMap, +} + +impl DecorumConfigState { + /// Retrieves the merged configuration for a specific window. + /// + /// # Arguments + /// + /// * `label` - The label of the window to retrieve the configuration for + /// + /// # Returns + /// + /// Returns an `Option<&WindowConfig>` containing the merged configuration for the specified window, + /// or `None` if no configuration exists for the given label. + pub fn get_for(&self, label: &str) -> Option<&WindowConfig> { + self.merged.get(label) + } +} -pub fn init() -> TauriPlugin { - let mut builder = Builder::::new("decorum") +pub fn init() -> TauriPlugin { + let mut builder = Builder::::new("decorum") .invoke_handler(tauri::generate_handler![ commands::set_window_buttons_inset, commands::show_snap_overlay, @@ -239,21 +259,32 @@ pub fn init() -> TauriPlugin { let config = api.config().clone(); #[cfg(any(target_os = "macos", target_os = "windows"))] - if let Some(buttons) = &config.all.window_buttons { - app.manage(DefaultInsets(match (buttons.inset_x, buttons.inset_y) { - (Some(x), Some(y)) => LogicalPosition::new(x, y), - _ => macos::DEFAULT_TRAFFIC_LIGHTS_INSET, - })); + { + let default_inset = config.all.window_buttons.as_ref().and_then(|buttons| { + if buttons.inset_x.is_some() || buttons.inset_y.is_some() { + Some(LogicalPosition::new( + buttons.inset_x.unwrap_or_default(), + buttons.inset_y.unwrap_or_default(), + )) + } else { + None + } + }); + + app.manage(DefaultInset(default_inset)); } - let merged = config::merge(config); + let merged_config = config.merged(); - println!("-CONFIG: \n{:#?}", api.config().clone()); - println!("-MERGED CONFIG: \n{:#?}", merged); + #[cfg(debug_assertions)] + { + println!("DECORUM-CONFIG: \n{:#?}", config.clone()); + println!("DECORUM-MERGED CONFIG: \n{:#?}", merged_config); + } #[cfg(target_os = "macos")] { - let insets_map: HashMap>> = merged + let insets_map: HashMap>> = merged_config .iter() .filter_map(|(label, config)| { // Make sure there's at least one inset defined. @@ -273,10 +304,13 @@ pub fn init() -> TauriPlugin { }) .collect(); - app.manage(WindowButtonsInsetsState(Arc::new(RwLock::new(insets_map)))); + app.manage(WindowButtonsInsetState(Arc::new(RwLock::new(insets_map)))); } - app.manage(DecorumConfigState(merged)); + app.manage(DecorumConfigState { + all: config.all, + merged: merged_config, + }); Ok(()) }) .on_page_load(|win, _payload: &tauri::webview::PageLoadPayload| { @@ -289,10 +323,13 @@ pub fn init() -> TauriPlugin { #[cfg(any(target_os = "macos", target_os = "windows"))] { builder = builder.on_window_ready(|window| { - let insets_state = window.state::(); + let insets_state = window.state::(); let insets_map = insets_state.0.read(); - if let Some(Some(insets)) = insets_map.get(window.label()) { + if let Some(insets) = insets_map + .get(window.label()) + .unwrap_or(&window.state::().0) + { #[cfg(target_os = "macos")] macos::nswindow_delegates::setup(window.clone(), insets.to_owned()); } diff --git a/src/macos/mod.rs b/src/macos/mod.rs index 4d0459e..57efe55 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -1,14 +1,14 @@ use nswindow_delegates::UnsafeWindowHandle; use tauri::{LogicalPosition, Manager, Runtime, Window}; -use crate::WindowButtonsInsetsState; +use crate::WindowButtonsInsetState; pub mod nswindow_delegates; pub const DEFAULT_TRAFFIC_LIGHTS_INSET: LogicalPosition = LogicalPosition::new(10.0, 15.0); pub fn update_window_controls_inset(window: &Window) { - let styles_state = window.state::(); + let styles_state = window.state::(); let styles_map_rw = styles_state.0.try_read(); if let Some(map) = styles_map_rw { if let Some(inset_option) = map.get(&window.label().to_string()) { From 76e84324b53bc7034a7687c5c7b20e2804598c44 Mon Sep 17 00:00:00 2001 From: Ilya <47112191+ItsEeleeya@users.noreply.github.com> Date: Mon, 2 Sep 2024 09:51:58 +0330 Subject: [PATCH 14/14] Add set_window_level command --- guest-js/index.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++++- src/commands.rs | 24 ++++++++++++++++ src/lib.rs | 7 ++++- src/macos/mod.rs | 1 + 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/guest-js/index.ts b/guest-js/index.ts index a0cfe5d..8821d65 100644 --- a/guest-js/index.ts +++ b/guest-js/index.ts @@ -1,16 +1,86 @@ import { invoke } from "@tauri-apps/api/core"; import { LogicalPosition } from "@tauri-apps/api/dpi"; +import { WebviewWindow } from "@tauri-apps/api/webviewWindow"; +import { Window } from "@tauri-apps/api/window"; export async function show_snap_overlay() { await invoke("plugin:decorum|show_snap_overlay"); } +/** + * Sets the window controls inset. + * + * ## Platform-specific: + * + * - **macOS:** Only supported on macOS. + * + * @param inset - The inset position for the window buttons. + * @param target - The target window. Can be a window label (string), a Window object, or null for the current window. + * @returns Promise + */ export async function setWindowButtonsInset( inset: LogicalPosition | null, - targetLabel: string | null = null + target: string | Window | null = null ) { + let targetLabel: string | null = null; + + if (typeof target === "string") { + targetLabel = target; + } else if (target instanceof Window) { + targetLabel = target.label; + } + await invoke("plugin:decorum|set_window_buttons_inset", { inset, target_label: targetLabel, + }).catch((e) => { + console.error("Failed to set window buttons inset:", e); + }); +} + +/** + * Representation of [NSWindowLevel](https://developer.apple.com/documentation/appkit/NSWindowLevel) + */ +export enum NSWindowLevel { + NSNormalWindowLevel = 0, + NSFloatingWindowLevel = 3, + NSSubmenuWindowLevel = 3, + NSTornOffMenuWindowLevel = 3, + NSMainMenuWindowLevel = 24, + NSStatusWindowLevel = 25, + NSModalPanelWindowLevel = 8, + NSPopUpMenuWindowLevel = 101, + NSScreenSaverWindowLevel = 1000, +} + +/** + * Set the window level. + * This will set the window level to the specified value. + * + * ## Platform-specific: + * + * - **macOS:** Only supported on macOS. + * + * @see {@link NSWindowLevel} for the available window levels. + * @param level - The window level to set. + * @returns Promise + */ +export async function setWindowLevel( + level: NSWindowLevel, + target: string | Window | null = null +) { + let targetLabel: string | null = null; + + if (typeof target === "string") { + targetLabel = target; + } else if (target instanceof WebviewWindow || target instanceof Window) { + targetLabel = target.label; + } + + await invoke("plugin:decorum|set_window_level", { + level, + target_label: targetLabel, + }).catch((e) => { + console.error("Failed to set window level:", e); }); } diff --git a/src/commands.rs b/src/commands.rs index 3b7adeb..292e659 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -45,3 +45,27 @@ pub async fn set_window_buttons_inset( "This command is only supported on macOS." ))) } + +#[tauri::command] +pub async fn set_window_level( + window: WebviewWindow, + level: u32, + target_label: Option, +) -> Result<()> { + #[cfg(target_os = "macos")] + { + let target = match target_label { + Some(label) => window + .get_webview_window(&label) + .ok_or_else(|| tauri::Error::WindowNotFound)?, + None => window, + }; + + target.set_window_level(crate::NSWindowLevel::from(level)) + } + + #[cfg(not(target_os = "macos"))] + Err(tauri::Error::Anyhow(anyhow::anyhow!( + "This command is only supported on macOS." + ))) +} diff --git a/src/lib.rs b/src/lib.rs index bac0c02..8613b7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ mod config; #[cfg(target_os = "macos")] mod macos; +/// Rust representation of [NSWindowLevel](https://developer.apple.com/documentation/appkit/NSWindowLevel) #[cfg(target_os = "macos")] #[repr(u32)] pub enum NSWindowLevel { @@ -186,7 +187,10 @@ impl WebviewWindowExt for WebviewWindow { /// ## Platform-specific: /// /// - **macOS:** Only supported on macOS. - /// This is a private API on macOS, so you cannot use this if your application will be published on the App Store. + /// + /// ## Warning: + /// This feature is an Apple internal implementation (aka private API) on macOS. + /// You cannot use this if your application will be published on the App Store. #[cfg(target_os = "macos")] fn make_transparent(&self) -> Result<()> { use cocoa::{ @@ -276,6 +280,7 @@ pub fn init() -> TauriPlugin { let merged_config = config.merged(); + // TODO: Remove #[cfg(debug_assertions)] { println!("DECORUM-CONFIG: \n{:#?}", config.clone()); diff --git a/src/macos/mod.rs b/src/macos/mod.rs index 57efe55..537f688 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -24,6 +24,7 @@ pub fn update_window_controls_inset(window: &Window) { } // TODO: Respect RTL display language +// TODO: Update Height, consider supporting the scenario where the buttons are hidden by the system due to screen sharing of the window // https://developer.apple.com/documentation/appkit/nsapplication/1428556-userinterfacelayoutdirection?language=objc pub fn position_window_controls(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64) { use cocoa::{