Skip to content

Commit 3144d1e

Browse files
committed
feat: support ime
1 parent a38f95e commit 3144d1e

File tree

4 files changed

+56
-42
lines changed

4 files changed

+56
-42
lines changed

crates/egui-term/src/display/mod.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ impl TerminalView<'_> {
4646
.term_ctx
4747
.to_range()
4848
.is_some_and(|r| r.contains(indexed.point));
49-
let is_hovered_hyperlink =
50-
self.term_ctx.hovered_hyperlink.as_ref().is_some_and(|r| {
51-
r.contains(&indexed.point) && r.contains(&state.mouse_position)
52-
});
49+
let is_hovered_hyperlink = self
50+
.term_ctx
51+
.hovered_hyperlink
52+
.as_ref()
53+
.is_some_and(|r| r.contains(&indexed.point) && r.contains(&state.mouse_point));
5354
let is_text_cell = indexed.c != ' ' && indexed.c != '\t';
5455

5556
let x = layout_min.x + indexed.point.column.saturating_mul(cell_width as usize) as f32;
@@ -112,6 +113,7 @@ impl TerminalView<'_> {
112113
cell_width / 2.
113114
};
114115

116+
state.cursor_position = Some(Pos2::new(x, y));
115117
shapes.push(Shape::Rect(RectShape::filled(
116118
Rect::from_min_size(Pos2::new(x, y), Vec2::new(cursor_width, cell_height)),
117119
CornerRadius::default(),
@@ -191,6 +193,7 @@ impl TerminalView<'_> {
191193
if let Ok(data) = self.term_ctx.clipboard.get_contents() {
192194
self.term_ctx.write_data(data.into_bytes());
193195
self.term_ctx.terminal.selection = None;
196+
ui.ctx().request_repaint();
194197
}
195198
ui.close();
196199
}

crates/egui-term/src/input/mod.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl TerminalView<'_> {
134134
self.left_button_click(state, layout, position, modifiers, pressed)
135135
}
136136
PointerButton::Secondary => {
137-
state.cursor_position = Some(position);
137+
state.context_menu_position = Some(position);
138138
None
139139
}
140140
_ => None,
@@ -149,15 +149,15 @@ impl TerminalView<'_> {
149149
modifiers: &Modifiers,
150150
pressed: bool,
151151
) -> Option<InputAction> {
152-
if state.cursor_position.is_some() {
152+
if state.context_menu_position.is_some() {
153153
return None;
154154
}
155155
let terminal_mode = self.term_ctx.terminal.mode();
156156
if terminal_mode.intersects(TermMode::MOUSE_MODE) {
157157
Some(InputAction::BackendCall(BackendCommand::MouseReport(
158158
MouseButton::LeftButton,
159159
*modifiers,
160-
state.mouse_position,
160+
state.mouse_point,
161161
pressed,
162162
)))
163163
} else if pressed {
@@ -189,7 +189,7 @@ impl TerminalView<'_> {
189189
*self.term_ctx.terminal.mode(),
190190
) {
191191
Some(BindingAction::LinkOpen) => Some(InputAction::BackendCall(
192-
BackendCommand::ProcessLink(LinkAction::Open, state.mouse_position),
192+
BackendCommand::ProcessLink(LinkAction::Open, state.mouse_point),
193193
)),
194194
_ => None,
195195
}
@@ -203,21 +203,22 @@ impl TerminalView<'_> {
203203
position: Pos2,
204204
modifiers: &Modifiers,
205205
) -> Vec<InputAction> {
206-
let cursor_x = position.x - layout.rect.min.x;
207-
let cursor_y = position.y - layout.rect.min.y;
206+
let mouse_x = position.x - layout.rect.min.x;
207+
let mouse_y = position.y - layout.rect.min.y;
208208

209-
state.mouse_position = selection_point(
210-
cursor_x,
211-
cursor_y,
209+
state.mouse_point = selection_point(
210+
mouse_x,
211+
mouse_y,
212212
self.term_ctx.size,
213213
self.term_ctx.terminal.grid().display_offset(),
214214
);
215+
state.mouse_position = Some(position);
215216

216217
let mut actions = vec![];
217218
// Handle command or selection update based on terminal mode and modifiers
218219
if state.is_dragged {
219220
if !self.term_ctx.selection_is_empty() {
220-
if let Some(action) = self.update_selection_scrolling(cursor_y as i32) {
221+
if let Some(action) = self.update_selection_scrolling(mouse_y as i32) {
221222
actions.push(action);
222223
}
223224
}
@@ -232,11 +233,11 @@ impl TerminalView<'_> {
232233
InputAction::BackendCall(BackendCommand::MouseReport(
233234
MouseButton::LeftMove,
234235
*modifiers,
235-
state.mouse_position,
236+
state.mouse_point,
236237
true,
237238
))
238239
} else {
239-
InputAction::BackendCall(BackendCommand::SelectUpdate(cursor_x, cursor_y))
240+
InputAction::BackendCall(BackendCommand::SelectUpdate(mouse_x, mouse_y))
240241
};
241242

242243
actions.push(cmd);
@@ -245,7 +246,7 @@ impl TerminalView<'_> {
245246
// Handle link hover if applicable
246247
actions.push(InputAction::BackendCall(BackendCommand::ProcessLink(
247248
LinkAction::Hover,
248-
state.mouse_position,
249+
state.mouse_point,
249250
)));
250251

251252
actions

crates/egui-term/src/view.rs

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,23 @@ use crate::types::Size;
99
use alacritty_terminal::grid::{Dimensions, Scroll};
1010
use alacritty_terminal::index::Point;
1111
use alacritty_terminal::vte::ansi::{Color, NamedColor};
12-
use egui::ImeEvent;
12+
use egui::output::IMEOutput;
1313
use egui::Widget;
1414
use egui::{Context, Event};
1515
use egui::{CursorIcon, Key};
1616
use egui::{Id, Pos2};
17+
use egui::{ImeEvent, Rect};
1718
use egui::{Response, Vec2};
1819

1920
#[derive(Clone, Default)]
2021
pub struct TerminalViewState {
2122
pub is_dragged: bool,
2223
pub scroll_pixels: f32,
2324
// for terminal
24-
pub mouse_position: Point,
25+
pub mouse_point: Point,
26+
pub mouse_position: Option<Pos2>,
27+
pub context_menu_position: Option<Pos2>,
2528
pub cursor_position: Option<Pos2>,
26-
// ime_enabled: bool,
27-
// ime_cursor_range: CursorRange,
2829
pub scrollbar_state: ScrollbarState,
2930
}
3031

@@ -80,13 +81,14 @@ impl Widget for TerminalView<'_> {
8081
}
8182

8283
// context menu
83-
if let Some(pos) = state.cursor_position {
84-
if !out_of_terminal(pos, &layout) {
84+
if let Some(pos) = state.context_menu_position {
85+
if !out_of_terminal(pos, layout.rect) {
8586
self.context_menu(pos, &layout, ui);
8687
}
8788
}
89+
8890
if ui.input(|input_state| input_state.pointer.primary_clicked()) {
89-
state.cursor_position = None;
91+
state.context_menu_position = None;
9092
ui.close();
9193
}
9294

@@ -97,6 +99,20 @@ impl Widget for TerminalView<'_> {
9799
.resize(&layout)
98100
.process_input(&mut state, &layout);
99101

102+
if let Some(pos) = state.mouse_position {
103+
if !out_of_terminal(pos, layout.rect) {
104+
if let Some(cur_pos) = state.cursor_position {
105+
ui.ctx().output_mut(|output| {
106+
let vec = Vec2::new(15., 15.);
107+
output.ime = Some(IMEOutput {
108+
rect: Rect::from_min_size(cur_pos, vec),
109+
cursor_rect: Rect::from_min_size(cur_pos, vec),
110+
})
111+
});
112+
}
113+
}
114+
}
115+
100116
let grid = term.term_ctx.terminal.grid_mut();
101117
let total_lines = grid.total_lines() as f32;
102118
let display_offset = grid.display_offset() as f32;
@@ -241,7 +257,7 @@ impl<'a> TerminalView<'a> {
241257
modifiers,
242258
pos,
243259
} => {
244-
let new_pos = if out_of_terminal(pos, layout) {
260+
let new_pos = if out_of_terminal(pos, layout.rect) {
245261
pos.clamp(layout.rect.min, layout.rect.max)
246262
} else {
247263
pos
@@ -257,15 +273,17 @@ impl<'a> TerminalView<'a> {
257273
input_actions = self.mouse_move(state, layout, pos, &modifiers)
258274
}
259275
Event::Ime(event) => match event {
260-
ImeEvent::Disabled => {
261-
// state.ime_enabled = false;
262-
}
263-
ImeEvent::Enabled | ImeEvent::Preedit(_) => {
264-
// state.ime_enabled = true;
276+
ImeEvent::Preedit(text_mark) => {
277+
if text_mark != "\n" && text_mark != "\r" {
278+
// TODO: handle preedit
279+
}
265280
}
266-
ImeEvent::Commit(text) => {
267-
input_actions.push(self.text_input(&text));
281+
ImeEvent::Commit(prediction) => {
282+
if prediction != "\n" && prediction != "\r" {
283+
input_actions.push(self.text_input(&prediction));
284+
}
268285
}
286+
_ => {}
269287
},
270288
_ => {}
271289
};
@@ -286,9 +304,6 @@ impl<'a> TerminalView<'a> {
286304
}
287305
}
288306

289-
fn out_of_terminal(pos: Pos2, layout: &Response) -> bool {
290-
!(pos.x > layout.rect.min.x
291-
&& pos.x < layout.rect.max.x
292-
&& pos.y > layout.rect.min.y
293-
&& pos.y < layout.rect.max.y)
307+
fn out_of_terminal(pos: Pos2, rect: Rect) -> bool {
308+
!(pos.x > rect.min.x && pos.x < rect.max.x && pos.y > rect.min.y && pos.y < rect.max.y)
294309
}

nxshell/src/app.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,6 @@ impl eframe::App for NxShell {
126126
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
127127
ui.label("Sessions");
128128
});
129-
130-
// TODO: add close menu
131-
// ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
132-
// ui.label("Sessions");
133-
// });
134129
});
135130

136131
self.search_sessions(ui);

0 commit comments

Comments
 (0)