New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Revert "Add composition event on macOS (#1979)" #2119
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ use crate::{ | |
scancode_to_keycode, EventWrapper, | ||
}, | ||
ffi::*, | ||
util::{self, ns_string_char_count, IdRef}, | ||
util::{self, IdRef}, | ||
window::get_window_id, | ||
DEVICE_ID, | ||
}, | ||
|
@@ -57,8 +57,6 @@ pub(super) struct ViewState { | |
raw_characters: Option<String>, | ||
pub(super) modifiers: ModifiersState, | ||
tracking_rect: Option<NSInteger>, | ||
is_ime_activated: bool, | ||
marked_text: id, | ||
} | ||
|
||
impl ViewState { | ||
|
@@ -70,17 +68,13 @@ impl ViewState { | |
pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<CursorState>>) { | ||
let cursor_state = Default::default(); | ||
let cursor_access = Arc::downgrade(&cursor_state); | ||
let marked_text = | ||
unsafe { <id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil)) }; | ||
let state = ViewState { | ||
ns_window, | ||
cursor_state, | ||
ime_spot: None, | ||
raw_characters: None, | ||
modifiers: Default::default(), | ||
tracking_rect: None, | ||
is_ime_activated: false, | ||
marked_text, | ||
}; | ||
unsafe { | ||
// This is free'd in `dealloc` | ||
|
@@ -153,10 +147,7 @@ lazy_static! { | |
sel!(setMarkedText:selectedRange:replacementRange:), | ||
set_marked_text as extern "C" fn(&mut Object, Sel, id, NSRange, NSRange), | ||
); | ||
decl.add_method( | ||
sel!(unmarkText), | ||
unmark_text as extern "C" fn(&mut Object, Sel), | ||
); | ||
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel)); | ||
decl.add_method( | ||
sel!(validAttributesForMarkedText), | ||
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id, | ||
|
@@ -168,7 +159,7 @@ lazy_static! { | |
); | ||
decl.add_method( | ||
sel!(insertText:replacementRange:), | ||
insert_text as extern "C" fn(&mut Object, Sel, id, NSRange), | ||
insert_text as extern "C" fn(&Object, Sel, id, NSRange), | ||
); | ||
decl.add_method( | ||
sel!(characterIndexForPoint:), | ||
|
@@ -267,6 +258,7 @@ lazy_static! { | |
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL, | ||
); | ||
decl.add_ivar::<*mut c_void>("winitState"); | ||
decl.add_ivar::<id>("markedText"); | ||
let protocol = Protocol::get("NSTextInputClient").unwrap(); | ||
decl.add_protocol(&protocol); | ||
ViewClass(decl.register()) | ||
|
@@ -276,9 +268,9 @@ lazy_static! { | |
extern "C" fn dealloc(this: &Object, _sel: Sel) { | ||
unsafe { | ||
let state: *mut c_void = *this.get_ivar("winitState"); | ||
let state = state as *mut ViewState; | ||
let _: () = msg_send![(*state).marked_text, release]; | ||
Box::from_raw(state); | ||
let marked_text: id = *this.get_ivar("markedText"); | ||
let _: () = msg_send![marked_text, release]; | ||
Box::from_raw(state as *mut ViewState); | ||
} | ||
} | ||
|
||
|
@@ -287,6 +279,9 @@ extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> i | |
let this: id = msg_send![this, init]; | ||
if this != nil { | ||
(*this).set_ivar("winitState", state); | ||
let marked_text = | ||
<id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil)); | ||
(*this).set_ivar("markedText", marked_text); | ||
let _: () = msg_send![this, setPostsFrameChangedNotifications: YES]; | ||
|
||
let notification_center: &Object = | ||
|
@@ -393,20 +388,17 @@ extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) { | |
extern "C" fn has_marked_text(this: &Object, _sel: Sel) -> BOOL { | ||
unsafe { | ||
trace!("Triggered `hasMarkedText`"); | ||
let state_ptr: *mut c_void = *this.get_ivar("winitState"); | ||
let state = &mut *(state_ptr as *mut ViewState); | ||
let retval = (state.marked_text.length() > 0) as BOOL; | ||
let marked_text: id = *this.get_ivar("markedText"); | ||
trace!("Completed `hasMarkedText`"); | ||
retval | ||
(marked_text.length() > 0) as BOOL | ||
} | ||
} | ||
|
||
extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange { | ||
unsafe { | ||
trace!("Triggered `markedRange`"); | ||
let state_ptr: *mut c_void = *this.get_ivar("winitState"); | ||
let state = &mut *(state_ptr as *mut ViewState); | ||
let length = state.marked_text.length(); | ||
let marked_text: id = *this.get_ivar("markedText"); | ||
let length = marked_text.length(); | ||
trace!("Completed `markedRange`"); | ||
if length > 0 { | ||
NSRange::new(0, length - 1) | ||
|
@@ -431,62 +423,32 @@ extern "C" fn set_marked_text( | |
) { | ||
trace!("Triggered `setMarkedText`"); | ||
unsafe { | ||
let state_ptr: *mut c_void = *this.get_ivar("winitState"); | ||
let state = &mut *(state_ptr as *mut ViewState); | ||
|
||
// Delete previous marked text | ||
let char_count = ns_string_char_count(state.marked_text.string()); | ||
delete_marked_text(state, char_count); | ||
|
||
state.is_ime_activated = true; | ||
|
||
let _: () = msg_send![state.marked_text, release]; | ||
state.marked_text = NSMutableAttributedString::alloc(nil); | ||
let marked_text_ref: &mut id = this.get_mut_ivar("markedText"); | ||
let _: () = msg_send![(*marked_text_ref), release]; | ||
let marked_text = NSMutableAttributedString::alloc(nil); | ||
let has_attr = msg_send![string, isKindOfClass: class!(NSAttributedString)]; | ||
if has_attr { | ||
state.marked_text.initWithAttributedString(string); | ||
marked_text.initWithAttributedString(string); | ||
} else { | ||
state.marked_text.initWithString(string); | ||
marked_text.initWithString(string); | ||
}; | ||
|
||
let text_ns_str = state.marked_text.string(); | ||
let slice = slice::from_raw_parts( | ||
text_ns_str.UTF8String() as *const c_uchar, | ||
text_ns_str.len(), | ||
); | ||
let text_str = str::from_utf8_unchecked(slice); | ||
|
||
for character in text_str.chars() { | ||
AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent { | ||
window_id: WindowId(get_window_id(state.ns_window)), | ||
event: WindowEvent::ReceivedCharacter(character), | ||
})); | ||
} | ||
*marked_text_ref = marked_text; | ||
} | ||
trace!("Completed `setMarkedText`"); | ||
} | ||
|
||
extern "C" fn unmark_text(this: &mut Object, _sel: Sel) { | ||
extern "C" fn unmark_text(this: &Object, _sel: Sel) { | ||
trace!("Triggered `unmarkText`"); | ||
unsafe { | ||
clear_marked_text(this); | ||
let marked_text: id = *this.get_ivar("markedText"); | ||
let mutable_string = marked_text.mutableString(); | ||
let _: () = msg_send![mutable_string, setString:""]; | ||
Comment on lines
+444
to
+445
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure whether this or the other method (release + alloc) is better here, but let's just leave it be for now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that releasing and allocating a new one would be safer, but the reference to |
||
let input_context: id = msg_send![this, inputContext]; | ||
let _: () = msg_send![input_context, discardMarkedText]; | ||
} | ||
trace!("Completed `unmarkText`"); | ||
} | ||
|
||
/// Unsafe because assumes that `this` is an instance of the `WinitView` class that we declare | ||
/// programmatically | ||
unsafe fn clear_marked_text(this: &mut Object) { | ||
let state_ptr: *mut c_void = *this.get_ivar("winitState"); | ||
let state = &mut *(state_ptr as *mut ViewState); | ||
|
||
let _: () = msg_send![state.marked_text, release]; | ||
state.marked_text = NSMutableAttributedString::alloc(nil); | ||
|
||
let input_context: id = msg_send![this, inputContext]; | ||
let _: () = msg_send![input_context, discardMarkedText]; | ||
} | ||
|
||
extern "C" fn valid_attributes_for_marked_text(_this: &Object, _sel: Sel) -> id { | ||
trace!("Triggered `validAttributesForMarkedText`"); | ||
trace!("Completed `validAttributesForMarkedText`"); | ||
|
@@ -534,19 +496,12 @@ extern "C" fn first_rect_for_character_range( | |
} | ||
} | ||
|
||
extern "C" fn insert_text(this: &mut Object, _sel: Sel, string: id, _replacement_range: NSRange) { | ||
extern "C" fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range: NSRange) { | ||
trace!("Triggered `insertText`"); | ||
unsafe { | ||
let state_ptr: *mut c_void = *this.get_ivar("winitState"); | ||
let state = &mut *(state_ptr as *mut ViewState); | ||
|
||
let is_ime_activated: bool = state.is_ime_activated; | ||
if is_ime_activated { | ||
clear_marked_text(this); | ||
state.is_ime_activated = false; | ||
return; | ||
} | ||
|
||
let has_attr = msg_send![string, isKindOfClass: class!(NSAttributedString)]; | ||
let characters = if has_attr { | ||
// This is a *mut NSAttributedString | ||
|
@@ -613,15 +568,6 @@ extern "C" fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) { | |
trace!("Completed `doCommandBySelector`"); | ||
} | ||
|
||
fn delete_marked_text(state: &mut ViewState, count: usize) { | ||
for _ in 0..count { | ||
AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent { | ||
window_id: WindowId(get_window_id(state.ns_window)), | ||
event: WindowEvent::ReceivedCharacter('\u{7f}'), // fire DELETE | ||
})); | ||
} | ||
} | ||
|
||
fn get_characters(event: id, ignore_modifiers: bool) -> String { | ||
unsafe { | ||
let characters: id = if ignore_modifiers { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was also UB btw, the block must take the four arguments as described in the docs (even if unused)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out, I'll try to remember this for the future.