Skip to content

Commit

Permalink
Auto merge of #20327 - kwonoj:fix-ignore, r=paulrouget
Browse files Browse the repository at this point in the history
fix(keyevent): do not emit default ignorable codepoint

<!-- Please describe your changes on the following line: -->
This PR intends to update `KeyEvent` emit behavior around #18130. Issue #17146 (comment) briefly explains what's happening in servo currently - there are KeyboardInput event emitted for separated key (modifier, and `V` in case of paste) and there are also `ReceivedCharacter` event corresponds to `\u{0016}`.

`0x0016` is unicode representation of `Synchronous Idle` (https://en.wikipedia.org/wiki/Synchronous_Idle), belong under category of `Default Ignorable` charater in unicode range doesn't have visual representation (http://www.unicode.org/L2/L2002/02368-default-ignorable.pdf). Currently servo forwards all of emitted event from `winit` including this, eventually leads into double execution of control event.

In this change try to omit default ignorable charater , if given char received is within range of ignorable do not dispatch `KeyEvent`. Once those are omitted, current event handling logic already takes care of key event with correct modifier state so duplicated event handling won't occur.

For implementation perspective, `std::char` in Rust doesn't seem to support `isIdentifierIgnorable` like other platform does (i.e: https://msdn.microsoft.com/en-us/library/aa285330(v=vs.60).aspx / https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html) - so does quick, naïve range comparison check based on unicode range specified in spec, similar to halfbuzz and other does. (https://github.com/harfbuzz/harfbuzz/blob/master/src/hb-unicode-private.hh#L134)

Lastly, this is indeed behavior of `winit` to emit all characters by default. *Why not try to make upstream changes instead?* While I've been reading through issues in `winit`, issue like rust-windowing/winit#350 trying to emit ignorable character by its intention (delete key `ReceivedCharacter` is also under category of default ignorable) and let each consumer application handles it as needed. I assume it'll cause breaking changes in winit's design if it intends to omit those characters, instead tried to make application-level changes.

Couple of consideration for review

- Is it desired changes to not emit `KeyEvent` for default ignorable chars? Do we rather want mapping / or restoring back to original char as @paulrouget mentioned in #17146 (comment)?
- Any better, recommended approach to detect unicode char range?
- Maybe try to make upstream changes to `winit` still, like having configuratble way to opt-in(out) those char event?

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #18130 (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
- This PR has been locally tested on Windows, Linux machines.

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20327)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Mar 22, 2018
2 parents 4433550 + da586d0 commit 28c92db
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions ports/servo/glutin_app/window.rs
Expand Up @@ -346,8 +346,32 @@ impl Window {
GlRequest::Specific(Api::OpenGlEs, (3, 0))
}

/// Detect if given char is default ignorable in unicode
/// http://www.unicode.org/L2/L2002/02368-default-ignorable.pdf
fn is_identifier_ignorable(&self, ch: &char) -> bool {
match *ch {
'\u{0000}'...'\u{0008}' | '\u{000E}'...'\u{001F}' |
'\u{007F}'...'\u{0084}' | '\u{0086}'...'\u{009F}' |
'\u{06DD}' | '\u{070F}' |
'\u{180B}'...'\u{180D}' | '\u{180E}' |
'\u{200C}'...'\u{200F}' |
'\u{202A}'...'\u{202E}' | '\u{2060}'...'\u{2063}' |
'\u{2064}'...'\u{2069}' | '\u{206A}'...'\u{206F}' |
'\u{FE00}'...'\u{FE0F}' | '\u{FEFF}' |
'\u{FFF0}'...'\u{FFF8}' | '\u{FFF9}'...'\u{FFFB}' |
'\u{1D173}'...'\u{1D17A}' | '\u{E0000}' |
'\u{E0001}' |
'\u{E0002}'...'\u{E001F}' | '\u{E0020}'...'\u{E007F}' |
'\u{E0080}'...'\u{E0FFF}' => true,
_ => false
}
}

fn handle_received_character(&self, ch: char) {
let modifiers = Window::glutin_mods_to_script_mods(self.key_modifiers.get());
if self.is_identifier_ignorable(&ch) {
return
}
if let Some(last_pressed_key) = self.last_pressed_key.get() {
let event = WindowEvent::KeyEvent(Some(ch), last_pressed_key, KeyState::Pressed, modifiers);
self.event_queue.borrow_mut().push(event);
Expand Down

0 comments on commit 28c92db

Please sign in to comment.