Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix windows glutin keydown #16198

Merged
merged 1 commit into from Apr 12, 2017

Conversation

@jonathandturner
Copy link

jonathandturner commented Mar 31, 2017

This fixes #12937 where keypresses arrive in a one-off fashion, effectively delaying each keystroke. This PR is based heavily on @codec-abc's #16193 PR, with some further fixes and cleanup. From the original PR comments:

There are 2 types of events associated with keyboard: Key event (up or down) and Character Input.

  • A character is not necessary created one a key is pressed (like the home key).
  • A character may be created only using a combination of several key. For example, using a Qwerty International layout you have to type then e to get é. The first key press on will create no character.
  • In servo, we currently merge the 2 events together, meaning that we store a Character Input event in a field to fire a single event later on when we get a Key event.

The order of events seems to be system dependent. For example, let's say that we type the A key on a Qwerty Layout. In Linux and MacOs we will get this:

  • Character Input for character A
  • Key down event with virtual key code of the key A
  • Key up event with virtual key code of the key A

while in Windows we get:

  • Key down event with virtual key code of the key A
  • Character Input for character A
  • Key up event with virtual key code of the key A

It seems that glutin make no attempt to reorder the event to make the order independent of the Operating System. I think it would be easier for Servo if it were handled by the library.

This fix is a stopgap for the current state of glutin. We may want to look into a deeper fix in the future. For now, this is hopefully adequate solution until a more permanent one can be found.

This is the last remaining issue for the Windows nightly blockers meta-issue #12125


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes fix #12937 (github issue number if applicable).
  • There are tests for these changes OR
  • These changes do not require tests because they are around Windows keyboard eventing.

This change is Reviewable

@jonathandturner jonathandturner mentioned this pull request Mar 31, 2017
4 of 4 tasks complete
@jdm jdm self-assigned this Mar 31, 2017
@codec-abc
Copy link

codec-abc commented Mar 31, 2017

Tested it quickly. I cannot type some characters like / or : for instance but backspace work as expected.

@jonathandturner
Copy link
Author

jonathandturner commented Apr 2, 2017

@codec-abc - good catch. Looking into it now

@jonathandturner
Copy link
Author

jonathandturner commented Apr 2, 2017

Looks like the VirtualKeyCode isn't getting passed correctly when hitting /. It's coming back as None, assuming what I'm seeing in the debugger is correct. This is causing it to take the path that says "Keyboard input without virtual key", which it shouldn't take.

@jonathandturner
Copy link
Author

jonathandturner commented Apr 2, 2017

Keys like '/' don't show up in the translation that Servo is using: https://github.com/servo/glutin/blob/servo/src/api/win32/event.rs

This means they don't get a VirtualKeyCode, and then we don't print them, since we expect to have one we can use to translate to a Key that we later use in ReceivedCharacter.

For US Keyboards, the / key is event VK_OEM_2 (see: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx). We don't currently translate this one to a VirtualKeyCode. That code is currently commented out. I think this makes sense, at least somewhat, because using this is specific to US keyboards.

If we want this approach to work, we may end up needing to have keyboard specific things we detect, which seems bad.

Another solution might be to let ReceivedCharacter handle everything, and on the case where it didn't have a Key from before, then check if the character it receives is printable itself.

@jonathandturner
Copy link
Author

jonathandturner commented Apr 3, 2017

I'm not entirely sure this is the direction we want to go, but this works for the tests I tried, including fixing the issue @codec-abc pointed out.

That said, because of the changing assumptions about how keyboard events work, it'd be good to talk through how we want things to work in the future as well.

@jonathandturner
Copy link
Author

jonathandturner commented Apr 3, 2017

Btw - not a fan of the dummy arguments I used. This was just to get things working. I also wasn't sure how deeply we wanted this change to go. I was shooting for a "get it working" PR that we could follow up with a tracking issue for cleanup once we knew how we wanted it to work.

@codec-abc
Copy link

codec-abc commented Apr 3, 2017

