Skip to content

Commit d3c2468

Browse files
authored
fix(windows): delay tray registeration until TaskbarCreated (#293)
This happens when launched from Task Scheduler
1 parent cb22cd5 commit d3c2468

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tray-icon": patch
3+
---
4+
5+
Handle Windows tray icon creation when the taskbar is not ready by keeping the message window alive and re-registering on TaskbarCreated.

src/platform_impl/windows/mod.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ use windows_sys::{
1717
NIM_ADD, NIM_DELETE, NIM_MODIFY, NOTIFYICONDATAW, NOTIFYICONIDENTIFIER,
1818
},
1919
WindowsAndMessaging::{
20-
CreateWindowExW, DefWindowProcW, DestroyWindow, GetCursorPos, KillTimer,
21-
RegisterClassW, RegisterWindowMessageA, SendMessageW, SetForegroundWindow,
22-
SetTimer, TrackPopupMenu, CREATESTRUCTW, CW_USEDEFAULT, GWL_USERDATA, HICON, HMENU,
23-
TPM_BOTTOMALIGN, TPM_LEFTALIGN, WM_CREATE, WM_DESTROY, WM_LBUTTONDBLCLK,
24-
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDBLCLK, WM_MBUTTONDOWN, WM_MBUTTONUP,
25-
WM_MOUSEMOVE, WM_NCCREATE, WM_RBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP,
26-
WM_TIMER, WNDCLASSW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW,
27-
WS_EX_TRANSPARENT, WS_OVERLAPPED,
20+
ChangeWindowMessageFilterEx, CreateWindowExW, DefWindowProcW, DestroyWindow,
21+
GetCursorPos, KillTimer, RegisterClassW, RegisterWindowMessageA, SendMessageW,
22+
SetForegroundWindow, SetTimer, TrackPopupMenu, CREATESTRUCTW, CW_USEDEFAULT,
23+
GWL_USERDATA, HICON, HMENU, MSGFLT_ALLOW, TPM_BOTTOMALIGN, TPM_LEFTALIGN,
24+
WM_CREATE, WM_DESTROY, WM_LBUTTONDBLCLK, WM_LBUTTONDOWN, WM_LBUTTONUP,
25+
WM_MBUTTONDBLCLK, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEMOVE, WM_NCCREATE,
26+
WM_RBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_TIMER, WNDCLASSW, WS_EX_LAYERED,
27+
WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, WS_OVERLAPPED,
2828
},
2929
},
3030
},
@@ -123,12 +123,14 @@ impl TrayIcon {
123123
return Err(crate::Error::OsError(std::io::Error::last_os_error()));
124124
}
125125

126+
// Allow "TaskbarCreated" through UIPI so elevated apps can re-register on explorer restart.
127+
ChangeWindowMessageFilterEx(hwnd, *S_U_TASKBAR_RESTART, MSGFLT_ALLOW, ptr::null_mut());
128+
126129
let hicon = attrs.icon.as_ref().map(|i| i.inner.as_raw_handle());
127130

128131
if !register_tray_icon(hwnd, internal_id, &hicon, &attrs.tooltip) {
129-
let result = Err(crate::Error::OsError(std::io::Error::last_os_error()));
130-
DestroyWindow(hwnd);
131-
return result;
132+
// Explorer/taskbar may not be ready yet (e.g., app starts before explorer.exe).
133+
// Keep the window alive and wait for TaskbarCreated to re-register.
132134
}
133135

134136
if let Some(menu) = &attrs.menu {
@@ -334,7 +336,6 @@ unsafe extern "system" fn tray_proc(
334336
userdata.tooltip = *tooltip;
335337
}
336338
_ if msg == *S_U_TASKBAR_RESTART => {
337-
remove_tray_icon(userdata.hwnd, userdata.internal_id);
338339
register_tray_icon(
339340
userdata.hwnd,
340341
userdata.internal_id,

0 commit comments

Comments
 (0)