1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-10 15:04:32 +03:00

macos: try to set the IME cursor position a bit better

Use the current terminal cursor position as the basis for the position
of the IME.
This commit is contained in:
Wez Furlong 2019-11-03 23:18:46 -08:00
parent e3f6375551
commit cb5e351187
3 changed files with 68 additions and 3 deletions

View File

@ -291,6 +291,9 @@ impl WindowCallbacks for TermWindow {
return;
}
};
self.update_text_cursor(&tab);
let start = std::time::Instant::now();
if let Err(err) = self.paint_tab(&tab, ctx) {
if let Some(&OutOfTextureSpace { size }) = err.downcast_ref::<OutOfTextureSpace>() {
@ -323,6 +326,7 @@ impl WindowCallbacks for TermWindow {
return;
}
};
self.update_text_cursor(&tab);
let start = std::time::Instant::now();
if let Err(err) = self.paint_tab_opengl(&tab, frame) {
if let Some(&OutOfTextureSpace { size }) = err.downcast_ref::<OutOfTextureSpace>() {
@ -486,6 +490,21 @@ impl TermWindow {
}
}
fn update_text_cursor(&mut self, tab: &Rc<dyn Tab>) {
let term = tab.renderer();
let cursor = term.get_cursor_position();
if let Some(win) = self.window.as_ref() {
let r = Rect::new(
Point::new(
cursor.x.max(0) as isize * self.render_metrics.cell_size.width,
cursor.y.max(0) as isize * self.render_metrics.cell_size.height,
),
self.render_metrics.cell_size,
);
win.set_text_cursor_position(r);
}
}
fn activate_tab(&mut self, tab_idx: usize) -> Fallible<()> {
let mux = Mux::get().unwrap();
let mut window = mux

View File

@ -172,6 +172,11 @@ pub trait WindowOps {
/// Resize the inner or client area of the window
fn set_inner_size(&self, width: usize, height: usize);
/// inform the windowing system of the current textual
/// cursor input location. This is used primarily for
/// the platform specific input method editor
fn set_text_cursor_position(&self, _cursor: Rect) {}
/// Schedule a callback on the data associated with the window.
/// The `Any` that is passed in corresponds to the WindowCallbacks
/// impl you passed to `new_window`, pre-converted to Any so that
@ -214,4 +219,9 @@ pub trait WindowOpsMut {
/// Resize the inner or client area of the window
fn set_inner_size(&self, width: usize, height: usize);
/// inform the windowing system of the current textual
/// cursor input location. This is used primarily for
/// the platform specific input method editor
fn set_text_cursor_position(&mut self, _cursor: Rect) {}
}

View File

@ -7,7 +7,7 @@ use crate::connection::ConnectionOps;
use crate::os::macos::bitmap::BitmapRef;
use crate::{
BitmapImage, Color, Connection, Dimensions, KeyCode, KeyEvent, Modifiers, MouseButtons,
MouseCursor, MouseEvent, MouseEventKind, MousePress, Operator, PaintContext, Point, Rect,
MouseCursor, MouseEvent, MouseEventKind, MousePress, Operator, PaintContext, Point, Rect, Size,
WindowCallbacks, WindowOps, WindowOpsMut,
};
use cocoa::appkit::{
@ -281,6 +281,7 @@ impl Window {
window_id,
#[cfg(feature = "opengl")]
gl_context_pair: None,
text_cursor_position: Rect::new(Point::new(0, 0), Size::new(0, 0)),
}));
let window = StrongPtr::new(
@ -364,6 +365,10 @@ impl WindowOps for Window {
Connection::with_window_inner(self.0, move |inner| inner.set_inner_size(width, height));
}
fn set_text_cursor_position(&self, cursor: Rect) {
Connection::with_window_inner(self.0, move |inner| inner.set_text_cursor_position(cursor));
}
fn apply<F: Send + 'static + Fn(&mut dyn Any, &dyn WindowOps)>(&self, func: F)
where
Self: Sized,
@ -462,6 +467,16 @@ impl WindowOpsMut for WindowInner {
);
}
}
fn set_text_cursor_position(&mut self, cursor: Rect) {
if let Some(window_view) = WindowView::get_this(unsafe { &**self.view }) {
window_view.inner.borrow_mut().text_cursor_position = cursor;
}
unsafe {
let input_context: id = msg_send![&**self.view, inputContext];
let () = msg_send![input_context, invalidateCharacterCoordinates];
}
}
}
struct Inner {
@ -470,6 +485,7 @@ struct Inner {
window_id: usize,
#[cfg(feature = "opengl")]
gl_context_pair: Option<opengl::GlContextPair>,
text_cursor_position: Rect,
}
const CLS_NAME: &str = "WezTermWindowView";
@ -727,9 +743,29 @@ impl WindowView {
"firstRectForCharacterRange: range:{:?} actual:{:?}",
range, actual
);
unsafe {
let frame = unsafe {
let window: id = msg_send![this, window];
let frame = NSWindow::frame(window);
NSWindow::frame(window)
};
let backing_frame: NSRect = unsafe { msg_send![this, convertRectToBacking: frame] };
let scale = frame.size.width / backing_frame.size.width;
if let Some(this) = Self::get_this(this) {
let cursor_pos = this
.inner
.borrow()
.text_cursor_position
.to_f64()
.scale(scale, scale);
NSRect::new(
NSPoint::new(
frame.origin.x + cursor_pos.origin.x,
frame.origin.y + frame.size.height - cursor_pos.origin.y,
),
NSSize::new(cursor_pos.size.width, cursor_pos.size.height),
)
} else {
frame
}
}