I agree with you on everything except for the commenting out of some keys in glutin. From my point of view, it should forward every key event that come and the user may choose to use them or not. As this code start to be tricky I think someone should test it in Linux or Mac before merging to be sure it won't break the keyboard handling on those platforms.

By the way, funny typo in the title 😄

@jonathandturner jonathandturner changed the title Fix windows gluten keydown Fix windows glutin keydown Apr 3, 2017
@jonathandturner
Copy link
Author

jonathandturner commented Apr 3, 2017

@codec-abc - yeah that commented out section was there before. I agree it feels a bit weird. I think they're trying to abstract over the user's keymap.

@jonathandturner
Copy link
Author

jonathandturner commented Apr 5, 2017

Pinging @jdm (who I'm not sure has seen the PR yet)

@jdm
Copy link
Member

jdm commented Apr 6, 2017

First question - is it possible to encapsulate this per-platform logic in a separate structure? Something like:

#[cfg(target_os = "windows")]
type KeyBuffer = windows::KeyBuffer;

mod windows {
    struct KeyBuffer {
        last_pressed_key: Cell<Option<constellation_msg::Key>>,
    }
    impl KeyBuffer {
        fn process_character_event(...) -> Option<WindowEvent> {
            ...
        }
        fn process_keyboard_event(...) -> Option<WindowEvent> {
            ...
        }
    }
}

This would make it easier for me to reason about the per-platform logic.

ElementState::Released => KeyState::Released,
};
let modifiers = Window::glutin_mods_to_script_mods(self.key_modifiers.get());
self.event_queue.borrow_mut().push(WindowEvent::KeyEvent(None, key, state, modifiers));

This comment has been minimized.

Copy link
@jdm

jdm Apr 6, 2017

Member

I am confused by the addition of this line. Is this intentional?

This comment has been minimized.

Copy link
@codec-abc

codec-abc Apr 6, 2017

Yes, it is to align the behavior between platform. In Windows, we get the KeyboardInput event before the ReceivedCharacter which lead to a KeyEvent being fired with no character until we get the associated ReceivedCharacter (if any). In the other OSs the order is reversed. With that line, we reorder the events on non Windows platforms. Said differently, you can see there is a KeyEvent fired in both ReceivedCharacter and KeyboardInput branches in Windows, while no event are fired in the ReceivedCharacter branch for the other platforms, which force us to fire 2 event in the KeyboardInput branch to get the same behavior.

@jonathandturner jonathandturner force-pushed the jonathandturner:fix_windows_gluten_keydown branch from 4790901 to d1edd95 Apr 10, 2017
@jonathandturner
Copy link
Author

jonathandturner commented Apr 10, 2017

@jdm - I did a bit of refactoring to hopefully make the code a bit more readable

Copy link
Member

jdm left a comment

Thanks for tackling this! As discussed on IRC, I think we can address this in glutin with much less effort, and the result will be easier to reason about: http://logs.glob.uno/?c=mozilla%23servo#c648119

@jonathandturner
Copy link
Author

jonathandturner commented Apr 10, 2017

@jdm - Poked around with the PeekMessage idea a bit. Unfortunately, I'm starting to wonder if we want to go this direction.

Let's say the user hits two keys immediately after each other, like shift followed by 'a'. The shift even will check PeekMessage, and may see the WM_CHAR when it looks (let's say there are a few keyboard events waiting), so it decides to delay sending out the keydown event. The result would be that we get a CHAR for 'a' and a keydown for 'a', which is not what we want.

There seemed like there were other race possibilities, that was just the first that came to mind.

Even barring that, which I'm not sure we can easily work around, I can't see PeekMessage working as expected with my naive setup. There may be other steps we need to do before we can see the WM_CHAR events at all.

@codec-abc
Copy link

codec-abc commented Apr 10, 2017

I will try to find some time to make a sample on Windows & Mac with SDL2 nad GLFW to see if the events are in the same count and order. With any luck, a library will get it right, so we can see how it handle it under the hood.

EDIT : I am not able to run a SDL2 sample on a Linux VM because the library complain that it cannot find a video device which is a bit unfortunate. I will try with GLFW next.

