diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 3e6cb6465c..9fec6b62b8 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -56,3 +56,4 @@ changelog entry. - On macOS, fix panic on exit when dropping windows outside the event loop. - On macOS, fix window dragging glitches when dragging across a monitor boundary with different scale factor. +- On macOS, fix the range in `Ime::Preedit`. diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index f6aa85c61c..f3f25597e0 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -270,19 +270,20 @@ declare_class!( fn set_marked_text( &self, string: &NSObject, - _selected_range: NSRange, + selected_range: NSRange, _replacement_range: NSRange, ) { + // TODO: Use _replacement_range, requires changing the event to report surrounding text. trace_scope!("setMarkedText:selectedRange:replacementRange:"); // SAFETY: This method is guaranteed to get either a `NSString` or a `NSAttributedString`. - let (marked_text, preedit_string) = if string.is_kind_of::() { + let (marked_text, string) = if string.is_kind_of::() { let string: *const NSObject = string; let string: *const NSAttributedString = string.cast(); let string = unsafe { &*string }; ( NSMutableAttributedString::from_attributed_nsstring(string), - string.string().to_string(), + string.string(), ) } else { let string: *const NSObject = string; @@ -290,7 +291,7 @@ declare_class!( let string = unsafe { &*string }; ( NSMutableAttributedString::from_nsstring(string), - string.to_string(), + string.copy(), ) }; @@ -310,16 +311,21 @@ declare_class!( self.ivars().ime_state.set(ImeState::Ground); } - // Empty string basically means that there's no preedit, so indicate that by sending - // `None` cursor range. - let cursor_range = if preedit_string.is_empty() { + let cursor_range = if string.is_empty() { + // An empty string basically means that there's no preedit, so indicate that by + // sending a `None` cursor range. None } else { - Some((preedit_string.len(), preedit_string.len())) + // Convert the selected range from UTF-16 indices to UTF-8 indices. + let sub_string_a = unsafe { string.substringToIndex(selected_range.location) }; + let sub_string_b = unsafe { string.substringToIndex(selected_range.end()) }; + let lowerbound_utf8 = sub_string_a.len(); + let upperbound_utf8 = sub_string_b.len(); + Some((lowerbound_utf8, upperbound_utf8)) }; // Send WindowEvent for updating marked text - self.queue_event(WindowEvent::Ime(Ime::Preedit(preedit_string, cursor_range))); + self.queue_event(WindowEvent::Ime(Ime::Preedit(string.to_string(), cursor_range))); } #[method(unmarkText)] @@ -379,6 +385,7 @@ declare_class!( #[method(insertText:replacementRange:)] fn insert_text(&self, string: &NSObject, _replacement_range: NSRange) { + // TODO: Use _replacement_range, requires changing the event to report surrounding text. trace_scope!("insertText:replacementRange:"); // SAFETY: This method is guaranteed to get either a `NSString` or a `NSAttributedString`.