Skip to content

Commit 000104b

Browse files
feat: add is_focused APIs, closes #6472 (#6530)
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
1 parent 8fd9cfa commit 000104b

File tree

13 files changed

+101
-5
lines changed

13 files changed

+101
-5
lines changed

.changes/is_focused-api.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tauri-apps/api': 'minor:feat'
3+
---
4+
5+
Add `WebviewWindow.is_focused` and `WebviewWindow.getFocusedWindow` getters.

.changes/is_focused-runtime.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'tauri-runtime': 'minor:feat'
3+
'tauri-runtime-wry': 'minor:feat'
4+
---
5+
6+
Add `Window::is_focused` getter.

.changes/is_focused-tauri.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'tauri': 'minor:feat'
3+
---
4+
5+
Add `Window::is_focused` and `Manager::get_focused_window` getters.

core/tauri-runtime-wry/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,7 @@ pub enum WindowMessage {
10721072
IsFullscreen(Sender<bool>),
10731073
IsMinimized(Sender<bool>),
10741074
IsMaximized(Sender<bool>),
1075+
IsFocused(Sender<bool>),
10751076
IsDecorated(Sender<bool>),
10761077
IsResizable(Sender<bool>),
10771078
IsMaximizable(Sender<bool>),
@@ -1308,6 +1309,10 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
13081309
window_getter!(self, WindowMessage::IsMaximized)
13091310
}
13101311

