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

feat: add IME preedit support #2198

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

OliverChao
Copy link

What kind of change does this PR introduce?

  • Feature

IME preedit is something lost in Neovide.
This pr support ime preedit.

Screen.Recording.2023-12-25.at.01.24.08.mp4

Did this PR introduce a breaking change?

  • No

@OliverChao OliverChao changed the title add IME preedit support feat: add IME preedit support Dec 24, 2023
Copy link
Member

@fredizzimo fredizzimo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the issues are fixed, I think we can go with this, since it’s better than nothing.

But there will still be problems, like word wrapping, especially on the last line. The colors might also not be as expected in all places. So I think we eventually should change the implementation to something else.

When I was thinking about this previously, I had the idea using the regula neovim insert mode for displaying the text, with a lua side plugin helping to deal with that. For example to handle aborts, or selecting another entry. The cursor would also be native, and the selection could use a custom highlight group or perhaps a built in, again, using the lua plugin to mark it.

That way we would not need any special rendering in Neovide, and word wrapping/scrolling of the buffer would happen automatically. We could even integrate proper code completion that way.

// } => {
// self.ime_preedit = (text.to_string(), *cursor_offset);
// log::trace!("Ime preedit {text}");
// }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep the ime state in the keyboard manager. And I also think that this breaks something, since we used to block keyboard inputs when the pre-edit was active, and that code is no longer effective.

if position != self.ime_position {
self.ime_position = position;
if position != self.ime.position() {
// self.ime.position = position;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commented code should be removed

Event::WindowEvent {
event: WindowEvent::Ime(ime),
..
} => match ime {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clippy warnings should be fixed

&self.text
}
pub fn cursor_offset(&self) -> Option<usize> {
if let Some(offset) = self.cursor_offset {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clippy warning should be fixed


#[inline]
pub fn position(&self) -> PhysicalPosition<i32> {
return self.position;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clippy warning should be fixed

// draw ime if possible under current cursor
if let Some(preedit) = preedit {
let factor = grid_renderer.font_dimensions.width as f32;
let y_adjustment = y_adjustment as f32 + factor / 5.0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this factor of 5.0 do?

start,
self.destination.y + y_adjustment,
end,
self.destination.y + y_adjustment + factor / 4.0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this factor 4.0 do?

canvas.draw_text_blob(blob, (start, self.destination.y + y_adjustment), &paint);
}

paint.set_color(skia_safe::colors::GREY.to_color());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use the correct highlight group color, otherwise it might be invisible. I think this is the selection right?

Also, shouldn’t it be drawn before the text? So that the text remain invisible, with the text color also set apporopriately through the highlight groups.

I also think that the floating window transparency need to be taken into account.

@@ -145,7 +147,7 @@ impl Renderer {
self.cursor_renderer.prepare_frame()
}

pub fn draw_frame(&mut self, root_canvas: &Canvas, dt: f32) {
pub fn draw_frame(&mut self, root_canvas: &Canvas, dt: f32, ime: &Ime, w: f32) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give the the w parameter a more descriptive name? We don’t use the shorthand for width anywhere else?


let mut start = self.destination.x;
let mut end = self.destination.x + off;
if end + factor > w {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ideally we should use the neovim grid window width here, not the global window width, otherwise it will render outside floating window and splits for example.

This als means that the code better belongs in rendered_window, where the width and tranaparency needed is available.

@OliverChao
Copy link
Author

very sorry for the late reply. I am a lot bit busy currently.
This pr seems far from completed especially blob string drawing.
I am finding one easy way to handle it.

@fredizzimo
Copy link
Member

Don't worry, I think it's quite close, if we just want an initial version that is usable, but indeed there's a lot to think about and fix if we want it to work perfectly.

You don't need to hurry though. And if you want to attempt the other way, using Neovim insert mode, I can give you a more detailed design of what I had planned. I think that's the best way of doing it, but the implementation is more complex, at least to get started.

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

Successfully merging this pull request may close these issues.

None yet

2 participants