add Window.is_always_on_top() and WebviewWindow.is_always_on_top() (#12944)

* add `Window.is_always_on_top()` and `WebviewWindow.is_always_on_top()`

* add api

* fmt

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
Simon Laux 2025-03-13 22:02:01 +01:00 committed by GitHub
parent b9ee806724
commit be2e6b85fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 98 additions and 2 deletions

View File

@ -0,0 +1,7 @@
---
tauri: 'minor:feat'
tauri-runtime: 'minor:feat'
tauri-runtime-wry: 'minor:feat'
---
add `Window.is_always_on_top()` and `WebviewWindow.is_always_on_top()`

View File

@ -0,0 +1,5 @@
---
"@tauri-apps/api": minor:feat
---
Added `Window#isAlwaysOnTop` and `WebviewWindow#isAlwaysOnTop` methods.

View File

@ -1229,6 +1229,7 @@ pub enum WindowMessage {
RawWindowHandle(Sender<std::result::Result<SendRawWindowHandle, raw_window_handle::HandleError>>),
Theme(Sender<Theme>),
IsEnabled(Sender<bool>),
IsAlwaysOnTop(Sender<bool>),
// Setters
Center,
RequestUserAttention(Option<UserAttentionTypeWrapper>),
@ -1801,6 +1802,10 @@ impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher<T> {
window_getter!(self, WindowMessage::IsEnabled)
}
fn is_always_on_top(&self) -> Result<bool> {
window_getter!(self, WindowMessage::IsAlwaysOnTop)
}
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
@ -3014,7 +3019,7 @@ fn handle_user_message<T: UserEvent>(
tx.send(map_theme(&window.theme())).unwrap();
}
WindowMessage::IsEnabled(tx) => tx.send(window.is_enabled()).unwrap(),
WindowMessage::IsAlwaysOnTop(tx) => tx.send(window.is_always_on_top()).unwrap(),
// Setters
WindowMessage::Center => window.center(),
WindowMessage::RequestUserAttention(request_type) => {

View File

@ -612,6 +612,13 @@ pub trait WindowDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 's
/// Whether the window is enabled or disable.
fn is_enabled(&self) -> Result<bool>;
/// Gets the window alwaysOnTop flag state.
///
/// ## Platform-specific
///
/// - **iOS / Android:** Unsupported.
fn is_always_on_top(&self) -> Result<bool>;
/// Gets the window's current title.
fn title(&self) -> Result<String>;

View File

@ -65,6 +65,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
("available_monitors", true),
("cursor_position", true),
("theme", true),
("is_always_on_top", true),
// setters
("center", false),
("request_user_attention", false),

View File

@ -26,6 +26,7 @@ Default permissions for the plugin.
- `allow-available-monitors`
- `allow-cursor-position`
- `allow-theme`
- `allow-is-always-on-top`
- `allow-internal-toggle-maximize`
## Permission Table
@ -352,6 +353,32 @@ Denies the internal_toggle_maximize command without any pre-configured scope.
<tr>
<td>
`core:window:allow-is-always-on-top`
</td>
<td>
Enables the is_always_on_top command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`core:window:deny-is-always-on-top`
</td>
<td>
Denies the is_always_on_top command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`core:window:allow-is-closable`
</td>

File diff suppressed because one or more lines are too long

View File

@ -1016,6 +1016,10 @@ impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
Ok(true)
}
fn is_always_on_top(&self) -> Result<bool> {
Ok(false)
}
fn set_background_color(&self, color: Option<tauri_utils::config::Color>) -> Result<()> {
Ok(())
}

View File

@ -1320,6 +1320,15 @@ impl<R: Runtime> WebviewWindow<R> {
self.webview.window().is_enabled()
}
/// Determines if this window should always be on top of other windows.
///
/// ## Platform-specific
///
/// - **iOS / Android:** Unsupported.
pub fn is_always_on_top(&self) -> crate::Result<bool> {
self.webview.window().is_always_on_top()
}
/// Gets the window's native maximize button state
///
/// ## Platform-specific

View File

@ -1397,6 +1397,19 @@ impl<R: Runtime> Window<R> {
self.window.dispatcher.is_enabled().map_err(Into::into)
}
/// Determines if this window should always be on top of other windows.
///
/// ## Platform-specific
///
/// - **iOS / Android:** Unsupported.
pub fn is_always_on_top(&self) -> crate::Result<bool> {
self
.window
.dispatcher
.is_always_on_top()
.map_err(Into::into)
}
/// Gets the window's native maximize button state
///
/// ## Platform-specific

View File

@ -100,6 +100,7 @@ mod desktop_commands {
getter!(available_monitors, Vec<Monitor>);
getter!(cursor_position, PhysicalPosition<f64>);
getter!(theme, Theme);
getter!(is_always_on_top, bool);
setter!(center);
setter!(request_user_attention, Option<UserAttentionType>);
@ -272,6 +273,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
desktop_commands::available_monitors,
desktop_commands::cursor_position,
desktop_commands::theme,
desktop_commands::is_always_on_top,
// setters
desktop_commands::center,
desktop_commands::request_user_attention,

View File

@ -799,6 +799,22 @@ class Window {
})
}
/**
* Whether the window is configured to be always on top of other windows or not.
* @example
* ```typescript
* import { getCurrentWindow } from '@tauri-apps/api/window';
* const alwaysOnTop = await getCurrentWindow().isAlwaysOnTop();
* ```
*
* @returns Whether the window is visible or not.
*/
async isAlwaysOnTop(): Promise<boolean> {
return invoke('plugin:window|is_always_on_top', {
label: this.label
})
}
// Setters
/**