ElementState::Released => KeyState::Released,
};
let modifiers = Window::glutin_mods_to_script_mods(self.key_modifiers.get());
//self.event_queue.borrow_mut().push(WindowEvent::KeyEvent(None, key, state, modifiers));

This comment has been minimized.

Copy link
@jdm

jdm Apr 12, 2017

Member

Remove this.

self.event_queue.borrow_mut().push(event);
} else {
// Only send the character if we can print it (by ignoring characters like backspace)
if ch >= ' ' {

This comment has been minimized.

Copy link
@jdm

jdm Apr 12, 2017

Member

!ch.is_control()

// Only send the character if we can print it (by ignoring characters like backspace)
if ch >= ' ' {
let event = WindowEvent::KeyEvent(Some(ch),
Key::A /* unused */,

This comment has been minimized.

@jdm
jdm approved these changes Apr 12, 2017
@jdm
Copy link
Member

jdm commented Apr 12, 2017

It's not just good; it's good enough! Squash the commits and we can merge them.
@bors-servo: delegate+

@bors-servo
Copy link
Contributor

bors-servo commented Apr 12, 2017

✌️ @jonathandturner can now approve this pull request

@jonathandturner jonathandturner force-pushed the jonathandturner:fix_windows_gluten_keydown branch from f1e9509 to c9a091a Apr 12, 2017
@jonathandturner
Copy link
Author

jonathandturner commented Apr 12, 2017

Squashed

@bors-servo r=jdm

@bors-servo
Copy link
Contributor

bors-servo commented Apr 12, 2017

📌 Commit c9a091a has been approved by jdm

@bors-servo
Copy link
Contributor

bors-servo commented Apr 12, 2017

Testing commit c9a091a with merge 4c85192...

bors-servo added a commit that referenced this pull request Apr 12, 2017
Fix windows glutin keydown

<!-- Please describe your changes on the following line: -->
This fixes #12937 where keypresses arrive in a one-off fashion, effectively delaying each keystroke.  This PR is based heavily on @codec-abc's #16193 PR, with some further fixes and cleanup.  From the original PR comments:

> There are 2 types of events associated with keyboard: Key event (up or down) and Character Input.
>
> * A character is not necessary created one a key is pressed (like the home key).
> * A character may be created only using a combination of several key. For example, using a Qwerty International layout you have to type ` then e to get é. The first key press on ` will create no character.
> * In servo, we currently merge the 2 events together, meaning that we store a Character Input event in a field to fire a single event later on when we get a Key event.
>
> The order of events seems to be system dependent. For example, let's say that we type the A key on a Qwerty Layout. In Linux and MacOs we will get this:
>
> * Character Input for character A
> * Key down event with virtual key code of the key A
> * Key up event with virtual key code of the key A
>
> while in Windows we get:
>
> * Key down event with virtual key code of the key A
> * Character Input for character A
> * Key up event with virtual key code of the key A
>
> It seems that glutin make no attempt to reorder the event to make the order independent of the Operating System. I think it would be easier for Servo if it were handled by the library.

This fix is a stopgap for the current state of glutin.  We may want to look into a deeper fix in the future.  For now, this is hopefully adequate solution until a more permanent one can be found.

This is the last remaining issue for the Windows nightly blockers meta-issue #12125

---
<!-- 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 #12937 (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are around Windows keyboard eventing.

<!-- 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/16198)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Apr 12, 2017

☀️ Test successful - android, arm32, arm64, linux-dev, linux-rel-css, linux-rel-wpt, mac-dev-unit, mac-rel-css, mac-rel-wpt1, mac-rel-wpt2, windows-msvc-dev
Approved by: jdm
Pushing 4c85192 to master...

@bors-servo bors-servo merged commit c9a091a into servo:master Apr 12, 2017
3 checks passed
3 checks passed
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
@bors-servo bors-servo mentioned this pull request Apr 12, 2017
3 of 6 tasks complete
@codec-abc
Copy link

codec-abc commented Apr 12, 2017

@jdm @jonathandturner Can one of you update me on the current status of the keyboard handling? to be honest, I am a little bit lost. Moreover, If I recall correctly Servo's behavior on Windows on this test page was incorrect. I can't test it right now so maybe the result is different with the lasts commits. Anyway are there some things to fix/change related to the keyboard events handling and is it needed to open an issue?

@jonathandturner
Copy link
Author

jonathandturner commented Apr 12, 2017

@codec-abc - what we ended up at was making Windows keyboard events work for basic things, but we don't have them event-accurate with what is expected on that test page. We took out the double events on non-Windows platform.

Ultimately, we want a different solution, but this should suffice for the time-being.

@jonathandturner
Copy link
Author

jonathandturner commented Apr 12, 2017

@jdm - not entirely sure how, but it seems like I managed to squash the wrong patch set (switching back and forth between VMs might have done it)

Working on updated PR now.

@jonathandturner jonathandturner mentioned this pull request Apr 12, 2017
3 of 5 tasks complete
bors-servo added a commit that referenced this pull request Apr 12, 2017
Add back in last keydown fixes

<!-- Please describe your changes on the following line: -->

This is a follow-up PR to #16198

The approved patch included these changes as well, but I accidentally excluded them from the squash that landed.

r? @jdm

---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are part of previously reviewed code

<!-- 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/16390)
<!-- Reviewable:end -->
bors-servo added a commit that referenced this pull request Apr 18, 2017
Add back in last keydown fixes

<!-- Please describe your changes on the following line: -->

This is a follow-up PR to #16198

The approved patch included these changes as well, but I accidentally excluded them from the squash that landed.

r? @jdm

---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are part of previously reviewed code

<!-- 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/16390)
<!-- Reviewable:end -->
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Apr 18, 2017
…urner:real_win_keydown_fix); r=jdm

