1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
5#![cfg_attr(feature = "doc", doc = document_features::document_features!())]
6
7use tracing::debug;
8use widestring::{U16Str, u16str};
9use windows_sys::Win32::{
10 Foundation::{BOOL, FALSE, HWND, LPARAM, TRUE},
11 System::Threading::GetCurrentThreadId,
12 UI::WindowsAndMessaging::{EnumThreadWindows, GetClassNameW, SendMessageW, WM_USER},
13};
14
15const IPC_CLASS_PREFIX: &U16Str = u16str!("EVERYTHING_TASKBAR_NOTIFICATION");
16
17const EVERYTHING_WM_IPC: u32 = WM_USER;
18
19struct EnumWindowsData {
20 result: Option<IpcWindow>,
21}
22
23unsafe extern "system" fn enum_windows_proc(hwnd: HWND, lparam: LPARAM) -> BOOL {
24 let data = unsafe { &mut *(lparam as *mut EnumWindowsData) };
25
26 let mut buf = [0; 256];
27 let len = unsafe { GetClassNameW(hwnd, buf.as_mut_ptr(), buf.len() as i32) };
28 if len > 0 {
29 let class_name = U16Str::from_slice(&buf[..len as usize]);
30 if class_name
32 .as_slice()
33 .starts_with(IPC_CLASS_PREFIX.as_slice())
34 {
35 data.result = Some(IpcWindow {
36 hwnd,
37 class_name: class_name.to_string().unwrap(),
38 });
39 return FALSE;
40 }
41 }
42
43 TRUE
44}
45
46#[derive(Debug)]
47pub struct IpcWindow {
48 hwnd: HWND,
49 class_name: String,
50}
51
52impl IpcWindow {
53 pub fn from_current_thread() -> Option<Self> {
54 let mut data = EnumWindowsData { result: None };
55
56 let tid = unsafe { GetCurrentThreadId() };
57 debug!(?tid, "from_current_thread");
58 unsafe {
59 EnumThreadWindows(tid, Some(enum_windows_proc), &mut data as *mut _ as LPARAM);
60 }
61
62 data.result
63 }
64
65 pub fn hwnd(&self) -> HWND {
66 self.hwnd
67 }
68
69 pub fn class_name(&self) -> &str {
70 &self.class_name
71 }
72
73 pub fn instance_name(&self) -> Option<&str> {
74 self.class_name
76 .strip_prefix("EVERYTHING_TASKBAR_NOTIFICATION_(")
77 .and_then(|s| s.strip_suffix(')'))
78 }
79
80 pub fn get_version(&self) -> Version {
81 const EVERYTHING_IPC_GET_MAJOR_VERSION: u32 = 0;
82 const EVERYTHING_IPC_GET_MINOR_VERSION: u32 = 1;
83 const EVERYTHING_IPC_GET_REVISION: u32 = 2;
84 const EVERYTHING_IPC_GET_BUILD_NUMBER: u32 = 3;
85 let send_u32 = |command: u32| unsafe {
88 SendMessageW(self.hwnd, EVERYTHING_WM_IPC, command as usize, 0)
89 } as u32;
90
91 Version {
92 major: send_u32(EVERYTHING_IPC_GET_MAJOR_VERSION),
93 minor: send_u32(EVERYTHING_IPC_GET_MINOR_VERSION),
94 revision: send_u32(EVERYTHING_IPC_GET_REVISION),
95 build: send_u32(EVERYTHING_IPC_GET_BUILD_NUMBER),
96 }
97 }
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
101pub struct Version {
102 pub major: u32,
103 pub minor: u32,
104 pub revision: u32,
105 pub build: u32,
106}
107
108impl Version {
109 pub fn new(major: u32, minor: u32, revision: u32, build: u32) -> Self {
110 Self {
111 major,
112 minor,
113 revision,
114 build,
115 }
116 }
117}