Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard event rework #1049

Merged
merged 23 commits into from
Jun 29, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions druid-shell/examples/perftest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ use time::Instant;
use piet_common::kurbo::{Line, Rect, Size};
use piet_common::{Color, FontBuilder, Piet, RenderContext, Text, TextLayoutBuilder};

use druid_shell::keyboard_types::KeyboardEvent;
use druid_shell::{Application, WinHandler, WindowBuilder, WindowHandle};
use druid_shell::{Application, KeyEvent, WinHandler, WindowBuilder, WindowHandle};

const BG_COLOR: Color = Color::rgb8(0x27, 0x28, 0x22);
const FG_COLOR: Color = Color::rgb8(0xf0, 0xf0, 0xea);
Expand Down Expand Up @@ -115,7 +114,7 @@ impl WinHandler for PerfTest {
}
}

fn key_down(&mut self, event: KeyboardEvent) -> bool {
fn key_down(&mut self, event: KeyEvent) -> bool {
println!("keydown: {:?}", event);
false
}
Expand Down
7 changes: 3 additions & 4 deletions druid-shell/examples/shello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ use std::any::Any;
use druid_shell::kurbo::{Line, Rect, Size};
use druid_shell::piet::{Color, RenderContext};

use druid_shell::keyboard_types::KeyboardEvent;
use druid_shell::{
Application, Cursor, FileDialogOptions, FileSpec, HotKey, Menu, MouseEvent, SysMods,
Application, Cursor, FileDialogOptions, FileSpec, HotKey, KeyEvent, Menu, MouseEvent, SysMods,
TimerToken, WinHandler, WindowBuilder, WindowHandle,
};

Expand Down Expand Up @@ -63,12 +62,12 @@ impl WinHandler for HelloState {
}
}

