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

Linux input method support #44

Closed
quininer opened this issue Jan 3, 2017 · 26 comments
Closed

Linux input method support #44

quininer opened this issue Jan 3, 2017 · 26 comments

Comments

@quininer
Copy link
Contributor

quininer commented Jan 3, 2017

Asian users often need to use input method (like fcitx, ibus). :D

@jwilm jwilm added this to the Version 1.0 milestone Jan 3, 2017
@rr-
Copy link

rr- commented Jan 8, 2017

Western users need it as well :)

@Determinant
Copy link
Contributor

Determinant commented Jun 22, 2017

As discussed in IRC, I plan to work on this issue.

According to my own experience and after some research online, I propose using XIM (X Input Method) to have an experimental implementation and basic support for XIM-aware input methods. The reason we don't consider other frameworks is because there is still dispute among them (fcitx vs ibus), and the IME framework scenario for X11 is still a mess. We don't want to first be adhere to fcitx or ibus since people only use one of them and both of them provide with support for XIM. As for GTK/QT im modules, since I believe this project does not want to introduce any dependency on either of them, we are not able to use any of their support.

As a heavy urxvt user, I personally feel comfortable with what urxvt supports for basic IME, and urxvt uses XIM with no surprise. A good reference is https://www.x.org/releases/X11R7.6/doc/libX11/specs/libX11/libX11.html#Input_Methods. Also urxvt provides with code for a typical use of XIM.

This is so far the best plan I could think of, and alacritty also uses x11-dl, which is a Rust port of xlib, so it should be convenient to start the implementation.

@jwilm What do you think? I can start with trying to spawn the IME in a very simple example of winit where there is no text lines or cursors, the first thing I need to make sure is that the example program is able to redirect to users' input to the appropriate IM via XIM and obtain the finalized wide character string and print it out to the terminal, in order to prove the concept. After this, I could try to incorporate this into alacritty code. More advanced features such as pre-editing should be tried and introduced later.

TL;DR: start with XIM first, since all main-stream input engines/framework has legacy support for it and there seems to be no other better choice although XIM is pretty old. But at least, we are able to achieve a similar experience to what urxvt provides.

@koterpillar
Copy link

What kind of Wayland support does XIM have?

@Determinant
Copy link
Contributor

XIM is a pretty old standard, way before Wayland was born. So XIM does not support Wayland. But I guess since Wayland can run X11 programs, it also provides with xlib where XIM can be used.

@jwilm
Copy link
Contributor

jwilm commented Jun 22, 2017

Replying here in addition to IRC -

XIM sounds like the way to go. From what I understand, Wayland will have a different solution. Rather add some support now than not.

This seems like it should be added to winit rather than Alacritty; however, it sounds like you're suggesting the reverse. Is there a reason this couldn't be added to winit?

@Determinant
Copy link
Contributor

Determinant commented Jun 22, 2017

Does alacritty current use winit to get the input text? Not very sure how alacritty is connected to winit. It could also be a problem if we would like to support preediting in the end (when a user is typing, the intermediate candidates are shown and corrected in the terminal line). But you are right, I also hope we could entirely do this in winit, rather than directly in alacritty.

@jwilm
Copy link
Contributor

jwilm commented Jun 23, 2017

Yep, Alacritty uses winit for text input. Currently, it's this KeyboardInput event. But that's really an old fork of Glutin. The new way to do this uses a combination of KeyboardInput and ReceivedChar (link is from winit/glutin update branch).

I imagine that implementing this in winit would mean suppressing ReceivedChar events until a character has been completed.

@quininer
Copy link
Contributor Author

winit already supports XIM.

@jwilm
Copy link
Contributor

jwilm commented Jun 23, 2017

@quininer oh wow, thanks for the link! Have you tried it out at all?

@quininer
Copy link
Contributor Author

@jwilm No, I don't know how to make it work. :(

@Determinant
Copy link
Contributor

@quininer It's currently undocumented... It is not clear what Windows2 is for at the first glance. Maybe we should call some API to enable the IME.

@Determinant
Copy link
Contributor

I guess instead of instantiate Window, in let window = winit::Window::new(&events_loop).unwrap();, we should try Window2.

@jwilm
Copy link
Contributor

jwilm commented Jun 23, 2017

Looks like that code was introduced all the way back in 2014 in rust-windowing/winit@26fec19. It's quite possible full IME support isn't done.

@jwilm
Copy link
Contributor

jwilm commented Jun 23, 2017

This issue seems relevant rust-windowing/winit#195

@jwilm
Copy link
Contributor

jwilm commented Jun 23, 2017

Also some relevant comments in rust-windowing/glutin#721

@Determinant
Copy link
Contributor

Determinant commented Jun 23, 2017

Got the IME popped out. Should use XSetLocaleModifier before creating an IM instance. The modifier
should be the desired IME name such as @im=fcitx. Working on using XwcLookupString to pull strings from the IME output.

@Determinant
Copy link
Contributor

Determinant commented Jun 23, 2017

Although winit has implemented Xutf8LookupString, it always returns zero when using IME. Another thing to keep a note is in the end we need to use XSetICValues to send the current position of the cursor to the IME so it can place its box in the correct position.

@Determinant
Copy link
Contributor

Determinant commented Jun 23, 2017

In order to activate the desired IME, we are supposed to set locale and locale modifier appropriately. for my machine, I use zh_CN.utf8 for LC_TYPE and @im=fcitx for xmodifier. winit currently does not set
either of them so as I tested, locale defaults to C and modifier is empty. In order to get Xutf8LookupString work correctly, it looks like we need to specify utf8 locale in LC_TYPE and to spawn the IME application, specify an appropriate IME name. We need to do both before creating an XIM object:

libc::setlocale(libc::LC_CTYPE, b"zh_CN.utf8\0".as_ptr() as *const _);
(x_events_loop.display.xlib.XSetLocaleModifiers)(b"@im=fcitx\0".as_ptr() as *const _);

Also it seems that if we specify an empty string for either of them, system seems to figure out the correct one from the environment variables.

libc::setlocale(libc::LC_CTYPE, b"\0".as_ptr() as *const _);
(x_events_loop.display.xlib.XSetLocaleModifiers)(b"@\0".as_ptr() as *const _);

Here is the code that works without hacking winit.

@quininer
Copy link
Contributor Author

Great! Then just wait to update glutin.

@Determinant
Copy link
Contributor

@quininer and also implement basic re-positioning of IME box. Looking forward to the update. After all these deps are consistent, I could submit a PR to bring in basic IME support.

@Determinant
Copy link
Contributor

IME now works as tested on my machine.

2017-07-12-004817_451x122_scrot
2017-07-12-005039_390x118_scrot

@umurgdk
Copy link

umurgdk commented Jul 14, 2017

Yay, was waiting this for so long!

@quininer
Copy link
Contributor Author

XIM has been supported!

@Moelf
Copy link

Moelf commented May 15, 2019

For some reason, ibus isn't working on my end. Using wayland, ibus is spawned as ibus --xim. Is there any configuration need to be done?

@Rouji
Copy link

Rouji commented Sep 16, 2019

For some reason, ibus isn't working on my end. Using wayland, ibus is spawned as ibus --xim. Is there any configuration need to be done?

Same here on Sway, using fcitx. Input works in native wayland qt/gtk clients, works in Alacritty when run as an XWayland client, but doesn't work when I run Alacritty as a Wayland client.

@kchibisov
Copy link
Member

@Rouji your issue is tracked here #2734

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

9 participants