1use std::sync::atomic::{AtomicU8, Ordering};
8
9use crate::event::Modifiers;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12pub enum Platform {
13 MacOS,
14 Windows,
15 Linux,
16 Other,
17}
18
19static CURRENT_PLATFORM: AtomicU8 = AtomicU8::new(default_platform_code());
20
21pub fn set_platform(platform: Platform) {
22 CURRENT_PLATFORM.store(platform_code(platform), Ordering::Relaxed);
23}
24
25pub fn current_platform() -> Platform {
26 platform_from_code(CURRENT_PLATFORM.load(Ordering::Relaxed))
27}
28
29pub fn primary_modifier_label() -> &'static str {
30 match current_platform() {
31 Platform::MacOS => "Cmd",
32 Platform::Windows | Platform::Linux | Platform::Other => "Ctrl",
33 }
34}
35
36pub fn command_modifier_pressed(modifiers: Modifiers) -> bool {
37 match current_platform() {
38 Platform::MacOS => modifiers.meta,
39 Platform::Windows | Platform::Linux | Platform::Other => modifiers.ctrl,
40 }
41}
42
43pub fn command_modifier_released(modifiers: Modifiers) -> bool {
44 !modifiers.ctrl && !modifiers.meta
45}
46
47pub fn platform_from_name(name: &str) -> Platform {
48 let name = name.to_ascii_lowercase();
49 if name.contains("mac")
50 || name.contains("darwin")
51 || name.contains("iphone")
52 || name.contains("ipad")
53 {
54 Platform::MacOS
55 } else if name.contains("win") {
56 Platform::Windows
57 } else if name.contains("linux")
58 || name.contains("x11")
59 || name.contains("ubuntu")
60 || name.contains("fedora")
61 || name.contains("android")
62 {
63 Platform::Linux
64 } else {
65 Platform::Other
66 }
67}
68
69const fn default_platform_code() -> u8 {
70 if cfg!(target_os = "macos") {
71 platform_code(Platform::MacOS)
72 } else if cfg!(target_os = "windows") {
73 platform_code(Platform::Windows)
74 } else if cfg!(target_os = "linux") {
75 platform_code(Platform::Linux)
76 } else {
77 platform_code(Platform::Other)
78 }
79}
80
81const fn platform_code(platform: Platform) -> u8 {
82 match platform {
83 Platform::MacOS => 1,
84 Platform::Windows => 2,
85 Platform::Linux => 3,
86 Platform::Other => 4,
87 }
88}
89
90fn platform_from_code(code: u8) -> Platform {
91 match code {
92 1 => Platform::MacOS,
93 2 => Platform::Windows,
94 3 => Platform::Linux,
95 _ => Platform::Other,
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn parses_common_client_platform_names() {
105 assert_eq!(platform_from_name("macOS"), Platform::MacOS);
106 assert_eq!(platform_from_name("Win32"), Platform::Windows);
107 assert_eq!(platform_from_name("Linux x86_64"), Platform::Linux);
108 assert_eq!(platform_from_name("unknown"), Platform::Other);
109 }
110}