fn key_down(&mut self, event: KeyboardEvent) -> bool {
fn key_down(&mut self, event: KeyEvent) -> bool {
println!("keydown: {:?}", event);
false
}

fn key_up(&mut self, event: KeyboardEvent) {
fn key_up(&mut self, event: KeyEvent) {
println!("keyup: {:?}", event);
}

Expand Down
89 changes: 19 additions & 70 deletions druid-shell/src/hotkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::borrow::Borrow;

use log::warn;

use crate::keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
use crate::{IntoKey, KbKey, KeyEvent, Modifiers};

// TODO: fix docstring
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤓


Expand All @@ -32,47 +32,33 @@ use crate::keyboard_types::{Code, Key, KeyState, KeyboardEvent, Location, Modifi
/// [`SysMods`] matches the Command key on macOS and Ctrl elsewhere:
///
/// ```
/// use druid_shell::{key_event_for_test, HotKey, RawMods, SysMods};
/// use druid_shell::keyboard_types::Key;
/// use druid_shell::{HotKey, KbKey, KeyEvent, RawMods, SysMods};
///
/// let hotkey = HotKey::new(SysMods::Cmd, "a");
///
/// #[cfg(target_os = "macos")]
/// assert!(hotkey.matches(key_event_for_test(RawMods::Meta, "a")));
/// assert!(hotkey.matches(KeyEvent::for_test(RawMods::Meta, "a")));
///
/// #[cfg(target_os = "windows")]
/// assert!(hotkey.matches(key_event_for_test(RawMods::Ctrl, "a")));
/// assert!(hotkey.matches(KeyEvent::for_test(RawMods::Ctrl, "a")));
/// ```
///
/// `None` matches only the key without modifiers:
///
/// ```
/// use druid_shell::{key_event_for_test, HotKey, RawMods, SysMods};
/// use druid_shell::keyboard_types::Key;
/// use druid_shell::{HotKey, KbKey, KeyEvent, RawMods, SysMods};
///
/// let hotkey = HotKey::new(None, Key::ArrowLeft);
/// let hotkey = HotKey::new(None, KbKey::ArrowLeft);
///
/// assert!(hotkey.matches(key_event_for_test(RawMods::None, Key::ArrowLeft)));
/// assert!(!hotkey.matches(key_event_for_test(RawMods::Ctrl, Key::ArrowLeft)));
/// assert!(hotkey.matches(KeyEvent::for_test(RawMods::None, KbKey::ArrowLeft)));
/// assert!(!hotkey.matches(KeyEvent::for_test(RawMods::Ctrl, KbKey::ArrowLeft)));
/// ```
///
/// [`SysMods`]: enum.SysMods.html
#[derive(Debug, Clone)]
pub struct HotKey {
pub(crate) mods: RawMods,
pub(crate) key: Key,
}

/// A convenience trait for creating Key objects.
///
/// This trait is implemented by [`Key`] itself and also strings, which are
/// converted into the `Character` variant. It is defined this way and not
/// using the standard `Into` mechanism because `Key` is a type in an external
/// crate.
///
/// [`Key`]: keyboard_types::Key
pub trait IntoKey {
fn into_key(self) -> Key;
pub(crate) key: KbKey,
}

impl HotKey {
Expand All @@ -83,16 +69,15 @@ impl HotKey {
/// 'Command' key on macOS with the 'Ctrl' key on other platforms.
///
/// The second argument describes the non-modifier key. This can be either
/// a `&str` or a [`Key`]; the former is merely a convenient
/// shorthand for `Key::Character()`.
/// a `&str` or a [`KbKey`]; the former is merely a convenient
/// shorthand for `KbKey::Character()`.
///
/// # Examples
/// ```
/// use druid_shell::{HotKey, RawMods, SysMods};
/// use druid_shell::keyboard_types::Key;
/// use druid_shell::{HotKey, KbKey, RawMods, SysMods};
///
/// let select_all = HotKey::new(SysMods::Cmd, "a");
/// let esc = HotKey::new(None, Key::Escape);
/// let esc = HotKey::new(None, KbKey::Escape);
/// let macos_fullscreen = HotKey::new(RawMods::CtrlMeta, "f");
/// ```
///
Expand All @@ -109,7 +94,7 @@ impl HotKey {

//TODO: figure out if we need to be normalizing case or something?
fn warn_if_needed(self) -> Self {
if let Key::Character(s) = &self.key {
if let KbKey::Character(s) = &self.key {
let km: Modifiers = self.mods.into();
if km.contains(Modifiers::SHIFT) && s.chars().any(|c| c.is_uppercase()) {
warn!(
Expand All @@ -125,7 +110,7 @@ impl HotKey {
/// Returns `true` if this [`KeyboardEvent`] matches this `HotKey`.
///
/// [`KeyboardEvent`]: keyboard_types::KeyEvent
pub fn matches(&self, event: impl Borrow<KeyboardEvent>) -> bool {
pub fn matches(&self, event: impl Borrow<KeyEvent>) -> bool {
let event = event.borrow();
self.mods == event.modifiers && self.key == event.key
}
Expand Down Expand Up @@ -221,18 +206,10 @@ impl From<RawMods> for Modifiers {
RawMods::AltCtrlMetaShift => (true, true, true, true),
};
let mut mods = Modifiers::empty();
if alt {
mods |= Modifiers::ALT;
}
if ctrl {
mods |= Modifiers::CONTROL;
}
if meta {
mods |= Modifiers::META;
}
if shift {
mods |= Modifiers::SHIFT;
}
mods.set(Modifiers::ALT, alt);
mods.set(Modifiers::CONTROL, ctrl);
mods.set(Modifiers::META, meta);
mods.set(Modifiers::SHIFT, shift);
mods
}
}
Expand Down Expand Up @@ -266,31 +243,3 @@ impl From<SysMods> for RawMods {
}
}
}

impl IntoKey for Key {
fn into_key(self) -> Key {
self
}
}

impl IntoKey for &str {
fn into_key(self) -> Key {
Key::Character(self.into())
}
}

#[allow(unused)]
/// Create a key event for testing purposes.
pub fn key_event_for_test(mods: impl Into<Modifiers>, key: impl IntoKey) -> KeyboardEvent {
let modifiers = mods.into();
let key = key.into_key();
KeyboardEvent {
key,
code: Code::Unidentified,
location: Location::Standard,
state: KeyState::Down,
modifiers,
is_composing: false,
repeat: false,
}
}
Loading