mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
feat: add Window::set_enabled and Window::is_enabled (#11154)
* feat: add `Window::set_enabled` and `Window::is_enabled` closes #6660 * license headers * fix build * fix mobile and macos * fix macos * again * unsafe * fix macos is_enabled * update example --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
5
.changes/window-set-enabled-api.md
Normal file
5
.changes/window-set-enabled-api.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tauri-apps/api": "patch:feat"
|
||||
---
|
||||
|
||||
Add `Window::setEnabled` and `Window::isEnabled` methods
|
||||
7
.changes/window-set-enabled.md
Normal file
7
.changes/window-set-enabled.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri": "patch:feat"
|
||||
"tauri-runtime": "patch:feat"
|
||||
"tauri-runtime-wry": "patch:feat"
|
||||
---
|
||||
|
||||
Add `Window::set_enabled` and `Window::is_enabled` methods
|
||||
@@ -30,8 +30,8 @@ members = [
|
||||
|
||||
# examples
|
||||
"examples/file-associations/src-tauri",
|
||||
"examples/api/src-tauri",
|
||||
"examples/resources/src-tauri",
|
||||
"examples/api/src-tauri",
|
||||
"examples/api/src-tauri/tauri-plugin-sample",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
@@ -49,9 +49,12 @@ percent-encoding = "2.1"
|
||||
objc2 = "0.5.2"
|
||||
objc2-foundation = { version = "0.2.2", features = [] }
|
||||
objc2-app-kit = { version = "0.2.2", features = [
|
||||
"block2",
|
||||
"NSApplication",
|
||||
"NSResponder",
|
||||
"NSView",
|
||||
"NSWindow",
|
||||
"NSGraphics",
|
||||
] }
|
||||
|
||||
[target."cfg(target_os = \"android\")".dependencies]
|
||||
|
||||
@@ -127,9 +127,11 @@ type IpcHandler = dyn Fn(Request<String>) + 'static;
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
mod undecorated_resizing;
|
||||
|
||||
mod webview;
|
||||
mod window;
|
||||
|
||||
pub use webview::Webview;
|
||||
use window::WindowExt as _;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WebContext {
|
||||
@@ -1166,9 +1168,11 @@ pub enum WindowMessage {
|
||||
GtkBox(Sender<GtkBox>),
|
||||
RawWindowHandle(Sender<std::result::Result<SendRawWindowHandle, raw_window_handle::HandleError>>),
|
||||
Theme(Sender<Theme>),
|
||||
IsEnabled(Sender<bool>),
|
||||
// Setters
|
||||
Center,
|
||||
RequestUserAttention(Option<UserAttentionTypeWrapper>),
|
||||
SetEnabled(bool),
|
||||
SetResizable(bool),
|
||||
SetMaximizable(bool),
|
||||
SetMinimizable(bool),
|
||||
@@ -1700,6 +1704,10 @@ impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher<T> {
|
||||
window_getter!(self, WindowMessage::Theme)
|
||||
}
|
||||
|
||||
fn is_enabled(&self) -> Result<bool> {
|
||||
window_getter!(self, WindowMessage::IsEnabled)
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
@@ -1775,6 +1783,13 @@ impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher<T> {
|
||||
)
|
||||
}
|
||||
|
||||
fn set_enabled(&self, enabled: bool) -> Result<()> {
|
||||
send_user_message(
|
||||
&self.context,
|
||||
Message::Window(self.window_id, WindowMessage::SetEnabled(enabled)),
|
||||
)
|
||||
}
|
||||
|
||||
fn set_maximizable(&self, maximizable: bool) -> Result<()> {
|
||||
send_user_message(
|
||||
&self.context,
|
||||
@@ -2865,40 +2880,10 @@ fn handle_user_message<T: UserEvent>(
|
||||
WindowMessage::Theme(tx) => {
|
||||
tx.send(map_theme(&window.theme())).unwrap();
|
||||
}
|
||||
// Setters
|
||||
WindowMessage::Center => {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
if let Some(monitor) = window.current_monitor() {
|
||||
#[allow(unused_mut)]
|
||||
let mut window_size = window.outer_size();
|
||||
#[cfg(windows)]
|
||||
if window.is_decorated() {
|
||||
use windows::Win32::Foundation::RECT;
|
||||
use windows::Win32::Graphics::Dwm::{
|
||||
DwmGetWindowAttribute, DWMWA_EXTENDED_FRAME_BOUNDS,
|
||||
};
|
||||
let mut rect = RECT::default();
|
||||
let result = unsafe {
|
||||
DwmGetWindowAttribute(
|
||||
HWND(window.hwnd() as _),
|
||||
DWMWA_EXTENDED_FRAME_BOUNDS,
|
||||
&mut rect as *mut _ as *mut _,
|
||||
std::mem::size_of::<RECT>() as u32,
|
||||
)
|
||||
};
|
||||
if result.is_ok() {
|
||||
window_size.height = (rect.bottom - rect.top) as u32;
|
||||
}
|
||||
}
|
||||
window.set_outer_position(calculate_window_center_position(window_size, monitor));
|
||||
}
|
||||
WindowMessage::IsEnabled(tx) => tx.send(window.is_enabled()).unwrap(),
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let ns_window: &objc2_app_kit::NSWindow = unsafe { &*window.ns_window().cast() };
|
||||
ns_window.center();
|
||||
}
|
||||
}
|
||||
// Setters
|
||||
WindowMessage::Center => window.center(),
|
||||
WindowMessage::RequestUserAttention(request_type) => {
|
||||
window.request_user_attention(request_type.map(|r| r.0));
|
||||
}
|
||||
@@ -2919,6 +2904,7 @@ fn handle_user_message<T: UserEvent>(
|
||||
WindowMessage::Unmaximize => window.set_maximized(false),
|
||||
WindowMessage::Minimize => window.set_minimized(true),
|
||||
WindowMessage::Unminimize => window.set_minimized(false),
|
||||
WindowMessage::SetEnabled(enabled) => window.set_enabled(enabled),
|
||||
WindowMessage::Show => window.set_visible(true),
|
||||
WindowMessage::Hide => window.set_visible(false),
|
||||
WindowMessage::Close => {
|
||||
@@ -3421,7 +3407,7 @@ fn handle_user_message<T: UserEvent>(
|
||||
let surface = if is_window_transparent {
|
||||
if let Ok(context) = softbuffer::Context::new(window.clone()) {
|
||||
if let Ok(mut surface) = softbuffer::Surface::new(&context, window.clone()) {
|
||||
clear_window_surface(&window, &mut surface);
|
||||
window.clear_surface(&mut surface);
|
||||
Some(surface)
|
||||
} else {
|
||||
None
|
||||
@@ -3499,7 +3485,7 @@ fn handle_event_loop<T: UserEvent>(
|
||||
if window.is_window_transparent {
|
||||
if let Some(surface) = &mut window.surface {
|
||||
if let Some(window) = &window.inner {
|
||||
clear_window_surface(window, surface)
|
||||
window.clear_surface(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3842,7 +3828,7 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
|
||||
}
|
||||
}
|
||||
}
|
||||
let position = calculate_window_center_position(window_size, monitor);
|
||||
let position = window::calculate_window_center_position(window_size, monitor);
|
||||
let logical_position = position.to_logical::<f64>(scale_factor);
|
||||
window_builder = window_builder.position(logical_position.x, logical_position.y);
|
||||
}
|
||||
@@ -3914,7 +3900,7 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
|
||||
let surface = if is_window_transparent {
|
||||
if let Ok(context) = softbuffer::Context::new(window.clone()) {
|
||||
if let Ok(mut surface) = softbuffer::Surface::new(&context, window.clone()) {
|
||||
clear_window_surface(&window, &mut surface);
|
||||
window.clear_surface(&mut surface);
|
||||
Some(surface)
|
||||
} else {
|
||||
None
|
||||
@@ -4398,49 +4384,3 @@ fn inner_size(
|
||||
) -> TaoPhysicalSize<u32> {
|
||||
window.inner_size()
|
||||
}
|
||||
|
||||
fn calculate_window_center_position(
|
||||
window_size: TaoPhysicalSize<u32>,
|
||||
target_monitor: MonitorHandle,
|
||||
) -> TaoPhysicalPosition<i32> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use tao::platform::windows::MonitorHandleExtWindows;
|
||||
use windows::Win32::Graphics::Gdi::{GetMonitorInfoW, HMONITOR, MONITORINFO};
|
||||
let mut monitor_info = MONITORINFO {
|
||||
cbSize: std::mem::size_of::<MONITORINFO>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
let status =
|
||||
unsafe { GetMonitorInfoW(HMONITOR(target_monitor.hmonitor() as _), &mut monitor_info) };
|
||||
if status.into() {
|
||||
let available_width = monitor_info.rcWork.right - monitor_info.rcWork.left;
|
||||
let available_height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
|
||||
let x = (available_width - window_size.width as i32) / 2 + monitor_info.rcWork.left;
|
||||
let y = (available_height - window_size.height as i32) / 2 + monitor_info.rcWork.top;
|
||||
return TaoPhysicalPosition::new(x, y);
|
||||
}
|
||||
}
|
||||
let screen_size = target_monitor.size();
|
||||
let monitor_pos = target_monitor.position();
|
||||
let x = (screen_size.width as i32 - window_size.width as i32) / 2 + monitor_pos.x;
|
||||
let y = (screen_size.height as i32 - window_size.height as i32) / 2 + monitor_pos.y;
|
||||
TaoPhysicalPosition::new(x, y)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn clear_window_surface(
|
||||
window: &Window,
|
||||
surface: &mut softbuffer::Surface<Arc<Window>, Arc<Window>>,
|
||||
) {
|
||||
let size = window.inner_size();
|
||||
if let (Some(width), Some(height)) = (
|
||||
std::num::NonZeroU32::new(size.width),
|
||||
std::num::NonZeroU32::new(size.height),
|
||||
) {
|
||||
surface.resize(width, height).unwrap();
|
||||
let mut buffer = surface.buffer_mut().unwrap();
|
||||
buffer.fill(0);
|
||||
let _ = buffer.present();
|
||||
}
|
||||
}
|
||||
|
||||
31
crates/tauri-runtime-wry/src/window/linux.rs
Normal file
31
crates/tauri-runtime-wry/src/window/linux.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use gtk::prelude::*;
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
use tao::platform::unix::WindowExtUnix;
|
||||
|
||||
impl super::WindowExt for tao::window::Window {
|
||||
fn set_enabled(&self, enabled: bool) {
|
||||
self.gtk_window().set_sensitive(enabled);
|
||||
}
|
||||
|
||||
fn is_enabled(&self) -> bool {
|
||||
self.gtk_window().is_sensitive()
|
||||
}
|
||||
|
||||
fn center(&self) {
|
||||
if let Some(monitor) = self.current_monitor() {
|
||||
let window_size = self.outer_size();
|
||||
let new_pos = super::calculate_window_center_position(window_size, monitor);
|
||||
self.set_outer_position(new_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
43
crates/tauri-runtime-wry/src/window/macos.rs
Normal file
43
crates/tauri-runtime-wry/src/window/macos.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use objc2_app_kit::{NSBackingStoreType, NSWindow, NSWindowStyleMask};
|
||||
use objc2_foundation::MainThreadMarker;
|
||||
use tao::platform::macos::WindowExtMacOS;
|
||||
|
||||
impl super::WindowExt for tao::window::Window {
|
||||
// based on electron implementation
|
||||
// https://github.com/electron/electron/blob/15db63e26df3e3d59ce6281f030624f746518511/shell/browser/native_window_mac.mm#L474
|
||||
fn set_enabled(&self, enabled: bool) {
|
||||
let ns_window: &NSWindow = unsafe { &*self.ns_window().cast() };
|
||||
if !enabled {
|
||||
let frame = ns_window.frame();
|
||||
let mtm = MainThreadMarker::new()
|
||||
.expect("`Window::set_enabled` can only be called on the main thread");
|
||||
let sheet = unsafe {
|
||||
NSWindow::initWithContentRect_styleMask_backing_defer(
|
||||
mtm.alloc(),
|
||||
frame,
|
||||
NSWindowStyleMask::Titled,
|
||||
NSBackingStoreType::NSBackingStoreBuffered,
|
||||
false,
|
||||
)
|
||||
};
|
||||
unsafe { sheet.setAlphaValue(0.5) };
|
||||
unsafe { ns_window.beginSheet_completionHandler(&sheet, None) };
|
||||
} else if let Some(attached) = unsafe { ns_window.attachedSheet() } {
|
||||
unsafe { ns_window.endSheet(&attached) };
|
||||
}
|
||||
}
|
||||
|
||||
fn is_enabled(&self) -> bool {
|
||||
let ns_window: &NSWindow = unsafe { &*self.ns_window().cast() };
|
||||
unsafe { ns_window.attachedSheet() }.is_none()
|
||||
}
|
||||
|
||||
fn center(&self) {
|
||||
let ns_window: &NSWindow = unsafe { &*self.ns_window().cast() };
|
||||
ns_window.center();
|
||||
}
|
||||
}
|
||||
88
crates/tauri-runtime-wry/src/window/mod.rs
Normal file
88
crates/tauri-runtime-wry/src/window/mod.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
#[cfg(windows)]
|
||||
mod windows;
|
||||
|
||||
pub trait WindowExt {
|
||||
/// Enable or disable the window
|
||||
///
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Android / iOS**: Unsupported.
|
||||
fn set_enabled(&self, enabled: bool);
|
||||
|
||||
/// Whether the window is enabled or disabled.
|
||||
///
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Android / iOS**: Unsupported, always returns `true`.
|
||||
fn is_enabled(&self) -> bool;
|
||||
|
||||
/// Center the window
|
||||
///
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Android / iOS**: Unsupported.
|
||||
fn center(&self) {}
|
||||
|
||||
/// Clears the window sufrace. i.e make it it transparent.
|
||||
#[cfg(windows)]
|
||||
fn clear_surface(
|
||||
&self,
|
||||
surface: &mut softbuffer::Surface<
|
||||
std::sync::Arc<tao::window::Window>,
|
||||
std::sync::Arc<tao::window::Window>,
|
||||
>,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(mobile)]
|
||||
impl WindowExt for tao::window::Window {
|
||||
fn set_enabled(&self, _: bool) {}
|
||||
fn is_enabled(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calculate_window_center_position(
|
||||
window_size: tao::dpi::PhysicalSize<u32>,
|
||||
target_monitor: tao::monitor::MonitorHandle,
|
||||
) -> tao::dpi::PhysicalPosition<i32> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use ::windows::Win32::Graphics::Gdi::{GetMonitorInfoW, HMONITOR, MONITORINFO};
|
||||
use tao::platform::windows::MonitorHandleExtWindows;
|
||||
|
||||
let mut monitor_info = MONITORINFO {
|
||||
cbSize: std::mem::size_of::<MONITORINFO>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
let hmonitor = target_monitor.hmonitor();
|
||||
let status = unsafe { GetMonitorInfoW(HMONITOR(hmonitor as _), &mut monitor_info) };
|
||||
if status.into() {
|
||||
let available_width = monitor_info.rcWork.right - monitor_info.rcWork.left;
|
||||
let available_height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
|
||||
let x = (available_width - window_size.width as i32) / 2 + monitor_info.rcWork.left;
|
||||
let y = (available_height - window_size.height as i32) / 2 + monitor_info.rcWork.top;
|
||||
return tao::dpi::PhysicalPosition::new(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
let screen_size = target_monitor.size();
|
||||
let monitor_pos = target_monitor.position();
|
||||
let x = (screen_size.width as i32 - window_size.width as i32) / 2 + monitor_pos.x;
|
||||
let y = (screen_size.height as i32 - window_size.height as i32) / 2 + monitor_pos.y;
|
||||
tao::dpi::PhysicalPosition::new(x, y)
|
||||
}
|
||||
64
crates/tauri-runtime-wry/src/window/windows.rs
Normal file
64
crates/tauri-runtime-wry/src/window/windows.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use windows::Win32::{
|
||||
Foundation::{HWND, RECT},
|
||||
Graphics::Dwm::{DwmGetWindowAttribute, DWMWA_EXTENDED_FRAME_BOUNDS},
|
||||
UI::Input::KeyboardAndMouse::{EnableWindow, IsWindowEnabled},
|
||||
};
|
||||
|
||||
use tao::platform::windows::WindowExtWindows;
|
||||
|
||||
impl super::WindowExt for tao::window::Window {
|
||||
fn set_enabled(&self, enabled: bool) {
|
||||
let _ = unsafe { EnableWindow(HWND(self.hwnd() as _), enabled) };
|
||||
}
|
||||
|
||||
fn is_enabled(&self) -> bool {
|
||||
unsafe { IsWindowEnabled(HWND(self.hwnd() as _)) }.as_bool()
|
||||
}
|
||||
|
||||
fn center(&self) {
|
||||
if let Some(monitor) = self.current_monitor() {
|
||||
let mut window_size = self.outer_size();
|
||||
|
||||
if self.is_decorated() {
|
||||
let mut rect = RECT::default();
|
||||
let result = unsafe {
|
||||
DwmGetWindowAttribute(
|
||||
HWND(self.hwnd() as _),
|
||||
DWMWA_EXTENDED_FRAME_BOUNDS,
|
||||
&mut rect as *mut _ as *mut _,
|
||||
std::mem::size_of::<RECT>() as u32,
|
||||
)
|
||||
};
|
||||
if result.is_ok() {
|
||||
window_size.height = (rect.bottom - rect.top) as u32;
|
||||
}
|
||||
}
|
||||
|
||||
let new_pos = super::calculate_window_center_position(window_size, monitor);
|
||||
self.set_outer_position(new_pos);
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_surface(
|
||||
&self,
|
||||
surface: &mut softbuffer::Surface<
|
||||
std::sync::Arc<tao::window::Window>,
|
||||
std::sync::Arc<tao::window::Window>,
|
||||
>,
|
||||
) {
|
||||
let size = self.inner_size();
|
||||
if let (Some(width), Some(height)) = (
|
||||
std::num::NonZeroU32::new(size.width),
|
||||
std::num::NonZeroU32::new(size.height),
|
||||
) {
|
||||
surface.resize(width, height).unwrap();
|
||||
let mut buffer = surface.buffer_mut().unwrap();
|
||||
buffer.fill(0);
|
||||
let _ = buffer.present();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,6 +603,10 @@ pub trait WindowDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 's
|
||||
|
||||
/// Gets the window's current visibility state.
|
||||
fn is_visible(&self) -> Result<bool>;
|
||||
|
||||
/// Whether the window is enabled or disable.
|
||||
fn is_enabled(&self) -> Result<bool>;
|
||||
|
||||
/// Gets the window's current title.
|
||||
fn title(&self) -> Result<String>;
|
||||
|
||||
@@ -676,6 +680,13 @@ pub trait WindowDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 's
|
||||
/// Updates the window resizable flag.
|
||||
fn set_resizable(&self, resizable: bool) -> Result<()>;
|
||||
|
||||
/// Enable or disable the window.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Android / iOS**: Unsupported.
|
||||
fn set_enabled(&self, enabled: bool) -> Result<()>;
|
||||
|
||||
/// Updates the window's native maximize button state.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
|
||||
@@ -57,6 +57,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
|
||||
("is_minimizable", true),
|
||||
("is_closable", true),
|
||||
("is_visible", true),
|
||||
("is_enabled", true),
|
||||
("title", true),
|
||||
("current_monitor", true),
|
||||
("primary_monitor", true),
|
||||
@@ -67,6 +68,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
|
||||
// setters
|
||||
("center", false),
|
||||
("request_user_attention", false),
|
||||
("set_enabled", false),
|
||||
("set_resizable", false),
|
||||
("set_maximizable", false),
|
||||
("set_minimizable", false),
|
||||
|
||||
@@ -123,32 +123,6 @@ Denies the get_all_webviews command without any pre-configured scope.
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:webview:allow-hide-webview`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the hide_webview command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:webview:deny-hide-webview`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the hide_webview command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:webview:allow-internal-toggle-devtools`
|
||||
|
||||
</td>
|
||||
@@ -331,32 +305,6 @@ Denies the set_webview_zoom command without any pre-configured scope.
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:webview:allow-show-webview`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the show_webview command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:webview:deny-show-webview`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the show_webview command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:webview:allow-webview-close`
|
||||
|
||||
</td>
|
||||
|
||||
@@ -18,6 +18,7 @@ Default permissions for the plugin.
|
||||
- `allow-is-minimizable`
|
||||
- `allow-is-closable`
|
||||
- `allow-is-visible`
|
||||
- `allow-is-enabled`
|
||||
- `allow-title`
|
||||
- `allow-current-monitor`
|
||||
- `allow-primary-monitor`
|
||||
@@ -403,6 +404,32 @@ Denies the is_decorated command without any pre-configured scope.
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-is-enabled`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the is_enabled command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:deny-is-enabled`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the is_enabled command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-is-focused`
|
||||
|
||||
</td>
|
||||
@@ -1079,6 +1106,32 @@ Denies the set_effects command without any pre-configured scope.
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-set-enabled`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Enables the set_enabled command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:deny-set-enabled`
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Denies the set_enabled command without any pre-configured scope.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
`core:window:allow-set-focus`
|
||||
|
||||
</td>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -971,6 +971,14 @@ impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
|
||||
fn set_theme(&self, theme: Option<Theme>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_enabled(&self, enabled: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_enabled(&self) -> Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
@@ -1157,6 +1157,11 @@ impl<R: Runtime> WebviewWindow<R> {
|
||||
self.window.is_resizable()
|
||||
}
|
||||
|
||||
/// Whether the window is enabled or disabled.
|
||||
pub fn is_enabled(&self) -> crate::Result<bool> {
|
||||
self.webview.window().is_enabled()
|
||||
}
|
||||
|
||||
/// Gets the window's native maximize button state
|
||||
///
|
||||
/// ## Platform-specific
|
||||
@@ -1322,6 +1327,11 @@ impl<R: Runtime> WebviewWindow<R> {
|
||||
self.window.set_resizable(resizable)
|
||||
}
|
||||
|
||||
/// Enable or disable the window.
|
||||
pub fn set_enabled(&self, enabled: bool) -> crate::Result<()> {
|
||||
self.webview.window().set_enabled(enabled)
|
||||
}
|
||||
|
||||
/// Determines if this window's native maximize button should be enabled.
|
||||
/// If resizable is set to false, this setting is ignored.
|
||||
///
|
||||
|
||||
@@ -1370,6 +1370,11 @@ impl<R: Runtime> Window<R> {
|
||||
self.window.dispatcher.is_resizable().map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Whether the window is enabled or disabled.
|
||||
pub fn is_enabled(&self) -> crate::Result<bool> {
|
||||
self.window.dispatcher.is_enabled().map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Gets the window's native maximize button state
|
||||
///
|
||||
/// ## Platform-specific
|
||||
@@ -1650,6 +1655,15 @@ impl<R: Runtime> Window<R> {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Enable or disable the window.
|
||||
pub fn set_enabled(&self, enabled: bool) -> crate::Result<()> {
|
||||
self
|
||||
.window
|
||||
.dispatcher
|
||||
.set_enabled(enabled)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Maximizes this window.
|
||||
pub fn maximize(&self) -> crate::Result<()> {
|
||||
self.window.dispatcher.maximize().map_err(Into::into)
|
||||
|
||||
@@ -92,6 +92,7 @@ mod desktop_commands {
|
||||
getter!(is_minimizable, bool);
|
||||
getter!(is_closable, bool);
|
||||
getter!(is_visible, bool);
|
||||
getter!(is_enabled, bool);
|
||||
getter!(title, String);
|
||||
getter!(current_monitor, Option<Monitor>);
|
||||
getter!(primary_monitor, Option<Monitor>);
|
||||
@@ -139,6 +140,7 @@ mod desktop_commands {
|
||||
setter!(set_title_bar_style, TitleBarStyle);
|
||||
setter!(set_size_constraints, WindowSizeConstraints);
|
||||
setter!(set_theme, Option<Theme>);
|
||||
setter!(set_enabled, bool);
|
||||
|
||||
#[command(root = "crate")]
|
||||
pub async fn set_icon<R: Runtime>(
|
||||
@@ -240,6 +242,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
desktop_commands::is_minimizable,
|
||||
desktop_commands::is_closable,
|
||||
desktop_commands::is_visible,
|
||||
desktop_commands::is_enabled,
|
||||
desktop_commands::title,
|
||||
desktop_commands::current_monitor,
|
||||
desktop_commands::primary_monitor,
|
||||
@@ -276,6 +279,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
desktop_commands::set_position,
|
||||
desktop_commands::set_fullscreen,
|
||||
desktop_commands::set_focus,
|
||||
desktop_commands::set_enabled,
|
||||
desktop_commands::set_skip_taskbar,
|
||||
desktop_commands::set_cursor_grab,
|
||||
desktop_commands::set_cursor_visible,
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
"description": "permissions to run the app",
|
||||
"windows": ["main", "main-*"],
|
||||
"permissions": [
|
||||
"core:window:allow-is-enabled",
|
||||
"core:window:allow-set-enabled",
|
||||
{
|
||||
"identifier": "allow-log-operation",
|
||||
"allow": [
|
||||
|
||||
@@ -138,16 +138,42 @@
|
||||
|
||||
let windowIconPath
|
||||
|
||||
function setTitle_() {
|
||||
function setTitle() {
|
||||
webviewMap[selectedWebview].setTitle(windowTitle)
|
||||
}
|
||||
|
||||
function hide_() {
|
||||
webviewMap[selectedWebview].hide()
|
||||
setTimeout(webviewMap[selectedWebview].show, 2000)
|
||||
async function hide() {
|
||||
let visible = await webviewMap[selectedWebview].isVisible()
|
||||
onMessage('window is ' + (visible ? 'visible' : 'invisible'))
|
||||
await webviewMap[selectedWebview].hide()
|
||||
|
||||
setTimeout(async () => {
|
||||
visible = await webviewMap[selectedWebview].isVisible()
|
||||
onMessage('window is ' + (visible ? 'visible' : 'invisible'))
|
||||
|
||||
await webviewMap[selectedWebview].show()
|
||||
visible = await webviewMap[selectedWebview].isVisible()
|
||||
onMessage('window is ' + (visible ? 'visible' : 'invisible'))
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
function minimize_() {
|
||||
async function disable() {
|
||||
let enabled = await webviewMap[selectedWebview].isEnabled()
|
||||
onMessage('window is ' + (enabled ? 'enabled' : 'disabled'))
|
||||
|
||||
await webviewMap[selectedWebview].setEnabled(false)
|
||||
|
||||
setTimeout(async () => {
|
||||
enabled = await webviewMap[selectedWebview].isEnabled()
|
||||
onMessage('window is ' + (enabled ? 'enabled' : 'disabled'))
|
||||
|
||||
await webviewMap[selectedWebview].setEnabled(true)
|
||||
enabled = await webviewMap[selectedWebview].isEnabled()
|
||||
onMessage('window is ' + (enabled ? 'enabled' : 'disabled'))
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
function minimize() {
|
||||
webviewMap[selectedWebview].minimize()
|
||||
setTimeout(webviewMap[selectedWebview].unminimize, 2000)
|
||||
}
|
||||
@@ -200,7 +226,7 @@
|
||||
resizeEventUnlisten = await window.listen('tauri://resize', loadWindowSize)
|
||||
}
|
||||
|
||||
async function requestUserAttention_() {
|
||||
async function requestUserAttention() {
|
||||
await webviewMap[selectedWebview].minimize()
|
||||
await webviewMap[selectedWebview].requestUserAttention(
|
||||
UserAttentionType.Critical
|
||||
@@ -363,7 +389,7 @@
|
||||
</div>
|
||||
<div class="grid gap-1 grow">
|
||||
<h4 class="my-2">Set Window Title</h4>
|
||||
<form class="flex gap-2" on:submit|preventDefault={setTitle_}>
|
||||
<form class="flex gap-2" on:submit|preventDefault={setTitle}>
|
||||
<input class="input flex-1 min-w-10" bind:value={windowTitle} />
|
||||
<button class="btn" type="submit">Set</button>
|
||||
</form>
|
||||
@@ -380,20 +406,23 @@
|
||||
<button
|
||||
class="btn"
|
||||
title="Unminimizes after 2 seconds"
|
||||
on:click={minimize_}
|
||||
on:click={minimize}
|
||||
>
|
||||
Minimize
|
||||
</button>
|
||||
<button
|
||||
class="btn"
|
||||
title="Visible again after 2 seconds"
|
||||
on:click={hide_}
|
||||
>
|
||||
<button class="btn" title="Visible again after 2 seconds" on:click={hide}>
|
||||
Hide
|
||||
</button>
|
||||
<button
|
||||
class="btn"
|
||||
on:click={requestUserAttention_}
|
||||
title="Enabled again after 2 seconds"
|
||||
on:click={disable}
|
||||
>
|
||||
Disable
|
||||
</button>
|
||||
<button
|
||||
class="btn"
|
||||
on:click={requestUserAttention}
|
||||
title="Minimizes the window, requests attention for 3s and then resets it"
|
||||
>Request attention</button
|
||||
>
|
||||
@@ -531,14 +560,16 @@
|
||||
Inner Logical Size
|
||||
</div>
|
||||
<span>Width: {innerSize.toLogical(scaleFactor).width.toFixed(3)}</span>
|
||||
<span>Height: {innerSize.toLogical(scaleFactor).height.toFixed(3)}</span>
|
||||
<span>Height: {innerSize.toLogical(scaleFactor).height.toFixed(3)}</span
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-accent dark:text-darkAccent font-700 m-block-1">
|
||||
Outer Logical Size
|
||||
</div>
|
||||
<span>Width: {outerSize.toLogical(scaleFactor).width.toFixed(3)}</span>
|
||||
<span>Height: {outerSize.toLogical(scaleFactor).height.toFixed(3)}</span>
|
||||
<span>Height: {outerSize.toLogical(scaleFactor).height.toFixed(3)}</span
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-accent dark:text-darkAccent font-700 m-block-1">
|
||||
|
||||
@@ -870,6 +870,43 @@ class Window {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the window.
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
* await getCurrentWindow().setEnabled(false);
|
||||
* ```
|
||||
*
|
||||
* @returns A promise indicating the success or failure of the operation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async setEnabled(enabled: boolean): Promise<void> {
|
||||
return invoke('plugin:window|set_enabled', {
|
||||
label: this.label,
|
||||
value: enabled
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the window is enabled or disabled.
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||
* await getCurrentWindow().setEnabled(false);
|
||||
* ```
|
||||
*
|
||||
* @returns A promise indicating the success or failure of the operation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async isEnabled(): Promise<boolean> {
|
||||
return invoke('plugin:window|is_enabled', {
|
||||
label: this.label
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the window's native maximize button is enabled or not.
|
||||
* If resizable is set to false, this setting is ignored.
|
||||
|
||||
Reference in New Issue
Block a user