Skip to content

Commit

Permalink
refactor(core): 💡key event
Browse files Browse the repository at this point in the history
  • Loading branch information
wjian23 authored and M-Adoo committed Oct 31, 2023
1 parent 335dac9 commit 9ca88ea
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 94 deletions.
14 changes: 8 additions & 6 deletions core/src/builtin_widgets/focus_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ mod tests {
};

use super::*;
use crate::{test_helper::*, window::DelayEvent};
use crate::test_helper::*;

#[test]
fn tab_scope() {
Expand Down Expand Up @@ -192,11 +192,13 @@ mod tests {
// will deal key event twice (inner and host).
wnd.draw_frame();

wnd.add_delay_event(DelayEvent::KeyDown {
id: wnd.focusing().unwrap(),
physical_key: PhysicalKey::Code(KeyCode::Digit1),
key: VirtualKey::Character("1".into()),
});
wnd.processes_keyboard_event(
PhysicalKey::Code(KeyCode::Digit0),
VirtualKey::Character("0".into()),
false,
KeyLocation::Standard,
ElementState::Pressed,
);

wnd.run_frame_tasks();
wnd.draw_frame();
Expand Down
2 changes: 1 addition & 1 deletion core/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mod character;
pub use character::*;
mod wheel;
pub use wheel::*;
pub use winit::keyboard::{Key as VirtualKey, KeyCode, ModifiersState, NamedKey, PhysicalKey};

pub(crate) mod focus_mgr;
mod listener_impl_helper;

Expand Down
36 changes: 15 additions & 21 deletions core/src/events/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{prelude::*, widget_tree::WidgetTree, window::DelayEvent};
use ribir_text::PIXELS_PER_EM;
use std::rc::{Rc, Weak};
use winit::{
event::{DeviceId, ElementState, Ime, KeyEvent, MouseButton, MouseScrollDelta, WindowEvent},
event::{DeviceId, ElementState, MouseButton, MouseScrollDelta, WindowEvent},
keyboard::ModifiersState,
};

Expand Down Expand Up @@ -55,38 +55,32 @@ impl Dispatcher {
WindowEvent::MouseInput { state, button, device_id, .. } => {
self.dispatch_mouse_input(device_id, state, button);
}
WindowEvent::KeyboardInput { event, .. } => {
self.dispatch_keyboard_input(event);
}
WindowEvent::Ime(ime) => {
if let Ime::Commit(s) = ime {
self.add_chars_event(s)
}
}
WindowEvent::MouseWheel { delta, .. } => self.dispatch_wheel(delta, wnd_factor),
_ => log::info!("not processed event {:?}", event),
}
}

pub fn dispatch_keyboard_input(&mut self, event: KeyEvent) {
pub fn dispatch_keyboard_input(
&mut self,
physical_key: PhysicalKey,
key: VirtualKey,
is_repeat: bool,
location: KeyLocation,
state: ElementState,
) {
let wnd = self.window();
if let Some(id) = wnd.focusing() {
let KeyEvent { physical_key, logical_key, text, .. } = event;
match event.state {
if let Some(focus_id) = wnd.focusing() {
let event = KeyboardEvent::new(wnd.id(), focus_id, physical_key, key, is_repeat, location);
match state {
ElementState::Pressed => {
wnd.add_delay_event(DelayEvent::KeyDown { id, physical_key, key: logical_key });
if let Some(text) = text {
self.add_chars_event(text.to_string());
}
}
ElementState::Released => {
wnd.add_delay_event(DelayEvent::KeyUp { id, physical_key, key: logical_key })
wnd.add_delay_event(DelayEvent::KeyDown(event));
}
ElementState::Released => wnd.add_delay_event(DelayEvent::KeyUp(event)),
};
}
}

pub fn add_chars_event(&mut self, chars: String) {
pub fn dispatch_receive_chars(&mut self, chars: String) {
let wnd = self.window();
if let Some(focus) = wnd.focusing() {
self
Expand Down
106 changes: 71 additions & 35 deletions core/src/events/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,33 @@ use crate::{
impl_listener, impl_multi_event_listener, prelude::*, window::WindowId,
};

pub use winit::keyboard::{
Key as VirtualKey, KeyCode, KeyLocation, ModifiersState, NamedKey, PhysicalKey,
};

#[derive(Debug)]
pub struct KeyboardEvent {
pub physical_key: PhysicalKey,
pub key: VirtualKey,
physical_key: PhysicalKey,
key: VirtualKey,
is_repeat: bool,
location: KeyLocation,
common: CommonEvent,
}

impl KeyboardEvent {
#[inline]
pub fn key_code(&self) -> &PhysicalKey { &self.physical_key }

#[inline]
pub fn key(&self) -> &VirtualKey { &self.key }

#[inline]
pub fn is_repeat(&self) -> bool { self.is_repeat }

#[inline]
pub fn location(&self) -> KeyLocation { self.location }
}

pub type KeyboardSubject = MutRefItemSubject<'static, AllKeyboard, Infallible>;

impl_multi_event_listener! {
Expand All @@ -34,19 +54,30 @@ impl_compose_child_with_focus_for_listener!(KeyboardListener);

impl KeyboardEvent {
#[inline]
pub fn new(physical_key: PhysicalKey, key: VirtualKey, id: WidgetId, wnd_id: WindowId) -> Self {
pub fn new(
wnd_id: WindowId,
id: WidgetId,
physical_key: PhysicalKey,
key: VirtualKey,
is_repeat: bool,
location: KeyLocation,
) -> Self {
Self {
physical_key,
key,
is_repeat,
location,
common: CommonEvent::new(id, wnd_id),
}
}
}

#[cfg(test)]
mod tests {
use winit::event::ElementState;

use super::*;
use crate::{test_helper::*, window::DelayEvent};
use crate::test_helper::*;
use std::{cell::RefCell, rc::Rc};

#[test]
Expand Down Expand Up @@ -90,45 +121,50 @@ mod tests {
let mut wnd = TestWindow::new(fn_widget!(w));
wnd.draw_frame();

let focusing = wnd.focusing().unwrap();

wnd.add_delay_event(DelayEvent::KeyDown {
id: focusing,
physical_key: PhysicalKey::Code(KeyCode::Digit0),
key: VirtualKey::Character("Key0".into()),
});
wnd.processes_keyboard_event(
PhysicalKey::Code(KeyCode::Digit0),
VirtualKey::Character("0".into()),
false,
KeyLocation::Standard,
ElementState::Pressed,
);

wnd.add_delay_event(DelayEvent::KeyUp {
id: focusing,
physical_key: PhysicalKey::Code(KeyCode::Digit0),
key: VirtualKey::Character("Key0".into()),
});
wnd.processes_keyboard_event(
PhysicalKey::Code(KeyCode::Digit0),
VirtualKey::Character("0".into()),
false,
KeyLocation::Standard,
ElementState::Released,
);

wnd.add_delay_event(DelayEvent::KeyDown {
id: focusing,
physical_key: PhysicalKey::Code(KeyCode::Digit1),
key: VirtualKey::Character("Key1".into()),
});
wnd.processes_keyboard_event(
PhysicalKey::Code(KeyCode::Digit1),
VirtualKey::Character("1".into()),
false,
KeyLocation::Standard,
ElementState::Pressed,
);

wnd.add_delay_event(DelayEvent::KeyUp {
id: focusing,
physical_key: PhysicalKey::Code(KeyCode::Digit1),
key: VirtualKey::Character("Key1".into()),
});
wnd.processes_keyboard_event(
PhysicalKey::Code(KeyCode::Digit1),
VirtualKey::Character("1".into()),
false,
KeyLocation::Standard,
ElementState::Released,
);

wnd.run_frame_tasks();

assert_eq!(
&*keys.borrow(),
&[
"key down capture Character(\"Key0\")",
"key down Character(\"Key0\")",
"key up capture Character(\"Key0\")",
"key up Character(\"Key0\")",
"key down capture Character(\"Key1\")",
"key down Character(\"Key1\")",
"key up capture Character(\"Key1\")",
"key up Character(\"Key1\")"
"key down capture Character(\"0\")",
"key down Character(\"0\")",
"key up capture Character(\"0\")",
"key up Character(\"0\")",
"key down capture Character(\"1\")",
"key down Character(\"1\")",
"key up capture Character(\"1\")",
"key up Character(\"1\")"
]
);
}
Expand Down
54 changes: 32 additions & 22 deletions core/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::{
rc::Rc,
time::Instant,
};
use winit::event::WindowEvent;
use winit::event::{ElementState, WindowEvent};
pub use winit::window::CursorIcon;

/// Window is the root to represent.
Expand Down Expand Up @@ -97,6 +97,27 @@ impl Window {
self.dispatcher.borrow_mut().dispatch(event, ratio);
}

pub fn processes_keyboard_event(
&self,
physical_key: PhysicalKey,
key: VirtualKey,
is_repeat: bool,
location: KeyLocation,
state: ElementState,
) {
self.dispatcher.borrow_mut().dispatch_keyboard_input(
physical_key,
key,
is_repeat,
location,
state,
);
}

pub fn processes_receive_chars(&self, chars: String) {
self.dispatcher.borrow_mut().dispatch_receive_chars(chars)
}

/// Request switch the focus to next widget.
pub fn request_next_focus(&self) { self.focus_mgr.borrow_mut().focus_next_widget(); }

Expand Down Expand Up @@ -402,18 +423,15 @@ impl Window {
let mut e = AllFocusBubble::FocusOut(e.into_inner());
self.bottom_up_emit::<FocusBubbleListener>(&mut e, bottom, up);
}
DelayEvent::KeyDown { id, physical_key, key } => {
let mut e = AllKeyboard::KeyDownCapture(KeyboardEvent::new(
physical_key,
key.clone(),
id,
self.id(),
));
DelayEvent::KeyDown(event) => {
let id = event.id();

let mut e = AllKeyboard::KeyDownCapture(event);
self.top_down_emit::<KeyboardListener>(&mut e, id, None);
let mut e = AllKeyboard::KeyDown(e.into_inner());
self.bottom_up_emit::<KeyboardListener>(&mut e, id, None);

if !e.is_prevent_default() && key == VirtualKey::Named(NamedKey::Tab) {
if !e.is_prevent_default() && *e.key() == VirtualKey::Named(NamedKey::Tab) {
let pressed_shift = {
let dispatcher = self.dispatcher.borrow();
dispatcher.info.modifiers().contains(ModifiersState::SHIFT)
Expand All @@ -427,9 +445,9 @@ impl Window {
}
}
}
DelayEvent::KeyUp { id, physical_key, key } => {
let mut e =
AllKeyboard::KeyUpCapture(KeyboardEvent::new(physical_key, key, id, self.id()));
DelayEvent::KeyUp(event) => {
let id = event.id();
let mut e = AllKeyboard::KeyUpCapture(event);
self.top_down_emit::<KeyboardListener>(&mut e, id, None);
let mut e = AllKeyboard::KeyUp(e.into_inner());
self.bottom_up_emit::<KeyboardListener>(&mut e, id, None);
Expand Down Expand Up @@ -588,16 +606,8 @@ pub(crate) enum DelayEvent {
bottom: WidgetId,
up: Option<WidgetId>,
},
KeyDown {
id: WidgetId,
physical_key: PhysicalKey,
key: VirtualKey,
},
KeyUp {
id: WidgetId,
physical_key: PhysicalKey,
key: VirtualKey,
},
KeyDown(KeyboardEvent),
KeyUp(KeyboardEvent),
Chars {
id: WidgetId,
chars: String,
Expand Down
2 changes: 1 addition & 1 deletion examples/wordle_game/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl Compose for Wordle {
e.chars.chars().for_each(|c| $this.write().guessing.enter_char(c))
},
on_key_down: move |e| {
match e.key {
match e.key() {
VirtualKey::Named(NamedKey::Backspace) => $this.write().guessing.delete_back_char(),
VirtualKey::Named(NamedKey::Enter) => {
match $this.write().guess() {
Expand Down
Loading

0 comments on commit 9ca88ea

Please sign in to comment.