tray_indicator/platform/
mod.rs

1mod error;
2mod icon;
3mod notify_icon;
4mod popup_menu;
5mod string;
6mod util;
7
8pub(crate) use string::NativeString;
9
10use self::error::WinError;
11use crate::Tray;
12use std::cell::RefCell;
13
14thread_local! {
15    static TRAY_DATA: RefCell<Tray> = panic!("Tray data is not initialized");
16}
17
18pub(crate) fn display(tray: Tray) -> Result<(), TrayError> {
19    TRAY_DATA.set(tray);
20
21    unsafe {
22        let instance = notify_icon::get_instance()?;
23        let hwnd = notify_icon::create_window(instance)?;
24        notify_icon::create_notify_icon(instance, hwnd)?;
25        notify_icon::run_message_loop(hwnd);
26    }
27
28    Ok(())
29}
30
31pub(crate) fn exit() {
32    unsafe {
33        windows_sys::Win32::UI::WindowsAndMessaging::PostQuitMessage(0);
34    }
35}
36
37#[derive(Debug)]
38pub enum TrayError {
39    NoInstance(WinError),
40    WndClassRegister(WinError),
41    WindowCreate(WinError),
42    IconLoad(WinError),
43    Display,
44    Version,
45}
46
47impl std::fmt::Display for TrayError {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        match self {
50            TrayError::NoInstance(e) => write!(f, "Failed to get process instance handle. ({e})"),
51            TrayError::WndClassRegister(e) => write!(f, "Failed to register window class. ({e})"),
52            TrayError::WindowCreate(e) => write!(f, "Failed to create tray window. ({e})"),
53            TrayError::IconLoad(e) => write!(f, "Failed to load icon for tray. ({e})"),
54            TrayError::Display => write!(f, "Failed to display notify icon."),
55            TrayError::Version => write!(f, "Notify icon API version is not supported by the OS."),
56        }
57    }
58}
59
60impl std::error::Error for TrayError {
61    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
62        match self {
63            TrayError::NoInstance(e) => Some(e),
64            TrayError::WndClassRegister(e) => Some(e),
65            TrayError::WindowCreate(e) => Some(e),
66            TrayError::IconLoad(e) => Some(e),
67            TrayError::Display => None,
68            TrayError::Version => None,
69        }
70    }
71}