druid_shell/
keyboard.rs

1// Copyright 2020 The Druid Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Keyboard types.
16
17// This is a reasonable lint, but we keep signatures in sync with the
18// bitflags implementation of the inner Modifiers type.
19#![allow(clippy::trivially_copy_pass_by_ref)]
20
21use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
22
23pub use keyboard_types::{Code, KeyState, Location};
24
25/// The meaning (mapped value) of a keypress.
26pub type KbKey = keyboard_types::Key;
27
28/// Information about a keyboard event.
29///
30/// Note that this type is similar to [`KeyboardEvent`] in keyboard-types,
31/// but has a few small differences for convenience.
32///
33/// [`KeyboardEvent`]: keyboard_types::KeyboardEvent
34#[non_exhaustive]
35#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
36pub struct KeyEvent {
37    /// Whether the key is pressed or released.
38    pub state: KeyState,
39    /// Logical key value.
40    pub key: KbKey,
41    /// Physical key position.
42    pub code: Code,
43    /// Location for keys with multiple instances on common keyboards.
44    pub location: Location,
45    /// Flags for pressed modifier keys.
46    pub mods: Modifiers,
47    /// True if the key is currently auto-repeated.
48    pub repeat: bool,
49    /// Events with this flag should be ignored in a text editor
50    /// and instead composition events should be used.
51    pub is_composing: bool,
52}
53
54/// The modifiers.
55///
56/// This type is a thin wrappers around [`keyboard_types::Modifiers`],
57/// mostly for the convenience methods. If those get upstreamed, it
58/// will simply become that type.
59///
60/// [`keyboard_types::Modifiers`]: keyboard_types::Modifiers
61#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
62pub struct Modifiers(keyboard_types::Modifiers);
63
64/// A convenience trait for creating Key objects.
65///
66/// This trait is implemented by [`KbKey`] itself and also strings, which are
67/// converted into the `Character` variant. It is defined this way and not
68/// using the standard `Into` mechanism because `KbKey` is a type in an external
69/// crate.
70///
71/// [`KbKey`]: KbKey
72pub trait IntoKey {
73    fn into_key(self) -> KbKey;
74}
75
76impl KeyEvent {
77    #[doc(hidden)]
78    /// Create a key event for testing purposes.
79    pub fn for_test(mods: impl Into<Modifiers>, key: impl IntoKey) -> KeyEvent {
80        let mods = mods.into();
81        let key = key.into_key();
82        KeyEvent {
83            key,
84            code: Code::Unidentified,
85            location: Location::Standard,
86            state: KeyState::Down,
87            mods,
88            is_composing: false,
89            repeat: false,
90        }
91    }
92}
93
94impl Modifiers {
95    pub const ALT: Modifiers = Modifiers(keyboard_types::Modifiers::ALT);
96    pub const ALT_GRAPH: Modifiers = Modifiers(keyboard_types::Modifiers::ALT_GRAPH);
97    pub const CAPS_LOCK: Modifiers = Modifiers(keyboard_types::Modifiers::CAPS_LOCK);
98    pub const CONTROL: Modifiers = Modifiers(keyboard_types::Modifiers::CONTROL);
99    pub const FN: Modifiers = Modifiers(keyboard_types::Modifiers::FN);
100    pub const FN_LOCK: Modifiers = Modifiers(keyboard_types::Modifiers::FN_LOCK);
101    pub const META: Modifiers = Modifiers(keyboard_types::Modifiers::META);
102    pub const NUM_LOCK: Modifiers = Modifiers(keyboard_types::Modifiers::NUM_LOCK);
103    pub const SCROLL_LOCK: Modifiers = Modifiers(keyboard_types::Modifiers::SCROLL_LOCK);
104    pub const SHIFT: Modifiers = Modifiers(keyboard_types::Modifiers::SHIFT);
105    pub const SYMBOL: Modifiers = Modifiers(keyboard_types::Modifiers::SYMBOL);
106    pub const SYMBOL_LOCK: Modifiers = Modifiers(keyboard_types::Modifiers::SYMBOL_LOCK);
107    pub const HYPER: Modifiers = Modifiers(keyboard_types::Modifiers::HYPER);
108    pub const SUPER: Modifiers = Modifiers(keyboard_types::Modifiers::SUPER);
109
110    /// Get the inner value.
111    ///
112    /// Note that this function might go away if our changes are upstreamed.
113    pub fn raw(&self) -> keyboard_types::Modifiers {
114        self.0
115    }
116
117    /// Determine whether Shift is set.
118    pub fn shift(&self) -> bool {
119        self.contains(Modifiers::SHIFT)
120    }
121
122    /// Determine whether Ctrl is set.
123    pub fn ctrl(&self) -> bool {
124        self.contains(Modifiers::CONTROL)
125    }
126
127    /// Determine whether Alt is set.
128    pub fn alt(&self) -> bool {
129        self.contains(Modifiers::ALT)
130    }
131
132    /// Determine whether Meta is set.
133    pub fn meta(&self) -> bool {
134        self.contains(Modifiers::META)
135    }
136
137    /// Returns an empty set of modifiers.
138    pub fn empty() -> Modifiers {
139        Default::default()
140    }
141
142    /// Returns `true` if no modifiers are set.
143    pub fn is_empty(&self) -> bool {
144        self.0.is_empty()
145    }
146
147    /// Returns `true` if all the modifiers in `other` are set.
148    pub fn contains(&self, other: Modifiers) -> bool {
149        self.0.contains(other.0)
150    }
151
152    /// Inserts or removes the specified modifiers depending on the passed value.
153    pub fn set(&mut self, other: Modifiers, value: bool) {
154        self.0.set(other.0, value)
155    }
156}
157
158impl BitAnd for Modifiers {
159    type Output = Self;
160
161    fn bitand(self, rhs: Self) -> Self {
162        Modifiers(self.0 & rhs.0)
163    }
164}
165
166impl BitAndAssign for Modifiers {
167    // rhs is the "right-hand side" of the expression `a &= b`
168    fn bitand_assign(&mut self, rhs: Self) {
169        *self = Modifiers(self.0 & rhs.0)
170    }
171}
172
173impl BitOr for Modifiers {
174    type Output = Self;
175
176    fn bitor(self, rhs: Self) -> Self {
177        Modifiers(self.0 | rhs.0)
178    }
179}
180
181impl BitOrAssign for Modifiers {
182    // rhs is the "right-hand side" of the expression `a &= b`
183    fn bitor_assign(&mut self, rhs: Self) {
184        *self = Modifiers(self.0 | rhs.0)
185    }
186}
187
188impl BitXor for Modifiers {
189    type Output = Self;
190
191    fn bitxor(self, rhs: Self) -> Self {
192        Modifiers(self.0 ^ rhs.0)
193    }
194}
195
196impl BitXorAssign for Modifiers {
197    // rhs is the "right-hand side" of the expression `a &= b`
198    fn bitxor_assign(&mut self, rhs: Self) {
199        *self = Modifiers(self.0 ^ rhs.0)
200    }
201}
202
203impl Not for Modifiers {
204    type Output = Self;
205
206    fn not(self) -> Self {
207        Modifiers(!self.0)
208    }
209}
210
211impl IntoKey for KbKey {
212    fn into_key(self) -> KbKey {
213        self
214    }
215}
216
217impl IntoKey for &str {
218    fn into_key(self) -> KbKey {
219        KbKey::Character(self.into())
220    }
221}