1#[cfg(feature = "accelerator")]
2use super::{get_menu_data, MenuData};
3#[cfg(feature = "accelerator")]
4use crate::platform::platform_impl::vtoi;
5#[cfg(feature = "accelerator")]
6use std::collections::HashMap;
7#[cfg(feature = "accelerator")]
8use windows::Win32::{
9 Foundation::HWND,
10 UI::{
11 Input::KeyboardAndMouse::{
12 VIRTUAL_KEY, VK_0, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6, VK_7, VK_8, VK_9, VK_A, VK_APPS, VK_B, VK_BACK, VK_BROWSER_HOME, VK_C, VK_CAPITAL, VK_CONVERT, VK_D, VK_DELETE, VK_DOWN, VK_E,
13 VK_END, VK_ESCAPE, VK_F, VK_F1, VK_F10, VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24, VK_F3, VK_F4, VK_F5, VK_F6,
14 VK_F7, VK_F8, VK_F9, VK_G, VK_H, VK_HELP, VK_HOME, VK_I, VK_INSERT, VK_J, VK_K, VK_KANA, VK_L, VK_LEFT, VK_M, VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE, VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP,
15 VK_N, VK_NEXT, VK_NONCONVERT, VK_NUMLOCK, VK_O, VK_OEM_1, VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5, VK_OEM_6, VK_OEM_7, VK_OEM_COMMA, VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_PLUS, VK_P,
16 VK_PAUSE, VK_PRIOR, VK_Q, VK_R, VK_RETURN, VK_RIGHT, VK_S, VK_SCROLL, VK_SNAPSHOT, VK_SPACE, VK_T, VK_TAB, VK_U, VK_UP, VK_V, VK_VOLUME_DOWN, VK_VOLUME_MUTE, VK_VOLUME_UP, VK_W, VK_X,
17 VK_Y, VK_Z,
18 },
19 WindowsAndMessaging::{CreateAcceleratorTableW, DestroyAcceleratorTable, TranslateAcceleratorW, ACCEL, FALT, FCONTROL, FSHIFT, FVIRTKEY, HACCEL, MSG},
20 },
21};
22
23#[cfg(feature = "accelerator")]
24const MODIFIERS: [&str; 3] = ["CTRL", "ALT", "SHIFT"];
25
26#[cfg(feature = "accelerator")]
27pub(crate) fn translate_accel(hwnd: HWND, msg: MSG) {
28 let data = get_menu_data(vtoi!(hwnd.0));
29 if let Some(accel) = &data.haccel {
30 unsafe { TranslateAcceleratorW(hwnd, HACCEL(accel.0), &msg) };
31 }
32}
33
34#[cfg(feature = "accelerator")]
35pub(crate) fn destroy_haccel(data: &MenuData) {
36 if let Some(haccel) = &data.haccel {
37 let haccel = HACCEL(haccel.0);
38 let _ = unsafe { DestroyAcceleratorTable(haccel) };
39 }
40}
41
42#[cfg(feature = "accelerator")]
43pub(crate) fn create_haccel(accelerators: &HashMap<u16, String>) -> Option<HACCEL> {
44 let mut accels = Vec::new();
45
46 for (cmd, accel_key) in accelerators {
47 let upper_key = accel_key.to_uppercase();
48 let upper_keys: Vec<&str> = upper_key.split('+').collect();
49
50 if MODIFIERS.contains(&upper_keys[upper_keys.len() - 1]) {
51 continue;
52 }
53
54 let keys: Vec<&str> = accel_key.split('+').collect();
55 let key = keys[keys.len() - 1];
56
57 let virtual_key = get_virtual_key(key);
58
59 if virtual_key == VIRTUAL_KEY(0) {
60 continue;
61 }
62
63 let mut virt = FVIRTKEY;
64
65 if upper_keys.contains(&"CTRL") {
66 virt |= FCONTROL;
67 }
68
69 if upper_keys.contains(&"ALT") {
70 virt |= FALT;
71 }
72
73 if upper_keys.contains(&"SHIFT") {
74 virt |= FSHIFT;
75 }
76
77 let accel = ACCEL {
78 fVirt: virt,
79 key: virtual_key.0,
80 cmd: *cmd,
81 };
82
83 accels.push(accel);
84 }
85
86 if accels.is_empty() {
87 None
88 } else {
89 let haccel = unsafe { CreateAcceleratorTableW(&accels).unwrap() };
90 Some(haccel)
91 }
92}
93
94#[cfg(feature = "accelerator")]
95fn get_virtual_key(key_string: &str) -> VIRTUAL_KEY {
96 match key_string {
97 "A" => VK_A,
98 "B" => VK_B,
99 "C" => VK_C,
100 "D" => VK_D,
101 "E" => VK_E,
102 "F" => VK_F,
103 "G" => VK_G,
104 "H" => VK_H,
105 "I" => VK_I,
106 "J" => VK_J,
107 "K" => VK_K,
108 "L" => VK_L,
109 "M" => VK_M,
110 "N" => VK_N,
111 "O" => VK_O,
112 "P" => VK_P,
113 "Q" => VK_Q,
114 "R" => VK_R,
115 "S" => VK_S,
116 "T" => VK_T,
117 "U" => VK_U,
118 "V" => VK_V,
119 "W" => VK_W,
120 "X" => VK_X,
121 "Y" => VK_Y,
122 "Z" => VK_Z,
123 "0" => VK_0,
124 "1" => VK_1,
125 "2" => VK_2,
126 "3" => VK_3,
127 "4" => VK_4,
128 "5" => VK_5,
129 "6" => VK_6,
130 "7" => VK_7,
131 "8" => VK_8,
132 "9" => VK_9,
133 "F1" => VK_F1,
134 "F2" => VK_F2,
135 "F3" => VK_F3,
136 "F4" => VK_F4,
137 "F5" => VK_F5,
138 "F6" => VK_F6,
139 "F7" => VK_F7,
140 "F8" => VK_F8,
141 "F9" => VK_F9,
142 "F10" => VK_F10,
143 "F11" => VK_F11,
144 "F12" => VK_F12,
145 "F13" => VK_F13,
146 "F14" => VK_F14,
147 "F15" => VK_F15,
148 "F16" => VK_F16,
149 "F17" => VK_F17,
150 "F18" => VK_F18,
151 "F19" => VK_F19,
152 "F20" => VK_F20,
153 "F21" => VK_F21,
154 "F22" => VK_F22,
155 "F23" => VK_F23,
156 "F24" => VK_F24,
157 "Plus" => VK_OEM_PLUS,
158 "Space" => VK_SPACE,
159 "Tab" => VK_TAB,
160 "CapsLock" => VK_CAPITAL,
161 "NumLock" => VK_NUMLOCK,
162 "ScrollLock" => VK_SCROLL,
163 "Backspace" => VK_BACK,
164 "Delete" => VK_DELETE,
165 "Insert" => VK_INSERT,
166 "Enter" => VK_RETURN,
167 "ArrowLeft" => VK_LEFT,
168 "ArrowUp" => VK_UP,
169 "ArrowRight" => VK_RIGHT,
170 "ArrowDown" => VK_DOWN,
171 "End" => VK_END,
172 "Home" => VK_HOME,
173 "PageUp" => VK_PRIOR,
174 "PageDown" => VK_NEXT,
175 "Escape" => VK_ESCAPE,
176 "BrowserHome" => VK_BROWSER_HOME,
177 "AudioVolumeMute" => VK_VOLUME_MUTE,
178 "AudioVolumeDown" => VK_VOLUME_DOWN,
179 "AudioVolumeUp" => VK_VOLUME_UP,
180 "MediaTrackNext" => VK_MEDIA_NEXT_TRACK,
181 "MediaTrackPrevious" => VK_MEDIA_PREV_TRACK,
182 "MediaStop" => VK_MEDIA_STOP,
183 "MediaPlayPause" => VK_MEDIA_PLAY_PAUSE,
184 "PrintScreen" => VK_SNAPSHOT,
185 "Comma" => VK_OEM_COMMA,
186 "Minus" => VK_OEM_MINUS,
187 "Period" => VK_OEM_PERIOD,
188 "Semicolon" => VK_OEM_1,
189 "Slash" => VK_OEM_2,
190 "Backquote" => VK_OEM_3,
191 "BracketLeft" => VK_OEM_4,
192 "Backslash" => VK_OEM_5,
193 "BracketRight" => VK_OEM_6,
194 "Quote" => VK_OEM_7,
195 "Pause" => VK_PAUSE,
196 "KanaMode" => VK_KANA,
197 "NonConvert" => VK_NONCONVERT,
198 "Help" => VK_HELP,
199 "ContextMenu" => VK_APPS,
200 "Convert" => VK_CONVERT,
201 _ => {
202 println!("Invalid key:{}", key_string);
203 VIRTUAL_KEY(0)
204 }
205 }
206}