Associate logical and physical keypresses together to support non-QWERTY keyboards.

This commit is contained in:
Josh Matthews 2016-06-30 04:27:26 -04:00
parent 87c7772527
commit 04ce86c08c
15 changed files with 137 additions and 77 deletions

View file

@ -17,6 +17,7 @@ use dom::uievent::UIEvent;
use dom::window::Window;
use msg::constellation_msg;
use msg::constellation_msg::{Key, KeyModifiers};
use std::borrow::Cow;
use std::cell::Cell;
no_jsmanaged_fields!(Key);
@ -69,6 +70,7 @@ impl KeyboardEvent {
cancelable: bool,
view: Option<&Window>,
_detail: i32,
ch: Option<char>,
key: Option<Key>,
key_string: DOMString,
code: DOMString,
@ -84,7 +86,7 @@ impl KeyboardEvent {
let ev = KeyboardEvent::new_uninitialized(window);
ev.InitKeyboardEvent(type_, canBubble, cancelable, view, key_string, location,
DOMString::new(), repeat, DOMString::new());
ev.key.set(key);
ev.key.set(logical_key(ch, key, location));
*ev.code.borrow_mut() = code;
ev.ctrl.set(ctrlKey);
ev.alt.set(altKey);
@ -103,7 +105,9 @@ impl KeyboardEvent {
init.parent.parent.parent.bubbles,
init.parent.parent.parent.cancelable,
init.parent.parent.view.r(),
init.parent.parent.detail, key_from_string(&init.key, init.location),
init.parent.parent.detail,
None,
key_from_string(&init.key, init.location),
init.key.clone(), init.code.clone(), init.location,
init.repeat, init.isComposing, init.parent.ctrlKey,
init.parent.altKey, init.parent.shiftKey, init.parent.metaKey,
@ -111,13 +115,13 @@ impl KeyboardEvent {
Ok(event)
}
pub fn key_properties(key: Key, mods: KeyModifiers)
pub fn key_properties(ch: Option<char>, key: Key, mods: KeyModifiers)
-> KeyEventProperties {
KeyEventProperties {
key_string: key_value(key, mods),
key_string: key_value(ch, key, mods),
code: code_value(key),
location: key_location(key),
char_code: key_charcode(key, mods),
char_code: ch.map(|ch| ch as u32),
key_code: key_keycode(key),
}
}
@ -147,11 +151,26 @@ impl KeyboardEvent {
}
}
fn logical_key(ch: Option<char>, key: Option<Key>, location: u32) -> Option<Key> {
if let Some(ch) = ch {
let key = key_from_string(&format!("{}", ch), location);
if key.is_some() {
return key;
}
}
key
}
// https://w3c.github.io/uievents-key/#key-value-tables
pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str {
pub fn key_value(ch: Option<char>, key: Key, mods: KeyModifiers) -> Cow<'static, str> {
if let Some(ch) = ch {
return Cow::from(format!("{}", ch));
}
let shift = mods.contains(constellation_msg::SHIFT);
match key {
Cow::from(match key {
Key::Space => " ",
Key::Apostrophe if shift => "\"",
Key::Apostrophe => "'",
@ -321,7 +340,7 @@ pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str {
Key::Menu => "ContextMenu",
Key::NavigateForward => "BrowserForward",
Key::NavigateBackward => "BrowserBack",
}
})
}
fn key_from_string(key_string: &str, location: u32) -> Option<Key> {
@ -647,16 +666,6 @@ fn key_location(key: Key) -> u32 {
}
}
// https://w3c.github.io/uievents/#dom-keyboardevent-charcode
fn key_charcode(key: Key, mods: KeyModifiers) -> Option<u32> {
let key_string = key_value(key, mods);
if key_string.len() == 1 {
Some(key_string.chars().next().unwrap() as u32)
} else {
None
}
}
// https://w3c.github.io/uievents/#legacy-key-models
fn key_keycode(key: Key) -> u32 {
match key {
@ -739,7 +748,7 @@ fn key_keycode(key: Key) -> u32 {
#[derive(HeapSizeOf)]
pub struct KeyEventProperties {
pub key_string: &'static str,
pub key_string: Cow<'static, str>,
pub code: &'static str,
pub location: u32,
pub char_code: Option<u32>,