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

macOS: Implement NSTextInputClient #518

Merged
merged 2 commits into from
May 18, 2018

Conversation

@francesca64
Copy link
Member Author

Note that this isn't perfect: #263 (comment)

There's still future work that needs to be done, i.e. it's not currently possible to display a cute little underlined ´ prior to é appearing. This is far more bothersome when working with IME, but it's still a big improvement over the current state of affairs.

@kwonoj
Copy link
Contributor

kwonoj commented May 15, 2018

Cool thing, I was recently realized this is needed and changes arrived even before I dig into impl :)

I'll try some quick testing around tomorrow once I get to access to my mac machine.

@kwonoj
Copy link
Contributor

kwonoj commented May 15, 2018

Also (somewhat) related : servo/servo#20770

@kwonoj
Copy link
Contributor

kwonoj commented May 15, 2018

I just gave it a try and it doesn't look like working as expected - I tried simple KR char composition to 한글 (added space to trigger composition end) , and belows are event I could observe:

WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 79, state: Released, virtual_keycode: None, modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 46, state: Pressed, virtual_keycode: Some(M), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: ReceivedCharacter('ㅎ') }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 46, state: Released, virtual_keycode: Some(M), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 3, state: Pressed, virtual_keycode: Some(F), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 3, state: Released, virtual_keycode: Some(F), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 1, state: Pressed, virtual_keycode: Some(S), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 1, state: Released, virtual_keycode: Some(S), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 40, state: Pressed, virtual_keycode: Some(K), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: ReceivedCharacter('ㅏ') }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 40, state: Released, virtual_keycode: Some(K), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 5, state: Pressed, virtual_keycode: Some(G), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 13, state: Pressed, virtual_keycode: Some(W), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 5, state: Released, virtual_keycode: Some(G), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 13, state: Released, virtual_keycode: Some(W), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 49, state: Pressed, virtual_keycode: Some(Space), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: ReceivedCharacter('글') }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: ReceivedCharacter(' ') }
WindowEvent { window_id: WindowId(Id(140512591906368)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 49, state: Released, virtual_keycode: Some(Space), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }

Particular odd point is ReceivedCharacter, in order it emits

and it doesn't have specific rules, 1 emits when composition starts, but 2 is neither composition starts nor composition end (cause last consonant for char supposed to be char right before composition end), then for next char it doesn't emit any vowel / consonant but emits composited char once composition completes via pressing space key.

@francesca64
Copy link
Member Author

I tried with 390 Sebulshik, and I seem to be able to produce the desired sequence in Alacritty, just like in Terminal.app. ReceivedCharacter contains code points, not graphemes, so maybe that's why the events aren't what you expect?

@kwonoj
Copy link
Contributor

kwonoj commented May 16, 2018

But still in those cases, what's recommended way to process keyevt with compositions? In this case receivedcharacter is pretty much unusable, so applications have to filter it away and compose via keyboardinput only.

For cases like broswers implements composition* event, it surpresses keydown while composition's in progress so it is acceptable (filter out receivedchar) but

  1. It is hard to figure out when composition is in progress with current keyinputevt (maybe this is up to application level to figure out)

  2. Even if receivedchar supposed to display codepoint, current behavior does not emit all codepoints - each kr vowel/consonant have visibile codepoint, so hard to explain why some are received and some are not.

@francesca64
Copy link
Member Author

There's not currently a recommendation, and there's plenty of API design that needs to be done. I'm open to suggestions (and detailed explanations of requirements), but it's not something I can put much time into at present.

@kwonoj
Copy link
Contributor

kwonoj commented May 16, 2018

I see. I'll try to check few other things than receivedcharacter event as well.

@kwonoj
Copy link
Contributor

kwonoj commented May 16, 2018

So for non-emitting ReceivedCharaters, it seems insert_text()(https://github.com/tomaka/winit/pull/518/files#diff-58d7f5aca673e64eda4815ae176040b2R236) itself is not even being called for certain composition status. I can't figure out exactly when it's not being called / why, probably worth to file separate issue instead of trying to dig out in this PR maybe?

@francesca64
Copy link
Member Author

Yeah, I'd like to get this merged and worry about further improvements afterwards.

@k0nserv
Copy link

k0nserv commented May 17, 2018

Dead keys are not working for me at all with this version, also Japanese input also does not work. I could however switch keyboard while Alacritty was focused. I'm on Sierra(10.12.6)

@francesca64
Copy link
Member Author

@k0nserv with what specific input sources?

@petobens
Copy link

petobens commented May 20, 2018

Hi @francesca64 thanks for this awesome fix (now I can finally input tildes in spanish characters :) ). Two things I did notice when using your alacritty branch on Mac and U.S keyboard layout are: i) before I used to be able to hold the j key in vim and the cursor would go down lines as long as I didn't release such key. Now in order to achieve such behaviour I need to hold and release j (i.e holding it down only works to go one line down but not further than that); and ii) for some reason now my <Enter> doesn't seem to work (whereas if I press <Ctrl-Enter> then I can actually mimic/send an <Enter keystroke). Is that expected?

