MacOS fix CursorEntered and CursorLeft events fired at old window size. (#1335)

* On macOS, Fix `CursorEntered` and `CursorLeft`

* Add CHANGELOG

Co-authored-by: Freya Gentz <zegentzy@protonmail.com>
This commit is contained in:
hatoo 2019-12-31 05:32:37 +09:00 committed by Freya Gentz
parent d9bda3e985
commit dd768fe655
2 changed files with 51 additions and 2 deletions

View file

@ -1,5 +1,6 @@
# Unreleased # Unreleased
- On macOS, fix `CursorEntered` and `CursorLeft` events fired at old window size.
- On macOS, fix error when `set_fullscreen` is called during fullscreen transition. - On macOS, fix error when `set_fullscreen` is called during fullscreen transition.
- On all platforms except mobile and WASM, implement `Window::set_minimized`. - On all platforms except mobile and WASM, implement `Window::set_minimized`.
- On X11, fix `CursorEntered` event being generated for non-winit windows. - On X11, fix `CursorEntered` event being generated for non-winit windows.

View file

@ -9,7 +9,7 @@ use std::{
use cocoa::{ use cocoa::{
appkit::{NSApp, NSEvent, NSEventModifierFlags, NSEventPhase, NSView, NSWindow}, appkit::{NSApp, NSEvent, NSEventModifierFlags, NSEventPhase, NSView, NSWindow},
base::{id, nil}, base::{id, nil},
foundation::{NSPoint, NSRect, NSSize, NSString, NSUInteger}, foundation::{NSInteger, NSPoint, NSRect, NSSize, NSString, NSUInteger},
}; };
use objc::{ use objc::{
declare::ClassDecl, declare::ClassDecl,
@ -42,6 +42,7 @@ struct ViewState {
raw_characters: Option<String>, raw_characters: Option<String>,
is_key_down: bool, is_key_down: bool,
modifiers: ModifiersState, modifiers: ModifiersState,
tracking_rect: Option<NSInteger>,
} }
pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<util::Cursor>>) { pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<util::Cursor>>) {
@ -54,6 +55,7 @@ pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<util::Cursor>>) {
raw_characters: None, raw_characters: None,
is_key_down: false, is_key_down: false,
modifiers: Default::default(), modifiers: Default::default(),
tracking_rect: None,
}; };
unsafe { unsafe {
// This is free'd in `dealloc` // This is free'd in `dealloc`
@ -228,6 +230,10 @@ lazy_static! {
sel!(cancelOperation:), sel!(cancelOperation:),
cancel_operation as extern "C" fn(&Object, Sel, id), cancel_operation as extern "C" fn(&Object, Sel, id),
); );
decl.add_method(
sel!(frameDidChange:),
frame_did_change as extern "C" fn(&Object, Sel, id),
);
decl.add_ivar::<*mut c_void>("winitState"); decl.add_ivar::<*mut c_void>("winitState");
decl.add_ivar::<id>("markedText"); decl.add_ivar::<id>("markedText");
let protocol = Protocol::get("NSTextInputClient").unwrap(); let protocol = Protocol::get("NSTextInputClient").unwrap();
@ -253,6 +259,19 @@ extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> i
let marked_text = let marked_text =
<id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil)); <id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil));
(*this).set_ivar("markedText", marked_text); (*this).set_ivar("markedText", marked_text);
let _: () = msg_send![this, setPostsFrameChangedNotifications: YES];
let notification_center: &Object =
msg_send![class!(NSNotificationCenter), defaultCenter];
let notification_name =
NSString::alloc(nil).init_str("NSViewFrameDidChangeNotification");
let _: () = msg_send![
notification_center,
addObserver: this
selector: sel!(frameDidChange:)
name: notification_name
object: this
];
} }
this this
} }
@ -261,17 +280,46 @@ extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> i
extern "C" fn view_did_move_to_window(this: &Object, _sel: Sel) { extern "C" fn view_did_move_to_window(this: &Object, _sel: Sel) {
trace!("Triggered `viewDidMoveToWindow`"); trace!("Triggered `viewDidMoveToWindow`");
unsafe { unsafe {
let state_ptr: *mut c_void = *this.get_ivar("winitState");
let state = &mut *(state_ptr as *mut ViewState);
if let Some(tracking_rect) = state.tracking_rect.take() {
let _: () = msg_send![this, removeTrackingRect: tracking_rect];
}
let rect: NSRect = msg_send![this, visibleRect]; let rect: NSRect = msg_send![this, visibleRect];
let _: () = msg_send![this, let tracking_rect: NSInteger = msg_send![this,
addTrackingRect:rect addTrackingRect:rect
owner:this owner:this
userData:nil userData:nil
assumeInside:NO assumeInside:NO
]; ];
state.tracking_rect = Some(tracking_rect);
} }
trace!("Completed `viewDidMoveToWindow`"); trace!("Completed `viewDidMoveToWindow`");
} }
extern "C" fn frame_did_change(this: &Object, _sel: Sel, _event: id) {
unsafe {
let state_ptr: *mut c_void = *this.get_ivar("winitState");
let state = &mut *(state_ptr as *mut ViewState);
if let Some(tracking_rect) = state.tracking_rect.take() {
let _: () = msg_send![this, removeTrackingRect: tracking_rect];
}
let rect: NSRect = msg_send![this, visibleRect];
let tracking_rect: NSInteger = msg_send![this,
addTrackingRect:rect
owner:this
userData:nil
assumeInside:NO
];
state.tracking_rect = Some(tracking_rect);
}
}
extern "C" fn draw_rect(this: &Object, _sel: Sel, rect: NSRect) { extern "C" fn draw_rect(this: &Object, _sel: Sel, rect: NSRect) {
unsafe { unsafe {
let state_ptr: *mut c_void = *this.get_ivar("winitState"); let state_ptr: *mut c_void = *this.get_ivar("winitState");