Evan's Blog
EvanZhu0721 / 公开仓库

SBMS

镜像已同步

SBMS complete the calculation rules for the default logical desktop topology relationship and the physical dimensions of the displays in the Windows multi-screen collaboration system.

上游 GitHub
READ-ONLY MIRROR

README、源码与 Release 已保存到本站;源码视图固定到 commit a37d6c4b。

main/ root / src
a37d6c4b· 固定源码快照
src/control.rs4.1 KB
1use std::thread;
2
3use windows::Win32::Foundation::{
4 CloseHandle, ERROR_ALREADY_EXISTS, ERROR_FILE_NOT_FOUND, GetLastError, HANDLE, WAIT_FAILED,
5};
6use windows::Win32::System::Threading::{
7 CreateEventW, CreateMutexW, EVENT_MODIFY_STATE, INFINITE, OpenEventW, ReleaseMutex, SetEvent,
8 WaitForSingleObject,
9};
10use windows::core::w;
11
12const TRAY_MUTEX: windows::core::PCWSTR = w!("Local\\SBMSTray-v1");
13const SHUTDOWN_EVENT: windows::core::PCWSTR = w!("Local\\SBMSShutdown-v1");
14const CONFIG_RELOAD_EVENT: windows::core::PCWSTR = w!("Local\\SBMSConfigReload-v1");
15
16pub struct TrayInstance(HANDLE);
17
18impl TrayInstance {
19 pub fn acquire() -> Result<Option<Self>, String> {
20 let handle = unsafe { CreateMutexW(None, true, TRAY_MUTEX) }
21 .map_err(|error| format!("CreateMutexW(tray) failed: {error}"))?;
22 if unsafe { GetLastError() } == ERROR_ALREADY_EXISTS {
23 unsafe {
24 let _ = CloseHandle(handle);
25 }
26 return Ok(None);
27 }
28 Ok(Some(Self(handle)))
29 }
30}
31
32impl Drop for TrayInstance {
33 fn drop(&mut self) {
34 unsafe {
35 let _ = ReleaseMutex(self.0);
36 let _ = CloseHandle(self.0);
37 }
38 }
39}
40
41pub fn listen_for_shutdown(callback: impl FnOnce() + Send + 'static) -> Result<(), String> {
42 let event = unsafe { CreateEventW(None, false, false, SHUTDOWN_EVENT) }
43 .map_err(|error| format!("CreateEventW(shutdown) failed: {error}"))?;
44 let event_value = event.0 as usize;
45 thread::Builder::new()
46 .name("sbms-shutdown-listener".into())
47 .spawn(move || {
48 let event = HANDLE(event_value as *mut _);
49 unsafe {
50 let _ = WaitForSingleObject(event, INFINITE);
51 let _ = CloseHandle(event);
52 }
53 callback();
54 })
55 .map(|_| ())
56 .map_err(|error| {
57 unsafe {
58 let _ = CloseHandle(event);
59 }
60 format!("failed to start shutdown listener: {error}")
61 })
62}
63
64pub fn signal_shutdown() -> Result<bool, String> {
65 let event = match unsafe { OpenEventW(EVENT_MODIFY_STATE, false, SHUTDOWN_EVENT) } {
66 Ok(event) => event,
67 Err(_error) if unsafe { GetLastError() } == ERROR_FILE_NOT_FOUND => return Ok(false),
68 Err(error) => return Err(format!("OpenEventW(shutdown) failed: {error}")),
69 };
70 let result = unsafe { SetEvent(event) }
71 .map(|()| true)
72 .map_err(|error| format!("SetEvent(shutdown) failed: {error}"));
73 unsafe {
74 let _ = CloseHandle(event);
75 }
76 result
77}
78
79pub fn listen_for_config_reload(callback: impl Fn() + Send + 'static) -> Result<(), String> {
80 let event = unsafe { CreateEventW(None, false, false, CONFIG_RELOAD_EVENT) }
81 .map_err(|error| format!("CreateEventW(config reload) failed: {error}"))?;
82 let event_value = event.0 as usize;
83 thread::Builder::new()
84 .name("sbms-config-reload-listener".into())
85 .spawn(move || {
86 let event = HANDLE(event_value as *mut _);
87 loop {
88 let wait = unsafe { WaitForSingleObject(event, INFINITE) };
89 if wait == WAIT_FAILED {
90 break;
91 }
92 callback();
93 }
94 unsafe {
95 let _ = CloseHandle(event);
96 }
97 })
98 .map(|_| ())
99 .map_err(|error| {
100 unsafe {
101 let _ = CloseHandle(event);
102 }
103 format!("failed to start config reload listener: {error}")
104 })
105}
106
107pub fn signal_config_reload() -> Result<bool, String> {
108 let event = match unsafe { OpenEventW(EVENT_MODIFY_STATE, false, CONFIG_RELOAD_EVENT) } {
109 Ok(event) => event,
110 Err(_error) if unsafe { GetLastError() } == ERROR_FILE_NOT_FOUND => return Ok(false),
111 Err(error) => return Err(format!("OpenEventW(config reload) failed: {error}")),
112 };
113 let result = unsafe { SetEvent(event) }
114 .map(|()| true)
115 .map_err(|error| format!("SetEvent(config reload) failed: {error}"));
116 unsafe {
117 let _ = CloseHandle(event);
118 }
119 result
120}
121