Once again thanks for such an amazing work. Btw Will there be a PR to alacritty with these changes?

@francesca64
Copy link
Member Author

@petobens

Is that expected?

If it happens in Terminal.app, then it's expected. If not, well, then I need to fix it. Does the enter key issue only happen in vim?

I'll make a PR on Alacritty once winit 0.15.0 is released (#530) and it makes its way into glutin (rust-windowing/glutin#1021).

@petobens
Copy link

I'm always on alacritty (not using terminal.app). The Enter issue happens only on tmux (and not on vanilla /plain alacritty). The j (or k) issue happens in both cases and inside vim or outside (for instance using less). It might have something to do with my own setup if you cannot reproduce it. Thanks!

@francesca64
Copy link
Member Author

I'll be sure to investigate that before releasing anything. I'm guessing the i/j thing happens with any key?

@petobens
Copy link

I'm guessing the i/j thing happens with any key?

Indeed.

I'll be sure to investigate that before releasing anything.

Thank you!

@francesca64
Copy link
Member Author

francesca64 commented May 21, 2018

@petobens cargo update and let me know if it's fixed. (If it doesn't work, double check that it pulled in https://github.com/francesca64/winit?branch=macos-kb-regressions#f1e450cf)

@francesca64 francesca64 mentioned this pull request May 21, 2018
@k0nserv
Copy link

k0nserv commented May 21, 2018

I was using Swedish Pro and trying to type e.g ´ procudes the following.

glutin event: WindowEvent { window_id: WindowId(Id(0)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 24, state: Pressed, virtual_keycode: Some(Equals), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
glutin event: WindowEvent { window_id: WindowId(Id(0)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 24, state: Released, virtual_keycode: Some(Equals), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }

The hardware keyboard in this case is a UK apple magic, worth noting that equals is what is printed on the key used and what you get when using a UK layout.

@francesca64
Copy link
Member Author

francesca64 commented May 21, 2018

@k0nserv that's not a regression, is it? If it's not a regression, then please report an issue for it. I'm quite exhausted, so at the moment I'm only addressing things that block a release.

@k0nserv
Copy link

k0nserv commented May 21, 2018

Nope it’s not a regression, but I guess it might be an edge case? Anyway thanks for the great work 👍

@petobens
Copy link

@francesca64 both fixes work :) Thank you!!

raphamorim added a commit to raphamorim/rio that referenced this pull request May 19, 2023
Sets whether the window should get IME events. When IME is not allowed, the window won’t receive Ime events, and will receive KeyboardInput events for every keypress instead. Without allowing IME, the window will also get ReceivedCharacter events for certain keyboard input. Not allowing IME is useful for games for example.

https://docs.rs/winit/latest/winit/window/struct.Window.html#method.set_ime_purpose

rust-windowing/winit#518
rust-windowing/winit#625
alacritty/alacritty#2017
servo/servo#20770
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants