Handle _selected_range sent to NSTextInputClient.setMarkedText(). (#3619)

Co-authored-by: Mads Marquart <mads@marquart.dk>
This commit is contained in:
ShikiSuen 2024-05-31 14:54:20 +08:00 committed by GitHub
parent 5d8091fc7f
commit 2d1382f7d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 17 additions and 9 deletions

View file

@ -56,3 +56,4 @@ changelog entry.
- On macOS, fix panic on exit when dropping windows outside the event loop. - 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 window dragging glitches when dragging across a monitor boundary with different scale factor.
- On macOS, fix the range in `Ime::Preedit`.

View file

@ -270,19 +270,20 @@ declare_class!(
fn set_marked_text( fn set_marked_text(
&self, &self,
string: &NSObject, string: &NSObject,
_selected_range: NSRange, selected_range: NSRange,
_replacement_range: NSRange, _replacement_range: NSRange,
) { ) {
// TODO: Use _replacement_range, requires changing the event to report surrounding text.
trace_scope!("setMarkedText:selectedRange:replacementRange:"); trace_scope!("setMarkedText:selectedRange:replacementRange:");
// SAFETY: This method is guaranteed to get either a `NSString` or a `NSAttributedString`. // 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 NSObject = string;
let string: *const NSAttributedString = string.cast(); let string: *const NSAttributedString = string.cast();
let string = unsafe { &*string }; let string = unsafe { &*string };
( (
NSMutableAttributedString::from_attributed_nsstring(string), NSMutableAttributedString::from_attributed_nsstring(string),
string.string().to_string(), string.string(),
) )
} else { } else {
let string: *const NSObject = string; let string: *const NSObject = string;
@ -290,7 +291,7 @@ declare_class!(
let string = unsafe { &*string }; let string = unsafe { &*string };
( (
NSMutableAttributedString::from_nsstring(string), NSMutableAttributedString::from_nsstring(string),
string.to_string(), string.copy(),
) )
}; };
@ -310,16 +311,21 @@ declare_class!(
self.ivars().ime_state.set(ImeState::Ground); self.ivars().ime_state.set(ImeState::Ground);
} }
// Empty string basically means that there's no preedit, so indicate that by sending let cursor_range = if string.is_empty() {
// `None` cursor range. // An empty string basically means that there's no preedit, so indicate that by
let cursor_range = if preedit_string.is_empty() { // sending a `None` cursor range.
None None
} else { } 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 // 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)] #[method(unmarkText)]
@ -379,6 +385,7 @@ declare_class!(
#[method(insertText:replacementRange:)] #[method(insertText:replacementRange:)]
fn insert_text(&self, string: &NSObject, _replacement_range: NSRange) { 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:"); trace_scope!("insertText:replacementRange:");
// SAFETY: This method is guaranteed to get either a `NSString` or a `NSAttributedString`. // SAFETY: This method is guaranteed to get either a `NSString` or a `NSAttributedString`.