Skip to content

Commit 11c1572

Browse files
authored
Auto merge of #26901 - jdm:keyup-winit, r=Manishearth
Generate keyup events for printable keys - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #26880 - [x] These changes do not require tests because we have no automated way to test user input
2 parents 5ee555f + 87724ec commit 11c1572

File tree

1 file changed

+34
-7
lines changed

1 file changed

+34
-7
lines changed

ports/winit/headed_window.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
3333
use servo::webrender_surfman::WebrenderSurfman;
3434
use servo_media::player::context::{GlApi, GlContext as PlayerGLContext, NativeDisplay};
3535
use std::cell::{Cell, RefCell};
36+
use std::collections::HashMap;
3637
use std::mem;
3738
use std::rc::Rc;
3839
#[cfg(target_os = "linux")]
@@ -73,7 +74,10 @@ pub struct Window {
7374
primary_monitor: winit::MonitorId,
7475
event_queue: RefCell<Vec<WindowEvent>>,
7576
mouse_pos: Cell<Point2D<i32, DevicePixel>>,
76-
last_pressed: Cell<Option<KeyboardEvent>>,
77+
last_pressed: Cell<Option<(KeyboardEvent, Option<VirtualKeyCode>)>>,
78+
/// A map of winit's key codes to key values that are interpreted from
79+
/// winit's ReceivedChar events.
80+
keys_down: RefCell<HashMap<VirtualKeyCode, Key>>,
7781
animation_state: Cell<AnimationState>,
7882
fullscreen: Cell<bool>,
7983
device_pixels_per_px: Option<f32>,
@@ -166,6 +170,7 @@ impl Window {
166170
mouse_down_point: Cell::new(Point2D::new(0, 0)),
167171
mouse_pos: Cell::new(Point2D::new(0, 0)),
168172
last_pressed: Cell::new(None),
173+
keys_down: RefCell::new(HashMap::new()),
169174
animation_state: Cell::new(AnimationState::Idle),
170175
fullscreen: Cell::new(false),
171176
inner_size: Cell::new(inner_size),
@@ -185,8 +190,8 @@ impl Window {
185190
// shift ASCII control characters to lowercase
186191
ch = (ch as u8 + 96) as char;
187192
}
188-
let mut event = if let Some(event) = self.last_pressed.replace(None) {
189-
event
193+
let (mut event, key_code) = if let Some((event, key_code)) = self.last_pressed.replace(None) {
194+
(event, key_code)
190195
} else if ch.is_ascii() {
191196
// Some keys like Backspace emit a control character in winit
192197
// but they are already dealt with in handle_keyboard_input
@@ -195,9 +200,19 @@ impl Window {
195200
} else {
196201
// For combined characters like the letter e with an acute accent
197202
// no keyboard event is emitted. A dummy event is created in this case.
198-
KeyboardEvent::default()
203+
(KeyboardEvent::default(), None)
199204
};
200205
event.key = Key::Character(ch.to_string());
206+
207+
if event.state == KeyState::Down {
208+
// Ensure that when we receive a keyup event from winit, we are able
209+
// to infer that it's related to this character and set the event
210+
// properties appropriately.
211+
if let Some(key_code) = key_code {
212+
self.keys_down.borrow_mut().insert(key_code, event.key.clone());
213+
}
214+
}
215+
201216
let xr_poses = self.xr_window_poses.borrow();
202217
for xr_window_pose in &*xr_poses {
203218
xr_window_pose.handle_xr_translation(&event);
@@ -208,11 +223,23 @@ impl Window {
208223
}
209224

210225
fn handle_keyboard_input(&self, input: KeyboardInput) {
211-
let event = keyboard_event_from_winit(input);
226+
let mut event = keyboard_event_from_winit(input);
227+
trace!("handling {:?}", event);
212228
if event.state == KeyState::Down && event.key == Key::Unidentified {
213229
// If pressed and probably printable, we expect a ReceivedCharacter event.
214-
self.last_pressed.set(Some(event));
215-
} else if event.key != Key::Unidentified {
230+
// Wait for that to be received and don't queue any event right now.
231+
self.last_pressed.set(Some((event, input.virtual_keycode)));
232+
return;
233+
} else if event.state == KeyState::Up && event.key == Key::Unidentified {
234+
// If release and probably printable, this is following a ReceiverCharacter event.
235+
if let Some(key_code) = input.virtual_keycode {
236+
if let Some(key) = self.keys_down.borrow_mut().remove(&key_code) {
237+
event.key = key;
238+
}
239+
}
240+
}
241+
242+
if event.key != Key::Unidentified {
216243
self.last_pressed.set(None);
217244
let xr_poses = self.xr_window_poses.borrow();
218245
for xr_window_pose in &*xr_poses {

0 commit comments

Comments
 (0)