Skip to content

Commit

Permalink
Handle _selected_range sent to NSTextInputClient.setMarkedText(). (#3619
Browse files Browse the repository at this point in the history
)

Co-authored-by: Mads Marquart <[email protected]>
  • Loading branch information
ShikiSuen and madsmtm authored May 31, 2024
1 parent 5d8091f commit 2d1382f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
25 changes: 16 additions & 9 deletions src/platform_impl/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,27 +270,28 @@ 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::<NSAttributedString>() {
let (marked_text, string) = if string.is_kind_of::<NSAttributedString>() {
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;
let string: *const NSString = string.cast();
let string = unsafe { &*string };
(
NSMutableAttributedString::from_nsstring(string),
string.to_string(),
string.copy(),
)
};

Expand All @@ -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)]
Expand Down Expand Up @@ -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`.
Expand Down

0 comments on commit 2d1382f

Please sign in to comment.