mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 13:52:55 +03:00
macos: improve ime vs dead key composing
When we translate a dead key, send the composed event immediately and don't try to route the current key press via the IME. Improve rendering when in the composing state: overlay the composing text at the cursor position to show what the composing text would look like, even though it hasn't been committed to the input stream yet. refs: https://github.com/wez/wezterm/issues/1504
This commit is contained in:
parent
71dae34b75
commit
0d6fbc1aa2
@ -815,6 +815,9 @@ impl TermWindow {
|
|||||||
log::trace!("DeadKeyStatus now: {:?}", status);
|
log::trace!("DeadKeyStatus now: {:?}", status);
|
||||||
self.dead_key_status = status;
|
self.dead_key_status = status;
|
||||||
self.update_title();
|
self.update_title();
|
||||||
|
// Ensure that we repaint so that any composing
|
||||||
|
// text is updated
|
||||||
|
window.invalidate();
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
WindowEvent::NeedRepaint => Ok(self.do_paint(window)),
|
WindowEvent::NeedRepaint => Ok(self.do_paint(window)),
|
||||||
|
@ -1730,20 +1730,45 @@ impl super::TermWindow {
|
|||||||
|
|
||||||
let local_shaped;
|
let local_shaped;
|
||||||
let cell_clusters;
|
let cell_clusters;
|
||||||
let shaped = match params.pre_shaped {
|
|
||||||
Some(s) => s,
|
// Referencing the text being composed, but only if it belongs to this pane
|
||||||
None => {
|
let composing = if params.pane.is_some()
|
||||||
// Break the line into clusters of cells with the same attributes
|
&& params.is_active
|
||||||
cell_clusters = params.line.cluster();
|
&& params.stable_line_idx == Some(params.cursor.y)
|
||||||
metrics::histogram!("render_screen_line_opengl.line.cluster", start.elapsed());
|
{
|
||||||
log::trace!(
|
if let DeadKeyStatus::Composing(composing) = &self.dead_key_status {
|
||||||
"cluster -> {} clusters, elapsed {:?}",
|
Some(composing)
|
||||||
cell_clusters.len(),
|
} else {
|
||||||
start.elapsed()
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Do we need to shape immediately, or can we use the pre-shaped data?
|
||||||
|
let to_shape = if let Some(composing) = composing {
|
||||||
|
// Create an updated line with the composition overlaid
|
||||||
|
let mut line = params.line.clone();
|
||||||
|
line.overlay_text_with_attribute(
|
||||||
|
params.cursor.x,
|
||||||
|
composing,
|
||||||
|
CellAttributes::blank(),
|
||||||
|
termwiz::surface::SEQ_ZERO,
|
||||||
);
|
);
|
||||||
|
cell_clusters = line.cluster();
|
||||||
|
Some(&cell_clusters)
|
||||||
|
} else if params.pre_shaped.is_none() {
|
||||||
|
cell_clusters = params.line.cluster();
|
||||||
|
Some(&cell_clusters)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let shaped = if let Some(cell_clusters) = to_shape {
|
||||||
local_shaped = self.cluster_and_shape(&cell_clusters, ¶ms)?;
|
local_shaped = self.cluster_and_shape(&cell_clusters, ¶ms)?;
|
||||||
&local_shaped
|
&local_shaped
|
||||||
}
|
} else {
|
||||||
|
params.pre_shaped.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let bounding_rect = euclid::rect(
|
let bounding_rect = euclid::rect(
|
||||||
|
@ -1488,12 +1488,14 @@ impl WindowView {
|
|||||||
modifiers: Modifiers::NONE,
|
modifiers: Modifiers::NONE,
|
||||||
repeat_count: 1,
|
repeat_count: 1,
|
||||||
key_is_down,
|
key_is_down,
|
||||||
}
|
};
|
||||||
.normalize_shift();
|
|
||||||
|
|
||||||
|
inner.ime_text.clear();
|
||||||
|
inner
|
||||||
|
.events
|
||||||
|
.dispatch(WindowEvent::AdviseDeadKeyStatus(DeadKeyStatus::None));
|
||||||
inner.ime_last_event.replace(event.clone());
|
inner.ime_last_event.replace(event.clone());
|
||||||
inner.events.dispatch(WindowEvent::KeyEvent(event));
|
inner.events.dispatch(WindowEvent::KeyEvent(event));
|
||||||
inner.ime_text.clear();
|
|
||||||
inner.ime_state = ImeDisposition::Acted;
|
inner.ime_state = ImeDisposition::Acted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1849,7 +1851,6 @@ impl WindowView {
|
|||||||
let modifier_flags = unsafe { nsevent.modifierFlags() };
|
let modifier_flags = unsafe { nsevent.modifierFlags() };
|
||||||
let modifiers = key_modifiers(modifier_flags);
|
let modifiers = key_modifiers(modifier_flags);
|
||||||
let virtual_key = unsafe { nsevent.keyCode() };
|
let virtual_key = unsafe { nsevent.keyCode() };
|
||||||
let translated;
|
|
||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"key_common: chars=`{}` unmod=`{}` modifiers=`{:?}` virtual_key={:?} key_is_down:{}",
|
"key_common: chars=`{}` unmod=`{}` modifiers=`{:?}` virtual_key={:?} key_is_down:{}",
|
||||||
@ -1928,12 +1929,18 @@ impl WindowView {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Some(Ok(s)) => {
|
Some(Ok(translated)) => {
|
||||||
inner
|
inner
|
||||||
.events
|
.events
|
||||||
.dispatch(WindowEvent::AdviseDeadKeyStatus(DeadKeyStatus::None));
|
.dispatch(WindowEvent::AdviseDeadKeyStatus(DeadKeyStatus::None));
|
||||||
translated = s;
|
let event = KeyEvent {
|
||||||
&translated
|
key: KeyCode::composed(&translated),
|
||||||
|
modifiers: Modifiers::NONE,
|
||||||
|
repeat_count: 1,
|
||||||
|
key_is_down,
|
||||||
|
};
|
||||||
|
inner.events.dispatch(WindowEvent::KeyEvent(event));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Some(Err(e)) => {
|
Some(Err(e)) => {
|
||||||
log::error!("Failed to translate dead key: {}", e);
|
log::error!("Failed to translate dead key: {}", e);
|
||||||
@ -1994,6 +2001,7 @@ impl WindowView {
|
|||||||
let mut inner = myself.inner.borrow_mut();
|
let mut inner = myself.inner.borrow_mut();
|
||||||
inner.key_is_down.replace(key_is_down);
|
inner.key_is_down.replace(key_is_down);
|
||||||
inner.ime_state = ImeDisposition::None;
|
inner.ime_state = ImeDisposition::None;
|
||||||
|
inner.ime_text.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -2050,8 +2058,17 @@ impl WindowView {
|
|||||||
inner.ime_last_event.as_ref().map(|e| e.clone())
|
inner.ime_last_event.as_ref().map(|e| e.clone())
|
||||||
{
|
{
|
||||||
inner.events.dispatch(WindowEvent::KeyEvent(event));
|
inner.events.dispatch(WindowEvent::KeyEvent(event));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let status = if inner.ime_text.is_empty() {
|
||||||
|
DeadKeyStatus::None
|
||||||
|
} else {
|
||||||
|
DeadKeyStatus::Composing(inner.ime_text.clone())
|
||||||
|
};
|
||||||
|
inner
|
||||||
|
.events
|
||||||
|
.dispatch(WindowEvent::AdviseDeadKeyStatus(status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user