-
Notifications
You must be signed in to change notification settings - Fork 1k
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: Composition Event #2147
macOS: Composition Event #2147
Conversation
I'm not familiar with macOS, but I can help bringing and finishing IME handling (by resurrecting old branch and as well as pushing Wayland bits) and providing help downstream(adding inline ime into alacritty). |
Thanks, @kchibisov. According to the discussion in #1497 (comment), the API design for IME seems to be fixed like this commit. I know this change is destructive, and this change should be done very carefully. I already found master version of Alacritty If you agree with this design and you are willing to implement it for Wayland, you may have to cherry-pick one of the commits in this PR. Should I split this PR into defining |
Just wait until tomorrow so I rebase composition-event and as well alacritty support. You'll just open PR against that branch, and then we rollup all of the platform changes in one patch. |
@komi1230 Thank you for working on MacOS side. And I recently got a windows machine, so I might support windows implementation in near future. |
@komi1230 I've update If you have any questions wrt that API or you're thinking that you need to expose something else to make things work properly on macOS feel free share. |
Thanks. I updated this PR to correspond to I have confirmed this works fine in macOS. I think this PR is ready to merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave the rest to @madsmtm , since I'm not a macOS expert(I don't use macOS).
I've added support for new IME event handling into alacritty alacritty/alacritty#5790 . Though, I'm using my Wayland branch, but just cloning and pointing to your branch in alacritty's |
Thanks, @kchibisov. I appreciate you for your great work!! Now I can find IME is properly working in my Alacritty. 2022-01-18.17.56.41.mov |
It seems like cursor position is off on your gif. When the cursor is in the end of string(so while you're typing) it shouldn't be visible, however when you start moving with left and right arrow keys it should draw hollow block cursor. Also, make sure that those offsets are in bytes and not in chars. |
@kchibisov When I set |
@ArturKovacs @kchibisov I fixed some points, and I want your advice for this. If you feel OK about these changes, please merge. |
I hope you don't mind that I added some changes. We apparently don't need |
@kchibisov note that I added some important information to the documentation of |
@madsmtm I reviewed the IME part of the PR, and now it seems done now. If it's up to me, you can merge it. @kchibisov is there anything else that needs to be done with this? @komi1230 As you can see I pushed some commits to this branch. If you don't mind I'll take over this and address the remaining feedback. |
I completely agree with your changes and have found this works good in macOS. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested the changes on my macOS machine.
- The backspace key is triggered twice. always. even on us layout.
- I think we shouldn't send backspace and other keys downstream when we're doing composing. If we really want to, we can mark them as synthetic, so the users will still get keys, but will know that those weren't for them.
This is a topic about responsibility boundary between winit and application. I think all keyboard event should be sent to application, and let application decide how to handle all keyboard event. This is possible via IME enum because application know when IME has been enabled. |
I mean to remove the existing implementation, and create a new implementation that uses IBus to get IME events. I have no idea how to make the existing implementation work, but I have a decent idea of how to use IBus. |
Won't it make us to depend on ibus for X11 IME? Can't IME be done just with what X11 provides? |
Why is that a concern? Is there any system currently that uses X11 and doesn't have IBus? |
On a different note: what is stopping this from getting merged? |
I never had ibus installed and some use fctix, etc, not ibus. |
I should test it, which I'll do in an hour. |
In that case, I think I'll try to get the current implementation to work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to allocate time for reviewing it this Friday (I'm not well-versed in IME, so doing a bit of research and testing it on my local machine will take some time)
If I haven't responded by then, feel free to merge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested it on my macOS machine with alacritty and it fails in the following ways:
- The state of IME isn't persistent. If I call
set_ime_allowed(true)
and change input source ime will stop working. - The ime gets randomly locked up. The event loop is continuing to run, but I have neither Keyboard nor IME events. I've tested it with hiragana and you likely can press arrow keys to make it trigger.
- When IME is disabled I still have IME window, but it's in the left bottom corner of the screen. I'd expect that it doesn't exist.
I think the locking up is the major pita now.
I could reproduce the first two with alacritty, but I haven't found a reliable way to reproduce them. Although I think did find how to reproduce getting double characters: The double character appearance can be reproduced by having the US layout active, switch to another desktop (with CTRL + Arrow), and switch back. Pressing keys like A, S, D will produce two characters in alacritty. This can then be reverted by having alacritty in focus, switching to Hiragana, pressing A, then switching back to US. My previous commit should fix this, and hopefully some of the other issues as well. |
@ArturKovacs it seems like I can't get alacritty locked anymore, which is good. However if I enable ime on creation, but start with ABC layout. Toggling layout to hiragana won't make IME work, I'll just continue to receive input as if there's no IME running at all. There's no way for downstream to enable IME in that case, since it doesn't even known that anything changed. So winit should track end enabled IME handling routines for a particular window based on recent call to |
I tried to reproduce this, but I couldn't. I modified the |
@madsmtm suggested that we might not need the subview if we instead implmenet the Note that both of the solutions require IME to be allowed for dead-key combinations to be forwarded to the application. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like everything is working for me now. Just some minor commends and should be good from my side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I think I've laid my eyes on most of it, in general it looks really good, nice work all of you!
A bit of terminology: The official term for the popup / overlay that allows you to select the desired characters is called the "candidate window", see the chinese guide and the japanese guide - as @ArturKovacs pointed out to me, the type of candidate window differs between input methods. I think it would be nice to have this term documented somewhere (along with all the other names that IME has).
Another important thing: Creating a new NSTextInputContext
in util::create_input_context
is probably wrong, we should just use NSView -inputContext
(which means view::set_ime_position
is likely working on the wrong NSTextInputContext
).
src/window.rs
Outdated
/// [`KeyboardInput`]: crate::event::WindowEvent::KeyboardInput | ||
/// [`ReceivedCharacter`]: crate::event::WindowEvent::ReceivedCharacter | ||
#[inline] | ||
pub fn set_ime_allowed(&self, allowed: bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a similar method WindowBuilder::with_ime_allowed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch, I forgot that we should likely add it on a builder.
src/platform_impl/macos/view.rs
Outdated
let input_source = current_input_source(); | ||
if state.input_source != input_source && state.is_ime_enabled() { | ||
state.ime_state = ImeState::Disabled; | ||
state.input_source = input_source; | ||
AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent { | ||
window_id: WindowId(get_window_id(state.ns_window)), | ||
event: WindowEvent::IME(IME::Disabled), | ||
})); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems unnecessary to me that we signal to the user that IME is "disabled" when the input source changes, since AppKit already clears the markedText
buffer, but maybe I just don't really understand how the Enabled
and Disabled
events would be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kchibisov could you elaborate on the requirements on these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose is that after you've got disabled you don't need to handle set_ime_position
at all and if you had something in preedit
you could safely discard it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, okay, but a Preedit("", None, None)
could do the same, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means that you could have IME running, but just preedit is empty, so you still call set_ime_postion
and potentially will call set_surrounding_text
(if we add this one).
You could send empty preedit if you want though, but your preedit is empty anyway after the last commit
, since this is how it usually works.
src/platform_impl/macos/view.rs
Outdated
Some(cursor_start), | ||
Some(cursor_end), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand the purpose of the cursor positions, but they are either redundant on macOS, or we're handling them wrong here? Perhaps @kchibisov could elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose is that the position of your cursor is defined by your IME. For example on Wayland you can move your cursor around in preedit text, however it's done entirely by IME. So cursor position is to indicate where your cursor is currently is and where its end. Since if start != end you likely have a so called marked text(selection). The position of the cursor in preedit determines how it should look in the end.
I still have a question who is responsible to update it on macOS, since I can move cursor on preedit string in terminal.app, but not with winit, since when I press left/rigth nothing changes, however in terminal app it seems like moving.
Maybe the user should set cursor position itself on macOS, but at this information is essential for Wayland IME and is the only way to obtain current cursor position in preedit string, so you can draw cursor in the right place.
Does it clarify it for you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think downstream (e.g. alacritty
/winit
, not AppKit) is expected to render things differently, including the cursor/selected text. At first I thought firstRectForCharacterRange:actualRange:
could be used to help tracking the currently focused characters, but then again, its value is cached, so probably not.
I actually think the selectedRange
parameter in setMarkedText:selectedRange:replacementRange:
could do the trick though. Thanks for the explanation!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, the current information this API exposes is already enough for alacritty to draw everything. At least on Wayland it looks like in any other app from my testing.
If it works out that will be nice, meaning that macOS actually handles it itself.
what's the status on this @madsmtm @ArturKovacs ? |
Sorry I'm super busy these days, I'll probably be able to work on it between the 4th and 6th but not sure. |
5042d9a
to
c152698
Compare
If you ask me I think this is pretty much mergeable as it is. The conflicts will have to be resolved of course, but the other stuff isn't that important in my opinion. It's more important to have this feature and we can tweak it later. I don't really have enough time to continue working on this these days. Although I can resolve the merge conflicts if you are willing to merge this afterwards, @kchibisov. |
If @madsmtm is fine with that or could resolve raised issues, I could merge it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Go ahead, I'll give another review when we're ready with the final PR
c152698
to
6a27687
Compare
I merged the |
@ArturKovacs it seems you've merged incorrectly, could you just discard the changes you've made to I can reset file later if you can't do that now. |
I think it's best if you do it. |
Ok, I've rebased and applied the patch on composition-event branch. Thanks. |
This is related to #1497.
To make IME work fine in all languages, we should add new event for composition as discussed in #1497 and #2119.
This PR defines enum variant
Composition
and implement it in macOS.I found some effort in #1404. (Thanks, @garasubo)
But this branch is very old and it's hard to sync with current master branch.
Thanks,
CHANGELOG.md
if knowledge of this change could be valuable to users