stdweb/webapi/events/keyboard.rs
1use webcore::value::Reference;
2use webcore::try_from::TryInto;
3use webapi::event::{IEvent, Event};
4
5// Used by KeyboardEvent and MouseEvent to get the state of a modifier key.
6pub(crate) fn get_event_modifier_state< T: IEvent >( event: &T, key: ModifierKey ) -> bool {
7 js!(
8 return @{event.as_ref()}.getModifierState( @{
9 match key {
10 ModifierKey::Alt => "Alt",
11 ModifierKey::AltGr => "AltGraph",
12 ModifierKey::CapsLock => "CapsLock",
13 ModifierKey::Ctrl => "Control",
14 ModifierKey::Function => "Fn",
15 ModifierKey::FunctionLock => "FnLock",
16 ModifierKey::Hyper => "Hyper",
17 ModifierKey::Meta => "Meta",
18 ModifierKey::NumLock => "NumLock",
19 ModifierKey::OS => "OS",
20 ModifierKey::ScrollLock => "ScrollLock",
21 ModifierKey::Shift => "Shift",
22 ModifierKey::Super => "Super",
23 ModifierKey::Symbol => "Symbol",
24 ModifierKey::SymbolLock => "SymbolLock",
25 }
26 } );
27 ).try_into().unwrap()
28}
29
30/// `IKeyboardEvent` objects describe a user interaction with the
31/// keyboard. Each event describes a key; the event type identifies
32/// what kind of activity was performed.
33///
34/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)
35// https://w3c.github.io/uievents/#keyboardevent
36pub trait IKeyboardEvent: IEvent {
37 /// Indicates whether the Alt key was down when this event was fired.
38 ///
39 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/altKey)
40 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-altkey-3
41 #[inline]
42 fn alt_key( &self ) -> bool {
43 js!(
44 return @{self.as_ref()}.altKey;
45 ).try_into().unwrap()
46 }
47
48 /// Returns a code value that indicates the physical key pressed on the keyboard.
49 ///
50 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code)
51 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-code-3
52 #[inline]
53 fn code( &self ) -> String {
54 js!(
55 return @{self.as_ref()}.code;
56 ).try_into().unwrap()
57 }
58
59 /// Returns whether the Ctrl key was down when this event was fired.
60 ///
61 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/ctrlKey)
62 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-ctrlkey-3
63 #[inline]
64 fn ctrl_key( &self ) -> bool {
65 js!(
66 return @{self.as_ref()}.ctrlKey;
67 ).try_into().unwrap()
68 }
69
70
71 /// Returns whether a modifier key was down when this event was fired.
72 ///
73 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState)
74 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-getmodifierstate-19
75 #[inline]
76 fn get_modifier_state( &self, key: ModifierKey ) -> bool {
77 get_event_modifier_state( self, key )
78 }
79
80 /// Returns whether this event was fired during composition.
81 ///
82 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/isComposing)
83 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-iscomposing-1
84 #[inline]
85 fn is_composing( &self ) -> bool {
86 js!(
87 return @{self.as_ref()}.isComposing;
88 ).try_into().unwrap()
89 }
90
91 /// Returns the location of the key on the keyboard.
92 ///
93 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location)
94 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-location-1
95 fn location( &self ) -> KeyboardLocation {
96 match js!(
97 return @{self.as_ref()}.location;
98 ).try_into().unwrap() {
99 0 => KeyboardLocation::Standard,
100 1 => KeyboardLocation::Left,
101 2 => KeyboardLocation::Right,
102 3 => KeyboardLocation::Numpad,
103 4 => KeyboardLocation::Mobile,
104 5 => KeyboardLocation::Joystick,
105 _ => unreachable!("Unexpected KeyboardEvent.location value"),
106 }
107 }
108
109 /// Returns the value of a key or keys pressed by the user.
110 ///
111 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
112 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-key-4
113 #[inline]
114 fn key( &self ) -> String {
115 js!(
116 return @{self.as_ref()}.key;
117 ).into_string().unwrap()
118 }
119
120 /// Indicates whether the Meta key was down when this event was fired.
121 ///
122 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey)
123 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-metakey-3
124 #[inline]
125 fn meta_key( &self ) -> bool {
126 js!(
127 return @{self.as_ref()}.metaKey;
128 ).try_into().unwrap()
129 }
130
131 /// Indicates whether the key is held down such that it is repeating.
132 ///
133 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat)
134 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-repeat-1
135 #[inline]
136 fn repeat( &self ) -> bool {
137 js!(
138 return @{self.as_ref()}.repeat;
139 ).try_into().unwrap()
140 }
141
142 /// Indicates whether the Shift key was down when this event was fired.
143 ///
144 /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/shiftKey)
145 // https://w3c.github.io/uievents/#ref-for-dom-keyboardevent-shiftkey-3
146 #[inline]
147 fn shift_key( &self ) -> bool {
148 js!(
149 return @{self.as_ref()}.shiftKey;
150 ).try_into().unwrap()
151 }
152}
153
154/// A modifier key on the keyboard.
155#[allow(missing_docs)]
156#[derive(Clone, Copy, Debug, Eq, PartialEq)]
157pub enum ModifierKey {
158 Alt,
159 AltGr,
160 CapsLock,
161 Ctrl,
162 Function,
163 FunctionLock,
164 Hyper,
165 Meta,
166 NumLock,
167 OS,
168 ScrollLock,
169 Shift,
170 Super,
171 Symbol,
172 SymbolLock,
173}
174
175/// The location on the keyboard of a key.
176#[derive(Clone, Copy, Debug, Eq, PartialEq)]
177pub enum KeyboardLocation {
178 /// The key has only one version, or the location can't be distinguished.
179 Standard,
180 /// The left-hand version of a key.
181 Left,
182 /// The right-hand version of a key.
183 Right,
184 /// The key was on a numeric pad.
185 Numpad,
186 /// The key was on a mobile device.
187 Mobile,
188 /// The key was on a joystick.
189 Joystick,
190}
191
192/// A reference to a JavaScript object which implements the [IKeyboardEvent](trait.IKeyboardEvent.html)
193/// interface.
194///
195/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)
196// https://w3c.github.io/uievents/#keyboardevent
197#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
198#[reference(instance_of = "KeyboardEvent")]
199#[reference(subclass_of(Event))]
200pub struct KeyboardEvent( Reference );
201
202impl IEvent for KeyboardEvent {}
203impl IKeyboardEvent for KeyboardEvent {}
204
205/// The `KeyPressEvent` is fired when a key is pressed down. It's only
206/// fired for keys which produce a character value.
207///
208/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/keypress)
209// https://w3c.github.io/uievents/#keypress
210#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
211#[reference(instance_of = "KeyboardEvent")]
212#[reference(event = "keypress")]
213#[reference(subclass_of(Event, KeyboardEvent))]
214pub struct KeyPressEvent( Reference );
215
216impl IEvent for KeyPressEvent {}
217impl IKeyboardEvent for KeyPressEvent {}
218
219/// The `KeyDownEvent` is fired when a key is pressed down.
220/// Unlike the `KeyPressEvent` event it's also fired for keys which
221/// do not produce a character value.
222///
223/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/keydown)
224// https://w3c.github.io/uievents/#event-type-keydown
225#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
226#[reference(instance_of = "KeyboardEvent")]
227#[reference(event = "keydown")]
228#[reference(subclass_of(Event, KeyboardEvent))]
229pub struct KeyDownEvent( Reference );
230
231impl IEvent for KeyDownEvent {}
232impl IKeyboardEvent for KeyDownEvent {}
233
234/// The `KeyUpEvent` is fired when a key is released.
235///
236/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/Events/keyup)
237// https://w3c.github.io/uievents/#event-type-keyup
238#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
239#[reference(instance_of = "KeyboardEvent")]
240#[reference(event = "keyup")]
241#[reference(subclass_of(Event, KeyboardEvent))]
242pub struct KeyUpEvent( Reference );
243
244impl IEvent for KeyUpEvent {}
245impl IKeyboardEvent for KeyUpEvent {}
246
247#[cfg(all(test, feature = "web_test"))]
248mod tests {
249 use super::*;
250 use webapi::event::ConcreteEvent;
251
252 #[test]
253 fn test_keyboard_event() {
254 let event: KeyboardEvent = js!(
255 return new KeyboardEvent(
256 @{KeyPressEvent::EVENT_TYPE},
257 {
258 key: "A",
259 code: "KeyA",
260 location: 0,
261 ctrlKey: true,
262 shiftKey: false,
263 altKey: true,
264 metaKey: false,
265 repeat: true,
266 isComposing: false
267 }
268 );
269 ).try_into().unwrap();
270 assert!( event.alt_key() );
271 assert_eq!( event.code(), "KeyA" );
272 assert!( event.ctrl_key() );
273 assert!( event.get_modifier_state( ModifierKey::Alt ) );
274 assert!( event.get_modifier_state( ModifierKey::Ctrl ) );
275 assert!( !event.get_modifier_state( ModifierKey::Shift ) );
276 assert!( !event.is_composing() );
277 assert_eq!( event.location(), KeyboardLocation::Standard );
278 assert_eq!( event.key(), "A" );
279 assert!( !event.meta_key() );
280 assert!( event.repeat() );
281 assert!( !event.shift_key() );
282 }
283
284 #[test]
285 fn test_keypress_event() {
286 let event: KeyPressEvent = js!(
287 return new KeyboardEvent( @{KeyPressEvent::EVENT_TYPE} );
288 ).try_into().unwrap();
289 assert_eq!( event.event_type(), KeyPressEvent::EVENT_TYPE );
290 }
291
292 #[test]
293 fn test_keydown_event_is_only_constructible_from_a_keydown_event() {
294 let event: Option< KeyDownEvent > = js!(
295 return new KeyboardEvent( "keydown" );
296 ).try_into().ok();
297 assert!( event.is_some() );
298
299 let event: Option< KeyDownEvent > = js!(
300 return new KeyboardEvent( "keyup" );
301 ).try_into().ok();
302 assert!( event.is_none() );
303 }
304}