fix: bring hidden or covered bubbles back every minute

Another always-on-top window, or a shell action that hid ours, could
leave a bubble covered or hidden until restart. The fullscreen check
thread now shows every ready bubble again and puts it back at the top of
the always-on-top band once a minute, unless the user or a fullscreen
app has them hidden. Windows re-asserts HWND_TOPMOST without activating;
other platforms drop and re-set always-on-top.
This commit is contained in:
tiennm99 committed 2026-10-27 12:11:24 +07:00
1 parent 97100cfcc0
commit 5362e46be5
5 files changed
+82 -4

No files matched your search

+23 -3
View File
@@ -28,9 +28,9 @@ use windows::Win32::UI::Shell::{
use windows::Win32::UI::WindowsAndMessaging::{
GetClassNameW, GetForegroundWindow, GetWindowLongPtrW, GetWindowRect, GetWindowThreadProcessId,
IsIconic, IsWindowVisible, MessageBoxW, SetForegroundWindow, SetWindowLongPtrW, SetWindowPos,
ShowWindow, GWL_EXSTYLE, GWL_STYLE, MA_NOACTIVATE, MB_ICONERROR, MB_OK, MB_SETFOREGROUND,
SWP_FRAMECHANGED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER, SW_HIDE,
SW_SHOWNOACTIVATE, WM_DISPLAYCHANGE, WM_EXITSIZEMOVE, WM_MOUSEACTIVATE, WM_NCDESTROY,
ShowWindow, GWL_EXSTYLE, GWL_STYLE, HWND_TOPMOST, MA_NOACTIVATE, MB_ICONERROR, MB_OK,
MB_SETFOREGROUND, SWP_FRAMECHANGED, SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOZORDER,
SW_HIDE, SW_SHOWNOACTIVATE, WM_DISPLAYCHANGE, WM_EXITSIZEMOVE, WM_MOUSEACTIVATE, WM_NCDESTROY,
WM_SETTINGCHANGE, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW,
};
@@ -293,6 +293,26 @@ pub fn show_no_activate(window: &tauri::WebviewWindow) -> io::Result<()> {
Ok(())
}
/// Put a bubble back at the top of the always-on-top band, above any
/// topmost window that came after it, without activating it.
pub fn raise_topmost(window: &tauri::WebviewWindow) -> io::Result<()> {
let hwnd = hwnd_of(window)?;
// SAFETY: `hwnd` is a live window of this process; nothing moves,
// resizes or activates.
unsafe {
SetWindowPos(
hwnd,
Some(HWND_TOPMOST),
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE,
)
}
.map_err(io::Error::from)
}
/// Hide a bubble (see [`show_no_activate`]).
pub fn hide(window: &tauri::WebviewWindow) -> io::Result<()> {
let hwnd = hwnd_of(window)?;