Add minimal support CJK input method to terminal box excepts IME cursor positioning which is a bit tricky

This commit is contained in:
KENZ 2025-04-27 12:54:46 +09:00 • committed by KENZ
parent faa61d1692
commit 18462517f0

View file

@ -13,6 +13,7 @@ use cosmic::{
iced::core::{ iced::core::{
Border, Shell, Border, Shell,
clipboard::Clipboard, clipboard::Clipboard,
input_method::{self, InputMethod},
keyboard::key::Named, keyboard::key::Named,
layout::{self, Layout}, layout::{self, Layout},
renderer::{self, Quad, Renderer as _}, renderer::{self, Quad, Renderer as _},
@ -233,6 +234,18 @@ where
self.disabled = disabled; self.disabled = disabled;
self self
} }
fn input_method<'b>(&self, state: &'b State, layout: Layout<'_>) -> InputMethod<&'b str> {
if !state.is_focused {
return InputMethod::Disabled;
}
InputMethod::Enabled {
cursor: Rectangle::default(),
purpose: input_method::Purpose::Normal,
preedit: state.preedit.as_ref().map(input_method::Preedit::as_ref),
}
}
} }
pub fn terminal_box<'a, Message>( pub fn terminal_box<'a, Message>(
@ -879,6 +892,7 @@ where
shell.request_redraw(); shell.request_redraw();
} }
} }
shell.request_input_method(&self.input_method(state, layout));
} }
cosmic::iced::window::Event::Unfocused => { cosmic::iced::window::Event::Unfocused => {
state.is_focused = false; state.is_focused = false;
@ -1160,6 +1174,30 @@ where
} }
} }
} }
Event::InputMethod(event) => match event {
input_method::Event::Opened | input_method::Event::Closed => {
state.preedit = matches!(event, input_method::Event::Opened).then(|| {
let preedit = input_method::Preedit::new();
preedit
});
}
input_method::Event::Preedit(content, selection) => {
if state.is_focused {
let metrics = terminal.with_buffer(|buffer| buffer.metrics());
state.preedit = Some(input_method::Preedit {
content: content.to_owned(),
selection: selection.clone(),
text_size: Some(metrics.font_size.into()),
})
}
}
input_method::Event::Commit(text) => {
if state.is_focused {
terminal.paste(text.to_string());
shell.capture_event();
}
}
},
Event::Mouse(MouseEvent::ButtonPressed(button)) => { Event::Mouse(MouseEvent::ButtonPressed(button)) => {
if let Some(p) = cursor_position.position_in(layout.bounds()) { if let Some(p) = cursor_position.position_in(layout.bounds()) {
let x = p.x - self.padding.left; let x = p.x - self.padding.left;
@ -1867,6 +1905,7 @@ pub struct State {
scroll_pixels: f32, scroll_pixels: f32,
scrollbar_rect: Cell<Rectangle<f32>>, scrollbar_rect: Cell<Rectangle<f32>>,
autoscroll: DragAutoscroll, autoscroll: DragAutoscroll,
preedit: Option<input_method::Preedit>,
} }
impl State { impl State {
@ -1880,6 +1919,7 @@ impl State {
scroll_pixels: 0.0, scroll_pixels: 0.0,
scrollbar_rect: Cell::new(Rectangle::default()), scrollbar_rect: Cell::new(Rectangle::default()),
autoscroll: DragAutoscroll::new(AUTOSCROLL_INTERVAL), autoscroll: DragAutoscroll::new(AUTOSCROLL_INTERVAL),
preedit: None,
} }
} }
} }