Overhaul the Keyboard API
Overhaul the keyboard API in winit to mimic the W3C specification
to achieve better crossplatform parity. The `KeyboardInput` event
is now uses `KeyEvent` which consists of:
- `physical_key` - a cross platform way to refer to scancodes;
- `logical_key` - keysym value, which shows your key respecting the
layout;
- `text` - the text produced by this keypress;
- `location` - the location of the key on the keyboard;
- `repeat` - whether the key was produced by the repeat.
And also a `platform_specific` field which encapsulates extra
information on desktop platforms, like key without modifiers
and text with all modifiers.
The `Modifiers` were also slightly reworked as in, the information
whether the left or right modifier is pressed is now also exposed
on platforms where it could be queried reliably. The support was
also added for the web and orbital platforms finishing the API
change.
This change made the `OptionAsAlt` API on macOS redundant thus it
was removed all together.
Co-authored-by: Artúr Kovács <kovacs.artur.barnabas@gmail.com>
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
Co-authored-by: daxpedda <daxpedda@gmail.com>
Fixes: #2631.
Fixes: #2055.
Fixes: #2032.
Fixes: #1904.
Fixes: #1810.
Fixes: #1700.
Fixes: #1443.
Fixes: #1343.
Fixes: #1208.
Fixes: #1151.
Fixes: #812.
Fixes: #600.
Fixes: #361.
Fixes: #343.
This commit is contained in:
parent
f3f46cb3f6
commit
918430979f
81 changed files with 9577 additions and 3419 deletions
|
|
@ -1,23 +1,19 @@
|
|||
use std::{cell::RefCell, collections::HashMap, rc::Rc, slice, sync::Arc};
|
||||
|
||||
use libc::{c_char, c_int, c_long, c_uint, c_ulong};
|
||||
use libc::{c_char, c_int, c_long, c_ulong};
|
||||
|
||||
use super::{
|
||||
events, ffi, get_xtarget, mkdid, mkwid, monitor, util, Device, DeviceId, DeviceInfo, Dnd,
|
||||
DndState, GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId,
|
||||
XExtension,
|
||||
ffi, get_xtarget, mkdid, mkwid, monitor, util, Device, DeviceId, DeviceInfo, Dnd, DndState,
|
||||
GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId, XExtension,
|
||||
};
|
||||
|
||||
use util::modifiers::{ModifierKeyState, ModifierKeymap};
|
||||
|
||||
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest};
|
||||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
event::{
|
||||
DeviceEvent, ElementState, Event, Ime, KeyboardInput, ModifiersState, TouchPhase,
|
||||
WindowEvent,
|
||||
},
|
||||
event::{DeviceEvent, ElementState, Event, Ime, RawKeyEvent, TouchPhase, WindowEvent},
|
||||
event_loop::EventLoopWindowTarget as RootELW,
|
||||
keyboard::ModifiersState,
|
||||
platform_impl::platform::common::{keymap, xkb_state::KbdState},
|
||||
};
|
||||
|
||||
/// The X11 documentation states: "Keycodes lie in the inclusive range `[8, 255]`".
|
||||
|
|
@ -30,9 +26,9 @@ pub(super) struct EventProcessor<T: 'static> {
|
|||
pub(super) randr_event_offset: c_int,
|
||||
pub(super) devices: RefCell<HashMap<DeviceId, Device>>,
|
||||
pub(super) xi2ext: XExtension,
|
||||
pub(super) xkbext: XExtension,
|
||||
pub(super) target: Rc<RootELW<T>>,
|
||||
pub(super) mod_keymap: ModifierKeymap,
|
||||
pub(super) device_mod_state: ModifierKeyState,
|
||||
pub(super) kb_state: KbdState,
|
||||
// Number of touch events currently in progress
|
||||
pub(super) num_touch: u32,
|
||||
pub(super) first_touch: Option<u64>,
|
||||
|
|
@ -134,47 +130,8 @@ impl<T: 'static> EventProcessor<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
// We can't call a `&mut self` method because of the above borrow,
|
||||
// so we use this macro for repeated modifier state updates.
|
||||
macro_rules! update_modifiers {
|
||||
( $state:expr , $modifier:expr ) => {{
|
||||
match ($state, $modifier) {
|
||||
(state, modifier) => {
|
||||
if let Some(modifiers) =
|
||||
self.device_mod_state.update_state(&state, modifier)
|
||||
{
|
||||
if let Some(window_id) = self.active_window {
|
||||
callback(Event::WindowEvent {
|
||||
window_id: mkwid(window_id),
|
||||
event: WindowEvent::ModifiersChanged(modifiers),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
let event_type = xev.get_type();
|
||||
match event_type {
|
||||
ffi::MappingNotify => {
|
||||
let mapping: &ffi::XMappingEvent = xev.as_ref();
|
||||
|
||||
if mapping.request == ffi::MappingModifier
|
||||
|| mapping.request == ffi::MappingKeyboard
|
||||
{
|
||||
unsafe {
|
||||
(wt.xconn.xlib.XRefreshKeyboardMapping)(xev.as_mut());
|
||||
}
|
||||
wt.xconn
|
||||
.check_errors()
|
||||
.expect("Failed to call XRefreshKeyboardMapping");
|
||||
|
||||
self.mod_keymap.reset_from_x_connection(&wt.xconn);
|
||||
self.device_mod_state.update_keymap(&self.mod_keymap);
|
||||
}
|
||||
}
|
||||
|
||||
ffi::ClientMessage => {
|
||||
let client_msg: &ffi::XClientMessageEvent = xev.as_ref();
|
||||
|
||||
|
|
@ -577,90 +534,35 @@ impl<T: 'static> EventProcessor<T> {
|
|||
}
|
||||
}
|
||||
|
||||
ffi::KeyPress | ffi::KeyRelease => {
|
||||
use crate::event::ElementState::{Pressed, Released};
|
||||
|
||||
// Note that in compose/pre-edit sequences, this will always be Released.
|
||||
let state = if xev.get_type() == ffi::KeyPress {
|
||||
Pressed
|
||||
} else {
|
||||
Released
|
||||
};
|
||||
|
||||
// Note that in compose/pre-edit sequences, we'll always receive KeyRelease events
|
||||
ffi::KeyPress => {
|
||||
let xkev: &mut ffi::XKeyEvent = xev.as_mut();
|
||||
|
||||
let window = xkev.window;
|
||||
let window_id = mkwid(window);
|
||||
|
||||
// Standard virtual core keyboard ID. XInput2 needs to be used to get a reliable
|
||||
// value, though this should only be an issue under multiseat configurations.
|
||||
let device = util::VIRTUAL_CORE_KEYBOARD;
|
||||
let device_id = mkdid(device);
|
||||
let keycode = xkev.keycode;
|
||||
let written = if let Some(ic) = wt.ime.borrow().get_context(window) {
|
||||
wt.xconn.lookup_utf8(ic, xkev)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
// When a compose sequence or IME pre-edit is finished, it ends in a KeyPress with
|
||||
// a keycode of 0.
|
||||
if keycode != 0 && !self.is_composing {
|
||||
let scancode = keycode - KEYCODE_OFFSET as u32;
|
||||
let keysym = wt.xconn.lookup_keysym(xkev);
|
||||
let virtual_keycode = events::keysym_to_element(keysym as c_uint);
|
||||
|
||||
update_modifiers!(
|
||||
ModifiersState::from_x11_mask(xkev.state),
|
||||
self.mod_keymap.get_modifier(xkev.keycode as ffi::KeyCode)
|
||||
);
|
||||
|
||||
let modifiers = self.device_mod_state.modifiers();
|
||||
|
||||
#[allow(deprecated)]
|
||||
callback(Event::WindowEvent {
|
||||
// If we're composing right now, send the string we've got from X11 via
|
||||
// Ime::Commit.
|
||||
if self.is_composing && xkev.keycode == 0 && !written.is_empty() {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id,
|
||||
input: KeyboardInput {
|
||||
state,
|
||||
scancode,
|
||||
virtual_keycode,
|
||||
modifiers,
|
||||
},
|
||||
is_synthetic: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
|
||||
};
|
||||
callback(event);
|
||||
|
||||
if state == Pressed {
|
||||
let written = if let Some(ic) = wt.ime.borrow().get_context(window) {
|
||||
wt.xconn.lookup_utf8(ic, xkev)
|
||||
} else {
|
||||
return;
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Ime(Ime::Commit(written)),
|
||||
};
|
||||
|
||||
// If we're composing right now, send the string we've got from X11 via
|
||||
// Ime::Commit.
|
||||
if self.is_composing && keycode == 0 && !written.is_empty() {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Ime(Ime::Preedit(String::new(), None)),
|
||||
};
|
||||
callback(event);
|
||||
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Ime(Ime::Commit(written)),
|
||||
};
|
||||
|
||||
self.is_composing = false;
|
||||
callback(event);
|
||||
} else {
|
||||
for chr in written.chars() {
|
||||
let event = Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ReceivedCharacter(chr),
|
||||
};
|
||||
|
||||
callback(event);
|
||||
}
|
||||
}
|
||||
self.is_composing = false;
|
||||
callback(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -696,9 +598,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
let modifiers = ModifiersState::from_x11(&xev.mods);
|
||||
update_modifiers!(modifiers, None);
|
||||
|
||||
let state = if xev.evtype == ffi::XI_ButtonPress {
|
||||
Pressed
|
||||
} else {
|
||||
|
|
@ -711,7 +610,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
device_id,
|
||||
state,
|
||||
button: Left,
|
||||
modifiers,
|
||||
},
|
||||
}),
|
||||
ffi::Button2 => callback(Event::WindowEvent {
|
||||
|
|
@ -720,7 +618,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
device_id,
|
||||
state,
|
||||
button: Middle,
|
||||
modifiers,
|
||||
},
|
||||
}),
|
||||
ffi::Button3 => callback(Event::WindowEvent {
|
||||
|
|
@ -729,7 +626,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
device_id,
|
||||
state,
|
||||
button: Right,
|
||||
modifiers,
|
||||
},
|
||||
}),
|
||||
|
||||
|
|
@ -750,7 +646,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
_ => unreachable!(),
|
||||
},
|
||||
phase: TouchPhase::Moved,
|
||||
modifiers,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -762,7 +657,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
device_id,
|
||||
state,
|
||||
button: Other(x as u16),
|
||||
modifiers,
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
|
@ -773,9 +667,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
let window_id = mkwid(xev.event);
|
||||
let new_cursor_pos = (xev.event_x, xev.event_y);
|
||||
|
||||
let modifiers = ModifiersState::from_x11(&xev.mods);
|
||||
update_modifiers!(modifiers, None);
|
||||
|
||||
let cursor_moved = self.with_window(xev.event, |window| {
|
||||
let mut shared_state_lock = window.shared_state_lock();
|
||||
util::maybe_change(&mut shared_state_lock.cursor_pos, new_cursor_pos)
|
||||
|
|
@ -788,7 +679,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
event: CursorMoved {
|
||||
device_id,
|
||||
position,
|
||||
modifiers,
|
||||
},
|
||||
});
|
||||
} else if cursor_moved.is_none() {
|
||||
|
|
@ -835,7 +725,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
}
|
||||
},
|
||||
phase: TouchPhase::Moved,
|
||||
modifiers,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
|
|
@ -889,25 +778,11 @@ impl<T: 'static> EventProcessor<T> {
|
|||
|
||||
let position = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
|
||||
// The mods field on this event isn't actually populated, so query the
|
||||
// pointer device. In the future, we can likely remove this round-trip by
|
||||
// relying on `Xkb` for modifier values.
|
||||
//
|
||||
// This needs to only be done after confirming the window still exists,
|
||||
// since otherwise we risk getting a `BadWindow` error if the window was
|
||||
// dropped with queued events.
|
||||
let modifiers = wt
|
||||
.xconn
|
||||
.query_pointer(xev.event, xev.deviceid)
|
||||
.expect("Failed to query pointer device")
|
||||
.get_modifier_state();
|
||||
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: CursorMoved {
|
||||
device_id,
|
||||
position,
|
||||
modifiers,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -935,10 +810,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
.focus(xev.event)
|
||||
.expect("Failed to focus input context");
|
||||
|
||||
let modifiers = ModifiersState::from_x11(&xev.mods);
|
||||
|
||||
self.device_mod_state.update_state(&modifiers, None);
|
||||
|
||||
if self.active_window != Some(xev.event) {
|
||||
self.active_window = Some(xev.event);
|
||||
|
||||
|
|
@ -956,10 +827,12 @@ impl<T: 'static> EventProcessor<T> {
|
|||
event: Focused(true),
|
||||
});
|
||||
|
||||
let modifiers: crate::keyboard::ModifiersState =
|
||||
self.kb_state.mods_state().into();
|
||||
if !modifiers.is_empty() {
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ModifiersChanged(modifiers),
|
||||
event: WindowEvent::ModifiersChanged(modifiers.into()),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -977,7 +850,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
event: CursorMoved {
|
||||
device_id: mkdid(pointer_id),
|
||||
position,
|
||||
modifiers,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -986,8 +858,7 @@ impl<T: 'static> EventProcessor<T> {
|
|||
wt,
|
||||
window_id,
|
||||
ElementState::Pressed,
|
||||
&self.mod_keymap,
|
||||
&mut self.device_mod_state,
|
||||
&mut self.kb_state,
|
||||
&mut callback,
|
||||
);
|
||||
}
|
||||
|
|
@ -1013,14 +884,15 @@ impl<T: 'static> EventProcessor<T> {
|
|||
wt,
|
||||
window_id,
|
||||
ElementState::Released,
|
||||
&self.mod_keymap,
|
||||
&mut self.device_mod_state,
|
||||
&mut self.kb_state,
|
||||
&mut callback,
|
||||
);
|
||||
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::ModifiersChanged(ModifiersState::empty()),
|
||||
event: WindowEvent::ModifiersChanged(
|
||||
ModifiersState::empty().into(),
|
||||
),
|
||||
});
|
||||
|
||||
if let Some(window) = self.with_window(xev.event, Arc::clone) {
|
||||
|
|
@ -1045,7 +917,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
};
|
||||
if self.window_exists(xev.event) {
|
||||
let id = xev.detail as u64;
|
||||
let modifiers = self.device_mod_state.modifiers();
|
||||
let location = PhysicalPosition::new(xev.event_x, xev.event_y);
|
||||
|
||||
// Mouse cursor position changes when touch events are received.
|
||||
|
|
@ -1057,7 +928,6 @@ impl<T: 'static> EventProcessor<T> {
|
|||
event: WindowEvent::CursorMoved {
|
||||
device_id: mkdid(util::VIRTUAL_CORE_POINTER),
|
||||
position: location.cast(),
|
||||
modifiers,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -1143,6 +1013,39 @@ impl<T: 'static> EventProcessor<T> {
|
|||
}
|
||||
}
|
||||
|
||||
// The regular KeyPress event has a problem where if you press a dead key, a KeyPress
|
||||
// event won't be emitted. XInput 2 does not have this problem.
|
||||
ffi::XI_KeyPress | ffi::XI_KeyRelease if !self.is_composing => {
|
||||
if let Some(active_window) = self.active_window {
|
||||
let state = if xev.evtype == ffi::XI_KeyPress {
|
||||
Pressed
|
||||
} else {
|
||||
Released
|
||||
};
|
||||
|
||||
let xkev: &ffi::XIDeviceEvent = unsafe { &*(xev.data as *const _) };
|
||||
|
||||
// We use `self.active_window` here as `xkev.event` has a completely different
|
||||
// value for some reason.
|
||||
let window_id = mkwid(active_window);
|
||||
|
||||
let device_id = mkdid(xkev.deviceid);
|
||||
let keycode = xkev.detail as u32;
|
||||
|
||||
let repeat = xkev.flags & ffi::XIKeyRepeat == ffi::XIKeyRepeat;
|
||||
let event = self.kb_state.process_key_event(keycode, state, repeat);
|
||||
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id,
|
||||
event,
|
||||
is_synthetic: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ffi::XI_RawKeyPress | ffi::XI_RawKeyRelease => {
|
||||
let xev: &ffi::XIRawEvent = unsafe { &*(xev.data as *const _) };
|
||||
|
||||
|
|
@ -1153,46 +1056,19 @@ impl<T: 'static> EventProcessor<T> {
|
|||
};
|
||||
|
||||
let device_id = mkdid(xev.sourceid);
|
||||
let keycode = xev.detail;
|
||||
let scancode = keycode - KEYCODE_OFFSET as i32;
|
||||
if scancode < 0 {
|
||||
let keycode = xev.detail as u32;
|
||||
if keycode < KEYCODE_OFFSET as u32 {
|
||||
return;
|
||||
}
|
||||
let keysym = wt.xconn.keycode_to_keysym(keycode as ffi::KeyCode);
|
||||
let virtual_keycode = events::keysym_to_element(keysym as c_uint);
|
||||
let modifiers = self.device_mod_state.modifiers();
|
||||
let physical_key = keymap::raw_keycode_to_keycode(keycode);
|
||||
|
||||
#[allow(deprecated)]
|
||||
callback(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: DeviceEvent::Key(KeyboardInput {
|
||||
scancode: scancode as u32,
|
||||
virtual_keycode,
|
||||
event: DeviceEvent::Key(RawKeyEvent {
|
||||
physical_key,
|
||||
state,
|
||||
modifiers,
|
||||
}),
|
||||
});
|
||||
|
||||
if let Some(modifier) =
|
||||
self.mod_keymap.get_modifier(keycode as ffi::KeyCode)
|
||||
{
|
||||
self.device_mod_state.key_event(
|
||||
state,
|
||||
keycode as ffi::KeyCode,
|
||||
modifier,
|
||||
);
|
||||
|
||||
let new_modifiers = self.device_mod_state.modifiers();
|
||||
|
||||
if modifiers != new_modifiers {
|
||||
if let Some(window_id) = self.active_window {
|
||||
callback(Event::WindowEvent {
|
||||
window_id: mkwid(window_id),
|
||||
event: WindowEvent::ModifiersChanged(new_modifiers),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffi::XI_HierarchyChanged => {
|
||||
|
|
@ -1222,6 +1098,55 @@ impl<T: 'static> EventProcessor<T> {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
if event_type == self.xkbext.first_event_id {
|
||||
let xev = unsafe { &*(xev as *const _ as *const ffi::XkbAnyEvent) };
|
||||
match xev.xkb_type {
|
||||
ffi::XkbNewKeyboardNotify => {
|
||||
let xev = unsafe {
|
||||
&*(xev as *const _ as *const ffi::XkbNewKeyboardNotifyEvent)
|
||||
};
|
||||
let keycodes_changed_flag = 0x1;
|
||||
let geometry_changed_flag = 0x1 << 1;
|
||||
|
||||
let keycodes_changed =
|
||||
util::has_flag(xev.changed, keycodes_changed_flag);
|
||||
let geometry_changed =
|
||||
util::has_flag(xev.changed, geometry_changed_flag);
|
||||
|
||||
if xev.device == self.kb_state.core_keyboard_id
|
||||
&& (keycodes_changed || geometry_changed)
|
||||
{
|
||||
unsafe { self.kb_state.init_with_x11_keymap() };
|
||||
}
|
||||
}
|
||||
ffi::XkbStateNotify => {
|
||||
let xev =
|
||||
unsafe { &*(xev as *const _ as *const ffi::XkbStateNotifyEvent) };
|
||||
|
||||
let prev_mods = self.kb_state.mods_state();
|
||||
self.kb_state.update_modifiers(
|
||||
xev.base_mods,
|
||||
xev.latched_mods,
|
||||
xev.locked_mods,
|
||||
xev.base_group as u32,
|
||||
xev.latched_group as u32,
|
||||
xev.locked_group as u32,
|
||||
);
|
||||
let new_mods = self.kb_state.mods_state();
|
||||
if prev_mods != new_mods {
|
||||
if let Some(window) = self.active_window {
|
||||
callback(Event::WindowEvent {
|
||||
window_id: mkwid(window),
|
||||
event: WindowEvent::ModifiersChanged(
|
||||
Into::<ModifiersState>::into(new_mods).into(),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if event_type == self.randr_event_offset {
|
||||
// In the future, it would be quite easy to emit monitor hotplug events.
|
||||
let prev_list = monitor::invalidate_cached_monitor_list();
|
||||
|
|
@ -1345,14 +1270,12 @@ impl<T: 'static> EventProcessor<T> {
|
|||
wt: &super::EventLoopWindowTarget<T>,
|
||||
window_id: crate::window::WindowId,
|
||||
state: ElementState,
|
||||
mod_keymap: &ModifierKeymap,
|
||||
device_mod_state: &mut ModifierKeyState,
|
||||
kb_state: &mut KbdState,
|
||||
callback: &mut F,
|
||||
) where
|
||||
F: FnMut(Event<'_, T>),
|
||||
{
|
||||
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD);
|
||||
let modifiers = device_mod_state.modifiers();
|
||||
|
||||
// Update modifiers state and emit key events based on which keys are currently pressed.
|
||||
for keycode in wt
|
||||
|
|
@ -1361,29 +1284,13 @@ impl<T: 'static> EventProcessor<T> {
|
|||
.into_iter()
|
||||
.filter(|k| *k >= KEYCODE_OFFSET)
|
||||
{
|
||||
let scancode = (keycode - KEYCODE_OFFSET) as u32;
|
||||
let keysym = wt.xconn.keycode_to_keysym(keycode);
|
||||
let virtual_keycode = events::keysym_to_element(keysym as c_uint);
|
||||
|
||||
if let Some(modifier) = mod_keymap.get_modifier(keycode as ffi::KeyCode) {
|
||||
device_mod_state.key_event(
|
||||
ElementState::Pressed,
|
||||
keycode as ffi::KeyCode,
|
||||
modifier,
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
let keycode = keycode as u32;
|
||||
let event = kb_state.process_key_event(keycode, state, false);
|
||||
callback(Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id,
|
||||
input: KeyboardInput {
|
||||
scancode,
|
||||
state,
|
||||
virtual_keycode,
|
||||
modifiers,
|
||||
},
|
||||
event,
|
||||
is_synthetic: true,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue