diff --git a/src/display.rs b/src/display.rs index 0f2c526f..d1af5411 100644 --- a/src/display.rs +++ b/src/display.rs @@ -331,4 +331,18 @@ impl Display { pub fn get_window_id(&self) -> Option { self.window.get_window_id() } + + /// Adjust the XIM editor position according to the new location of the cursor + pub fn update_ime_position(&mut self, terminal: &Term) { + use index::{Point, Line, Column}; + use term::SizeInfo; + let Point{line: Line(row), col: Column(col)} = terminal.cursor().point; + let SizeInfo{cell_width: cw, + cell_height: ch, + padding_x: px, + padding_y: py, ..} = *terminal.size_info(); + let nspot_y = (py + (row + 1) as f32 * ch) as i16; + let nspot_x = (px + col as f32 * cw) as i16; + self.window().send_xim_spot(nspot_x, nspot_y); + } } diff --git a/src/main.rs b/src/main.rs index 9db5ce58..472e4144 100644 --- a/src/main.rs +++ b/src/main.rs @@ -172,6 +172,8 @@ fn run(mut config: Config, options: cli::Options) -> Result<(), Box> { // Maybe draw the terminal if terminal.needs_draw() { + // Try to update the position of the input method editor + display.update_ime_position(&terminal); // Handle pending resize events // // The second argument is a list of types that want to be notified diff --git a/src/term/mod.rs b/src/term/mod.rs index 64541b33..0a51aac3 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -490,7 +490,7 @@ impl IndexMut for Charsets { #[derive(Default, Copy, Clone)] pub struct Cursor { /// The location of this cursor - point: Point, + pub point: Point, /// Template cell when using this cursor template: Cell, @@ -1054,6 +1054,11 @@ impl Term { &self.mode } + #[inline] + pub fn cursor(&self) -> &Cursor { + &self.cursor + } + pub fn swap_alt(&mut self) { if self.alt { let template = self.empty_cell; diff --git a/src/window.rs b/src/window.rs index 4fbe8631..8126454d 100644 --- a/src/window.rs +++ b/src/window.rs @@ -183,6 +183,8 @@ impl Window { title: &str ) -> Result { let event_loop = EventsLoop::new(); + + Window::platform_window_init(); let window = WindowBuilder::new() .with_title(title); let context = ContextBuilder::new() @@ -282,6 +284,36 @@ impl Window { } } + #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))] + pub fn platform_window_init() { + /// Set up env to make XIM work correctly + use x11_dl::xlib; + use libc::{setlocale, LC_CTYPE}; + let xlib = xlib::Xlib::open().expect("get xlib"); + unsafe { + /// Use empty c string to fallback to LC_CTYPE in environment variables + setlocale(LC_CTYPE, b"\0".as_ptr() as *const _); + /// Use empty c string for implementation dependent behavior, + /// which might be the XMODIFIERS set in env + (xlib.XSetLocaleModifiers)(b"\0".as_ptr() as *const _); + } + } + + /// TODO: change this directive when adding functions for other platforms + #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))] + pub fn platform_window_init() { + } + + #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))] + pub fn send_xim_spot(&self, x: i16, y: i16) { + use glutin::os::unix::WindowExt; + self.window.send_xim_spot(x, y); + } + + #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))] + pub fn send_xim_spot(&self, x: i16, y: i16) { + } + #[cfg(not(target_os = "macos"))] pub fn get_window_id(&self) -> Option { use glutin::os::unix::WindowExt;