1312+
fn is_focused(&self) -> Result<bool> {
1313+
window_getter!(self, WindowMessage::IsFocused)
1314+
}
1315+
13111316
/// Gets the window’s current decoration state.
13121317
fn is_decorated(&self) -> Result<bool> {
13131318
window_getter!(self, WindowMessage::IsDecorated)
@@ -2467,6 +2472,7 @@ fn handle_user_message<T: UserEvent>(
24672472
WindowMessage::IsFullscreen(tx) => tx.send(window.fullscreen().is_some()).unwrap(),
24682473
WindowMessage::IsMinimized(tx) => tx.send(window.is_minimized()).unwrap(),
24692474
WindowMessage::IsMaximized(tx) => tx.send(window.is_maximized()).unwrap(),
2475+
WindowMessage::IsFocused(tx) => tx.send(window.is_focused()).unwrap(),
24702476
WindowMessage::IsDecorated(tx) => tx.send(window.is_decorated()).unwrap(),
24712477
WindowMessage::IsResizable(tx) => tx.send(window.is_resizable()).unwrap(),
24722478
WindowMessage::IsMaximizable(tx) => tx.send(window.is_maximizable()).unwrap(),

core/tauri-runtime/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,9 @@ pub trait Dispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + 'static
576576
/// Gets the window's current maximized state.
577577
fn is_maximized(&self) -> Result<bool>;
578578

579+
/// Gets the window's current focus state.
580+
fn is_focused(&self) -> Result<bool>;
581+
579582
/// Gets the window’s current decoration state.
580583
fn is_decorated(&self) -> Result<bool>;
581584

core/tauri/scripts/bundle.global.js

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/tauri/src/endpoints/window.rs

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub enum WindowManagerCmd {
6565
IsFullscreen,
6666
IsMinimized,
6767
IsMaximized,
68+
IsFocused,
6869
IsDecorated,
6970
IsResizable,
7071
IsMaximizable,
@@ -263,6 +264,7 @@ impl Cmd {
263264
WindowManagerCmd::IsFullscreen => return Ok(window.is_fullscreen()?.into()),
264265
WindowManagerCmd::IsMinimized => return Ok(window.is_minimized()?.into()),
265266
WindowManagerCmd::IsMaximized => return Ok(window.is_maximized()?.into()),
267+
WindowManagerCmd::IsFocused => return Ok(window.is_focused()?.into()),
266268
WindowManagerCmd::IsDecorated => return Ok(window.is_decorated()?.into()),
267269
WindowManagerCmd::IsResizable => return Ok(window.is_resizable()?.into()),
268270
WindowManagerCmd::IsMaximizable => return Ok(window.is_maximizable()?.into()),

core/tauri/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,10 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
651651
fn get_window(&self, label: &str) -> Option<Window<R>> {
652652
self.manager().get_window(label)
653653
}
654+
/// Fetch the focused window. Returns `None` if there is not any focused window.
655+
fn get_focused_window(&self) -> Option<Window<R>> {
656+
self.manager().get_focused_window()
657+
}
654658

655659
/// Fetch all managed windows.
656660
fn windows(&self) -> HashMap<String, Window<R>> {

core/tauri/src/manager.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,14 @@ impl<R: Runtime> WindowManager<R> {
11801180
self.windows_lock().get(label).cloned()
11811181
}
11821182

1183+
pub fn get_focused_window(&self) -> Option<Window<R>> {
1184+
self
1185+
.windows_lock()
1186+
.iter()
1187+
.find(|w| w.1.is_focused().unwrap_or(false))
1188+
.map(|w| w.1.clone())
1189+
}
1190+
11831191
pub fn windows(&self) -> HashMap<String, Window<R>> {
11841192
self.windows_lock().clone()
11851193
}

core/tauri/src/test/mock_runtime.rs

+4
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,10 @@ impl<T: UserEvent> Dispatch<T> for MockDispatcher {
395395
Ok(false)
396396
}
397397

398+
fn is_focused(&self) -> Result<bool> {
399+
Ok(false)
400+
}
401+
398402
fn is_decorated(&self) -> Result<bool> {
399403
Ok(false)
400404
}

core/tauri/src/window.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,11 @@ impl<R: Runtime> Window<R> {
10421042
self.window.dispatcher.is_maximized().map_err(Into::into)
10431043
}
10441044

1045+
/// Gets the window's current focus state.
1046+
pub fn is_focused(&self) -> crate::Result<bool> {
1047+
self.window.dispatcher.is_focused().map_err(Into::into)
1048+
}
1049+
10451050
/// Gets the window’s current decoration state.
10461051
pub fn is_decorated(&self) -> crate::Result<bool> {
10471052
self.window.dispatcher.is_decorated().map_err(Into::into)

tooling/api/docs/js-api.json

+1-1
Large diffs are not rendered by default.

tooling/api/src/window.ts

+48
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,33 @@ class WindowManager extends WebviewWindowHandle {
636636
})
637637
}
638638

639+
/**
640+
* Gets the window's current focus state.
641+
* @example
642+
* ```typescript
643+
* import { appWindow } from '@tauri-apps/api/window';
644+
* const focused = await appWindow.isFocused();
645+
* ```
646+
*
647+
* @returns Whether the window is focused or not.
648+
*
649+
* @since 1.4
650+
* */
651+
async isFocused(): Promise<boolean> {
652+
return invokeTauriCommand({
653+
__tauriModule: 'Window',
654+
message: {
655+
cmd: 'manage',
656+
data: {
657+
label: this.label,
658+
cmd: {
659+
type: 'isFocused'
660+
}
661+
}
662+
}
663+
})
664+
}
665+
639666
/**
640667
* Gets the window's current decorated state.
641668
* @example
@@ -2228,6 +2255,27 @@ class WebviewWindow extends WindowManager {
22282255
}
22292256
return null
22302257
}
2258+
2259+
/**
2260+
* Gets the focused window.
2261+
* @example
2262+
* ```typescript
2263+
* import { WebviewWindow } from '@tauri-apps/api/window';
2264+
* const focusedWindow = WebviewWindow.getFocusedWindow();
2265+
* ```
2266+
*
2267+
* @returns The WebviewWindow instance to communicate with the webview or `undefined` if there is not any focused window.
2268+
*
2269+
* @since 1.4
2270+
*/
2271+
static async getFocusedWindow(): Promise<WebviewWindow | null> {
2272+
for (const w of getAll()) {
2273+
if (await w.isFocused()) {
2274+
return w
2275+
}
2276+
}
2277+
return null
2278+
}
22312279
}
22322280

22332281
/** The WebviewWindow for the current window. */

0 commit comments

Comments
 (0)