<!-- Please describe your changes on the following line: -->

This is a follow-up PR to servo/servo#16198

The approved patch included these changes as well, but I accidentally excluded them from the squash that landed.

r? @jdm

---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are part of previously reviewed code

<!-- 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. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 967fef15de75fd969dd04686cb50d732330295a5

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 8a991d13ca6a5a7517fd5756e6a35eed1bab42d1
Manishearth pushed a commit to Manishearth/gecko-dev that referenced this pull request Apr 21, 2017
…urner:real_win_keydown_fix); r=jdm

<!-- Please describe your changes on the following line: -->

This is a follow-up PR to servo/servo#16198

The approved patch included these changes as well, but I accidentally excluded them from the squash that landed.

r? @jdm

---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are part of previously reviewed code

<!-- 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. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 967fef15de75fd969dd04686cb50d732330295a5
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this pull request Oct 1, 2019
…urner:real_win_keydown_fix); r=jdm

<!-- Please describe your changes on the following line: -->

This is a follow-up PR to servo/servo#16198

The approved patch included these changes as well, but I accidentally excluded them from the squash that landed.

r? jdm

---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are part of previously reviewed code

<!-- 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. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 967fef15de75fd969dd04686cb50d732330295a5

UltraBlame original commit: fd067187532f2c1d8a17decf01236b453565e274
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this pull request Oct 1, 2019
…urner:real_win_keydown_fix); r=jdm

<!-- Please describe your changes on the following line: -->

This is a follow-up PR to servo/servo#16198

The approved patch included these changes as well, but I accidentally excluded them from the squash that landed.

r? jdm

---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are part of previously reviewed code

<!-- 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. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 967fef15de75fd969dd04686cb50d732330295a5

UltraBlame original commit: fd067187532f2c1d8a17decf01236b453565e274
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this pull request Oct 1, 2019
…urner:real_win_keydown_fix); r=jdm

<!-- Please describe your changes on the following line: -->

This is a follow-up PR to servo/servo#16198

The approved patch included these changes as well, but I accidentally excluded them from the squash that landed.

r? jdm

---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because they are part of previously reviewed code

<!-- 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. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: 967fef15de75fd969dd04686cb50d732330295a5

UltraBlame original commit: fd067187532f2c1d8a17decf01236b453565e274
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

5 participants
You can’t perform that action at this time.