mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
Make the modifiers simple booleans in the key event
This will give a nicer API to expose to .60. If the struct weren't repr(C) then the booleans would be nicely packed, but alas that's not happening. On the other hand we're not keeping many instances of them around.
This commit is contained in:
parent
886dd425fc
commit
ae1178dd55
8 changed files with 59 additions and 125 deletions
|
@ -199,8 +199,6 @@ pub mod re_exports {
|
||||||
};
|
};
|
||||||
pub use sixtyfps_corelib::input::{
|
pub use sixtyfps_corelib::input::{
|
||||||
FocusEvent, InputEventResult, KeyEvent, KeyEventResult, KeyboardModifiers, MouseEvent,
|
FocusEvent, InputEventResult, KeyEvent, KeyEventResult, KeyboardModifiers, MouseEvent,
|
||||||
ALT_MODIFIER, CONTROL_MODIFIER, COPY_PASTE_MODIFIER, LOGO_MODIFIER, NO_MODIFIER,
|
|
||||||
SHIFT_MODIFIER,
|
|
||||||
};
|
};
|
||||||
pub use sixtyfps_corelib::item_tree::{
|
pub use sixtyfps_corelib::item_tree::{
|
||||||
item_offset, visit_item_tree, ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable,
|
item_offset, visit_item_tree, ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable,
|
||||||
|
|
|
@ -144,97 +144,37 @@ impl InternalKeyCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// KeyboardModifiers wraps a u32 that reserves a single bit for each
|
/// KeyboardModifier provides booleans to indicate possible modifier keys
|
||||||
/// possible modifier key on a keyboard, such as Shift, Control, etc.
|
/// on a keyboard, such as Shift, Control, etc.
|
||||||
///
|
///
|
||||||
/// On macOS, the command key is mapped to the logo modifier.
|
/// On macOS, the command key is mapped to the logo modifier.
|
||||||
///
|
///
|
||||||
/// On Windows, the windows key is mapped to the logo modifier.
|
/// On Windows, the windows key is mapped to the logo modifier.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct KeyboardModifiers(u32);
|
pub struct KeyboardModifiers {
|
||||||
/// KeyboardModifier wraps a u32 that has a single bit set to represent
|
/// Indicates the alt key on a keyboard.
|
||||||
/// a modifier key such as shift on a keyboard. Convenience constants such as
|
pub alt: bool,
|
||||||
/// [`NO_MODIFIER`], [`SHIFT_MODIFIER`], [`CONTROL_MODIFIER`], [`ALT_MODIFIER`]
|
/// Indicates the control key on a keyboard.
|
||||||
/// and [`LOGO_MODIFIER`] are provided.
|
pub control: bool,
|
||||||
#[derive(Copy, Clone, Debug)]
|
/// Indicates the shift key on a keyboard.
|
||||||
#[repr(C)]
|
pub shift: bool,
|
||||||
pub struct KeyboardModifier(u32);
|
/// Indicates the logo key on macOS and the windows key on Windows.
|
||||||
/// Convenience constant that indicates no modifier key being pressed on a keyboard.
|
pub logo: bool,
|
||||||
pub const NO_MODIFIER: KeyboardModifier = KeyboardModifier(0);
|
}
|
||||||
/// Convenience constant that indicates the shift key being pressed on a keyboard.
|
|
||||||
pub const SHIFT_MODIFIER: KeyboardModifier = KeyboardModifier(1);
|
|
||||||
/// Convenience constant that indicates the control key being pressed on a keyboard.
|
|
||||||
pub const CONTROL_MODIFIER: KeyboardModifier = KeyboardModifier(2);
|
|
||||||
/// Convenience constant that indicates the control key being pressed on a keyboard.
|
|
||||||
pub const ALT_MODIFIER: KeyboardModifier = KeyboardModifier(4);
|
|
||||||
/// Convenience constant that on macOS indicates the command key and on Windows the
|
|
||||||
/// windows key being pressed on a keyboard.
|
|
||||||
pub const LOGO_MODIFIER: KeyboardModifier = KeyboardModifier(8);
|
|
||||||
|
|
||||||
/// Convenience constant that is used to detect copy & paste related shortcuts, where
|
|
||||||
/// on macOS the modifier is the command key (aka LOGO_MODIFIER) and on Linux and Windows
|
|
||||||
/// it is control.
|
|
||||||
pub const COPY_PASTE_MODIFIER: KeyboardModifier =
|
|
||||||
if cfg!(target_os = "macos") { LOGO_MODIFIER } else { CONTROL_MODIFIER };
|
|
||||||
|
|
||||||
impl KeyboardModifiers {
|
impl KeyboardModifiers {
|
||||||
/// Returns true if this set of keyboard modifiers includes the given modifier; false otherwise.
|
/// Convenience function that is used to detect copy & paste related shortcuts, where
|
||||||
///
|
/// on macOS the modifier is the command key (aka logo) and on Linux and Windows
|
||||||
/// Arguments:
|
/// it is control.
|
||||||
/// * `modifier`: The keyboard modifier to test for, usually one of the provided convenience
|
pub fn is_copy_paste_modifier(&self) -> bool {
|
||||||
/// constants such as [`SHIFT_MODIFIER`].
|
match (self.alt, self.control, self.shift, self.logo) {
|
||||||
pub fn test(&self, modifier: KeyboardModifier) -> bool {
|
#[cfg(target_os = "macos")]
|
||||||
self.0 & modifier.0 != 0
|
(false, false, false, true) => true,
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
(false, true, false, false) => true,
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this set of keyboard modifiers consists of exactly the one specified
|
|
||||||
/// modifier; false otherwise.
|
|
||||||
///
|
|
||||||
/// Arguments:
|
|
||||||
/// * `modifier`: The only modifier that is allowed to be in this modifier set, in order
|
|
||||||
// for this function to return true;
|
|
||||||
pub fn test_exclusive(&self, modifier: KeyboardModifier) -> bool {
|
|
||||||
self.0 == modifier.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the shift key is part of this set of keyboard modifiers.
|
|
||||||
pub fn shift(&self) -> bool {
|
|
||||||
self.test(SHIFT_MODIFIER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the control key is part of this set of keyboard modifiers.
|
|
||||||
pub fn control(&self) -> bool {
|
|
||||||
self.test(CONTROL_MODIFIER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the alt key is part of this set of keyboard modifiers.
|
|
||||||
pub fn alt(&self) -> bool {
|
|
||||||
self.test(ALT_MODIFIER)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if on macOS the command key and on Windows the Windows key is part of this
|
|
||||||
/// set of keyboard modifiers.
|
|
||||||
pub fn logo(&self) -> bool {
|
|
||||||
self.test(LOGO_MODIFIER)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for KeyboardModifiers {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self(NO_MODIFIER.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<KeyboardModifier> for KeyboardModifiers {
|
|
||||||
fn from(modifier: KeyboardModifier) -> Self {
|
|
||||||
Self(modifier.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::ops::BitOrAssign<KeyboardModifier> for KeyboardModifiers {
|
|
||||||
fn bitor_assign(&mut self, rhs: KeyboardModifier) {
|
|
||||||
self.0 |= rhs.0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,7 @@ impl Item for TextInput {
|
||||||
// Only insert/interpreter non-control character strings
|
// Only insert/interpreter non-control character strings
|
||||||
if !event_text.is_empty() && event_text.as_str().chars().all(|ch| !ch.is_control()) =>
|
if !event_text.is_empty() && event_text.as_str().chars().all(|ch| !ch.is_control()) =>
|
||||||
{
|
{
|
||||||
if modifiers.test_exclusive(crate::input::COPY_PASTE_MODIFIER) {
|
if modifiers.is_copy_paste_modifier() {
|
||||||
if event_text == "c" {
|
if event_text == "c" {
|
||||||
self.copy();
|
self.copy();
|
||||||
return KeyEventResult::EventAccepted;
|
return KeyEventResult::EventAccepted;
|
||||||
|
@ -385,7 +385,7 @@ enum AnchorMode {
|
||||||
|
|
||||||
impl From<KeyboardModifiers> for AnchorMode {
|
impl From<KeyboardModifiers> for AnchorMode {
|
||||||
fn from(modifiers: KeyboardModifiers) -> Self {
|
fn from(modifiers: KeyboardModifiers) -> Self {
|
||||||
if modifiers.shift() {
|
if modifiers.shift {
|
||||||
Self::KeepAnchor
|
Self::KeepAnchor
|
||||||
} else {
|
} else {
|
||||||
Self::MoveAnchor
|
Self::MoveAnchor
|
||||||
|
|
|
@ -10,7 +10,7 @@ LICENSE END */
|
||||||
//! Functions usefull for testing
|
//! Functions usefull for testing
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
use crate::input::{KeyEvent, KeyboardModifiers, MouseEvent, MouseEventType, SHIFT_MODIFIER};
|
use crate::input::{KeyEvent, KeyboardModifiers, MouseEvent, MouseEventType};
|
||||||
use crate::window::ComponentWindow;
|
use crate::window::ComponentWindow;
|
||||||
use crate::SharedString;
|
use crate::SharedString;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ pub extern "C" fn send_keyboard_string_sequence(
|
||||||
for ch in sequence.chars() {
|
for ch in sequence.chars() {
|
||||||
let mut modifiers = modifiers;
|
let mut modifiers = modifiers;
|
||||||
if ch.is_ascii_uppercase() {
|
if ch.is_ascii_uppercase() {
|
||||||
modifiers |= SHIFT_MODIFIER;
|
modifiers.shift = true;
|
||||||
}
|
}
|
||||||
let text: SharedString = ch.to_string().into();
|
let text: SharedString = ch.to_string().into();
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ LICENSE END */
|
||||||
*/
|
*/
|
||||||
use sixtyfps_corelib as corelib;
|
use sixtyfps_corelib as corelib;
|
||||||
|
|
||||||
|
use corelib::graphics::Point;
|
||||||
use corelib::input::{InternalKeyCode, KeyEvent, KeyboardModifiers, MouseEventType};
|
use corelib::input::{InternalKeyCode, KeyEvent, KeyboardModifiers, MouseEventType};
|
||||||
use corelib::window::*;
|
use corelib::window::*;
|
||||||
use corelib::{graphics::Point, input::NO_MODIFIER};
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ pub fn run() {
|
||||||
{
|
{
|
||||||
let modifiers = window.current_keyboard_modifiers();
|
let modifiers = window.current_keyboard_modifiers();
|
||||||
|
|
||||||
if !modifiers.control() && !modifiers.alt() && !modifiers.logo() {
|
if !modifiers.control && !modifiers.alt && !modifiers.logo {
|
||||||
let key_event = KeyEvent::KeyReleased {
|
let key_event = KeyEvent::KeyReleased {
|
||||||
text: ch.to_string().into(),
|
text: ch.to_string().into(),
|
||||||
modifiers,
|
modifiers,
|
||||||
|
@ -382,19 +382,12 @@ pub fn run() {
|
||||||
if let Some(Some(window)) =
|
if let Some(Some(window)) =
|
||||||
windows.borrow().get(&window_id).map(|weakref| weakref.upgrade())
|
windows.borrow().get(&window_id).map(|weakref| weakref.upgrade())
|
||||||
{
|
{
|
||||||
let mut modifiers: KeyboardModifiers = NO_MODIFIER.into();
|
let modifiers = KeyboardModifiers {
|
||||||
if state.shift() {
|
shift: state.shift(),
|
||||||
modifiers |= corelib::input::SHIFT_MODIFIER;
|
alt: state.alt(),
|
||||||
}
|
control: state.ctrl(),
|
||||||
if state.alt() {
|
logo: state.logo(),
|
||||||
modifiers |= corelib::input::ALT_MODIFIER;
|
};
|
||||||
}
|
|
||||||
if state.ctrl() {
|
|
||||||
modifiers |= corelib::input::CONTROL_MODIFIER;
|
|
||||||
}
|
|
||||||
if state.logo() {
|
|
||||||
modifiers |= corelib::input::LOGO_MODIFIER;
|
|
||||||
}
|
|
||||||
window.set_current_keyboard_modifiers(modifiers);
|
window.set_current_keyboard_modifiers(modifiers);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -647,19 +647,12 @@ impl QtWindow {
|
||||||
fn key_event(&self, key: i32, text: qttypes::QString, modif: u32, released: bool) {
|
fn key_event(&self, key: i32, text: qttypes::QString, modif: u32, released: bool) {
|
||||||
sixtyfps_corelib::animations::update_animations();
|
sixtyfps_corelib::animations::update_animations();
|
||||||
let text: String = text.into();
|
let text: String = text.into();
|
||||||
let mut modifiers = sixtyfps_corelib::input::KeyboardModifiers::default();
|
let modifiers = sixtyfps_corelib::input::KeyboardModifiers {
|
||||||
if modif & key_generated::Qt_KeyboardModifier_ControlModifier != 0 {
|
control: modif & key_generated::Qt_KeyboardModifier_ControlModifier != 0,
|
||||||
modifiers |= sixtyfps_corelib::input::CONTROL_MODIFIER
|
alt: modif & key_generated::Qt_KeyboardModifier_AltModifier != 0,
|
||||||
}
|
shift: modif & key_generated::Qt_KeyboardModifier_ShiftModifier != 0,
|
||||||
if modif & key_generated::Qt_KeyboardModifier_AltModifier != 0 {
|
logo: modif & key_generated::Qt_KeyboardModifier_MetaModifier != 0,
|
||||||
modifiers |= sixtyfps_corelib::input::ALT_MODIFIER
|
};
|
||||||
}
|
|
||||||
if modif & key_generated::Qt_KeyboardModifier_ShiftModifier != 0 {
|
|
||||||
modifiers |= sixtyfps_corelib::input::SHIFT_MODIFIER
|
|
||||||
}
|
|
||||||
if modif & key_generated::Qt_KeyboardModifier_MetaModifier != 0 {
|
|
||||||
modifiers |= sixtyfps_corelib::input::LOGO_MODIFIER
|
|
||||||
}
|
|
||||||
|
|
||||||
let text = match key as key_generated::Qt_Key {
|
let text = match key as key_generated::Qt_Key {
|
||||||
key_generated::Qt_Key_Key_Left => Some(InternalKeyCode::Left),
|
key_generated::Qt_Key_Key_Left => Some(InternalKeyCode::Left),
|
||||||
|
|
|
@ -27,6 +27,11 @@ const HOME_CODE: char = '\u{0002}'; // start of text
|
||||||
const END_CODE: char = '\u{0003}'; // end of text
|
const END_CODE: char = '\u{0003}'; // end of text
|
||||||
const BACK_CODE: char = '\u{0007}'; // backspace \b
|
const BACK_CODE: char = '\u{0007}'; // backspace \b
|
||||||
|
|
||||||
|
let shift_modifier = sixtyfps::re_exports::KeyboardModifiers {
|
||||||
|
shift: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
let instance = TestCase::new();
|
let instance = TestCase::new();
|
||||||
sixtyfps::testing::send_mouse_click(&instance, 50., 50.);
|
sixtyfps::testing::send_mouse_click(&instance, 50., 50.);
|
||||||
assert!(instance.get_input_focused());
|
assert!(instance.get_input_focused());
|
||||||
|
@ -35,9 +40,9 @@ sixtyfps::testing::send_keyboard_string_sequence(&instance, "Test");
|
||||||
assert_eq!(instance.get_test_text(), "Test");
|
assert_eq!(instance.get_test_text(), "Test");
|
||||||
assert!(!instance.get_has_selection());
|
assert!(!instance.get_has_selection());
|
||||||
|
|
||||||
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::SHIFT_MODIFIER.into());
|
sixtyfps::testing::set_current_keyboard_modifiers(&instance, shift_modifier);
|
||||||
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
||||||
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::NO_MODIFIER.into());
|
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::KeyboardModifiers::default());
|
||||||
assert!(instance.get_has_selection());
|
assert!(instance.get_has_selection());
|
||||||
sixtyfps::testing::send_keyboard_string_sequence(&instance, &BACK_CODE.to_string());
|
sixtyfps::testing::send_keyboard_string_sequence(&instance, &BACK_CODE.to_string());
|
||||||
assert!(!instance.get_has_selection());
|
assert!(!instance.get_has_selection());
|
||||||
|
@ -57,9 +62,9 @@ sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string
|
||||||
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
||||||
assert_eq!(instance.get_test_cursor_pos(), 0);
|
assert_eq!(instance.get_test_cursor_pos(), 0);
|
||||||
|
|
||||||
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::SHIFT_MODIFIER.into());
|
sixtyfps::testing::set_current_keyboard_modifiers(&instance, shift_modifier);
|
||||||
sixtyfps::testing::send_keyboard_string_sequence(&instance, &END_CODE.to_string());
|
sixtyfps::testing::send_keyboard_string_sequence(&instance, &END_CODE.to_string());
|
||||||
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::NO_MODIFIER.into());
|
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::KeyboardModifiers::default());
|
||||||
assert!(instance.get_has_selection());
|
assert!(instance.get_has_selection());
|
||||||
assert_eq!(instance.get_test_cursor_pos(), 2);
|
assert_eq!(instance.get_test_cursor_pos(), 2);
|
||||||
assert_eq!(instance.get_test_anchor_pos(), 0);
|
assert_eq!(instance.get_test_anchor_pos(), 0);
|
||||||
|
@ -67,9 +72,9 @@ assert_eq!(instance.get_test_anchor_pos(), 0);
|
||||||
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
||||||
assert!(!instance.get_has_selection());
|
assert!(!instance.get_has_selection());
|
||||||
|
|
||||||
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::SHIFT_MODIFIER.into());
|
sixtyfps::testing::set_current_keyboard_modifiers(&instance, shift_modifier);
|
||||||
sixtyfps::testing::send_keyboard_string_sequence(&instance, &HOME_CODE.to_string());
|
sixtyfps::testing::send_keyboard_string_sequence(&instance, &HOME_CODE.to_string());
|
||||||
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::NO_MODIFIER.into());
|
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::KeyboardModifiers::default());
|
||||||
assert!(instance.get_has_selection());
|
assert!(instance.get_has_selection());
|
||||||
assert_eq!(instance.get_test_cursor_pos(), 0);
|
assert_eq!(instance.get_test_cursor_pos(), 0);
|
||||||
assert_eq!(instance.get_test_anchor_pos(), 1);
|
assert_eq!(instance.get_test_anchor_pos(), 1);
|
||||||
|
|
|
@ -24,6 +24,11 @@ TestCase := TextInput {
|
||||||
const LEFT_CODE: char = '\u{000E}'; // shift out
|
const LEFT_CODE: char = '\u{000E}'; // shift out
|
||||||
const BACK_CODE: char = '\u{0007}'; // backspace \b
|
const BACK_CODE: char = '\u{0007}'; // backspace \b
|
||||||
|
|
||||||
|
let shift_modifier = sixtyfps::re_exports::KeyboardModifiers {
|
||||||
|
shift: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
let instance = TestCase::new();
|
let instance = TestCase::new();
|
||||||
sixtyfps::testing::send_mouse_click(&instance, 50., 50.);
|
sixtyfps::testing::send_mouse_click(&instance, 50., 50.);
|
||||||
assert!(instance.get_input_focused());
|
assert!(instance.get_input_focused());
|
||||||
|
@ -32,7 +37,7 @@ sixtyfps::testing::send_keyboard_string_sequence(&instance, "😍");
|
||||||
assert_eq!(instance.get_test_text(), "😍");
|
assert_eq!(instance.get_test_text(), "😍");
|
||||||
assert!(!instance.get_has_selection());
|
assert!(!instance.get_has_selection());
|
||||||
|
|
||||||
sixtyfps::testing::set_current_keyboard_modifiers(&instance, sixtyfps::re_exports::SHIFT_MODIFIER.into());
|
sixtyfps::testing::set_current_keyboard_modifiers(&instance, shift_modifier);
|
||||||
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
sixtyfps::testing::send_keyboard_string_sequence(&instance, &LEFT_CODE.to_string());
|
||||||
assert!(instance.get_has_selection());
|
assert!(instance.get_has_selection());
|
||||||
assert_eq!(instance.get_test_cursor_pos(), 0);
|
assert_eq!(instance.get_test_cursor_pos(), 0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue