Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 27e475c

Browse files
committedDec 20, 2018
User events
1 parent 157418d commit 27e475c

File tree

6 files changed

+190
-91
lines changed

6 files changed

+190
-91
lines changed
 

‎src/platform_impl/macos/app_state.rs

+29-11
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,16 @@ impl Event<Never> {
2727

2828
pub trait EventHandler: Debug {
2929
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow);
30-
//fn handle_user_events(&mut self, control_flow: &mut ControlFlow);
30+
fn handle_user_events(&mut self, control_flow: &mut ControlFlow);
3131
}
3232

3333
struct EventLoopHandler<F, T: 'static> {
3434
callback: F,
35+
will_exit: bool,
3536
window_target: RootWindowTarget<T>,
3637
}
3738

38-
impl<F, T: 'static> Debug for EventLoopHandler<F, T> {
39+
impl<F, T> Debug for EventLoopHandler<F, T> {
3940
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
4041
formatter.debug_struct("EventLoopHandler")
4142
.field("window_target", &self.window_target)
@@ -54,17 +55,27 @@ where
5455
&self.window_target,
5556
control_flow,
5657
);
58+
self.will_exit |= *control_flow == ControlFlow::Exit;
59+
if self.will_exit {
60+
*control_flow = ControlFlow::Exit;
61+
}
5762
}
5863

59-
/*fn handle_user_events(&mut self, control_flow: &mut ControlFlow) {
60-
for event in self.event_loop.inner.receiver.try_iter() {
64+
fn handle_user_events(&mut self, control_flow: &mut ControlFlow) {
65+
let mut will_exit = self.will_exit;
66+
for event in self.window_target.inner.receiver.try_iter() {
6167
(self.callback)(
6268
Event::UserEvent(event),
63-
&self.event_loop,
69+
&self.window_target,
6470
control_flow,
6571
);
72+
will_exit |= *control_flow == ControlFlow::Exit;
73+
if will_exit {
74+
*control_flow = ControlFlow::Exit;
75+
}
6676
}
67-
}*/
77+
self.will_exit = will_exit;
78+
}
6879
}
6980

7081
#[derive(Default)]
@@ -98,7 +109,7 @@ impl Handler {
98109
self.ready.store(true, Ordering::Release);
99110
}
100111

101-
fn is_control_flow_exit(&self) -> bool {
112+
fn should_exit(&self) -> bool {
102113
*self.control_flow.lock().unwrap() == ControlFlow::Exit
103114
}
104115

@@ -134,6 +145,14 @@ impl Handler {
134145
);
135146
}
136147
}
148+
149+
fn handle_user_events(&self) {
150+
if let Some(ref mut callback) = *self.callback.lock().unwrap() {
151+
callback.handle_user_events(
152+
&mut *self.control_flow.lock().unwrap(),
153+
);
154+
}
155+
}
137156
}
138157

139158
pub enum AppState {}
@@ -146,6 +165,7 @@ impl AppState {
146165
{
147166
*HANDLER.callback.lock().unwrap() = Some(Box::new(EventLoopHandler {
148167
callback,
168+
will_exit: false,
149169
window_target,
150170
}));
151171
}
@@ -203,14 +223,12 @@ impl AppState {
203223

204224
pub fn cleared() {
205225
if !HANDLER.is_ready() { return }
206-
let mut will_stop = HANDLER.is_control_flow_exit();
226+
HANDLER.handle_user_events();
207227
for event in HANDLER.take_events() {
208228
HANDLER.handle_nonuser_event(event);
209-
will_stop |= HANDLER.is_control_flow_exit();
210229
}
211230
HANDLER.handle_nonuser_event(Event::EventsCleared);
212-
will_stop |= HANDLER.is_control_flow_exit();
213-
if will_stop {
231+
if HANDLER.should_exit() {
214232
let _: () = unsafe { msg_send![NSApp(), stop:nil] };
215233
return
216234
}

‎src/platform_impl/macos/event_loop.rs

+42-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::{
2-
collections::VecDeque, marker::PhantomData, process,
2+
collections::VecDeque, mem, os::raw::c_void, process, ptr, sync::mpsc,
33
};
44

55
use cocoa::{appkit::NSApp, base::{id, nil}, foundation::NSAutoreleasePool};
@@ -11,16 +11,18 @@ use {
1111
use platform_impl::platform::{
1212
app::APP_CLASS, app_delegate::APP_DELEGATE_CLASS,
1313
app_state::AppState, monitor::{self, MonitorHandle},
14-
observer::setup_control_flow_observers, util::IdRef,
14+
observer::*, util::IdRef,
1515
};
1616

1717
pub struct EventLoopWindowTarget<T: 'static> {
18-
_marker: PhantomData<T>,
18+
pub sender: mpsc::Sender<T>, // this is only here to be cloned elsewhere
19+
pub receiver: mpsc::Receiver<T>,
1920
}
2021

2122
impl<T> Default for EventLoopWindowTarget<T> {
2223
fn default() -> Self {
23-
EventLoopWindowTarget { _marker: PhantomData }
24+
let (sender, receiver) = mpsc::channel();
25+
EventLoopWindowTarget { sender, receiver }
2426
}
2527
}
2628

@@ -90,23 +92,50 @@ impl<T> EventLoop<T> {
9092
}
9193

9294
pub fn create_proxy(&self) -> Proxy<T> {
93-
Proxy::default()
95+
Proxy::new(self.window_target.inner.sender.clone())
9496
}
9597
}
9698

9799
#[derive(Clone)]
98100
pub struct Proxy<T> {
99-
_marker: PhantomData<T>,
101+
sender: mpsc::Sender<T>,
102+
source: CFRunLoopSourceRef,
100103
}
101104

102-
impl<T> Default for Proxy<T> {
103-
fn default() -> Self {
104-
Proxy { _marker: PhantomData }
105-
}
106-
}
105+
unsafe impl<T> Send for Proxy<T> {}
106+
unsafe impl<T> Sync for Proxy<T> {}
107107

108108
impl<T> Proxy<T> {
109-
pub fn send_event(&self, _event: T) -> Result<(), EventLoopClosed> {
110-
unimplemented!();
109+
fn new(sender: mpsc::Sender<T>) -> Self {
110+
unsafe {
111+
// just wakeup the eventloop
112+
extern "C" fn event_loop_proxy_handler(_: *mut c_void) {}
113+
114+
// adding a Source to the main CFRunLoop lets us wake it up and
115+
// process user events through the normal OS EventLoop mechanisms.
116+
let rl = CFRunLoopGetMain();
117+
let mut context: CFRunLoopSourceContext = mem::zeroed();
118+
context.perform = event_loop_proxy_handler;
119+
let source = CFRunLoopSourceCreate(
120+
ptr::null_mut(),
121+
CFIndex::max_value() - 1,
122+
&mut context,
123+
);
124+
CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes);
125+
CFRunLoopWakeUp(rl);
126+
127+
Proxy { sender, source }
128+
}
129+
}
130+
131+
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> {
132+
self.sender.send(event).map_err(|_| EventLoopClosed)?;
133+
unsafe {
134+
// let the main thread know there's a new event
135+
CFRunLoopSourceSignal(self.source);
136+
let rl = CFRunLoopGetMain();
137+
CFRunLoopWakeUp(rl);
138+
}
139+
Ok(())
111140
}
112141
}

‎src/platform_impl/macos/observer.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ impl Default for EventLoopWaker {
215215
fn default() -> EventLoopWaker {
216216
extern fn wakeup_main_loop(_timer: CFRunLoopTimerRef, _info: *mut c_void) {}
217217
unsafe {
218-
// create a timer with a 1microsec interval (1ns does not work) to mimic polling.
218+
// create a timer with a 1µs interval (1ns does not work) to mimic polling.
219219
// it is initially setup with a first fire time really far into the
220220
// future, but that gets changed to fire immediatley in did_finish_launching
221221
let timer = CFRunLoopTimerCreate(
@@ -228,7 +228,6 @@ impl Default for EventLoopWaker {
228228
ptr::null_mut(),
229229
);
230230
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes);
231-
232231
EventLoopWaker { timer }
233232
}
234233
}

‎src/platform_impl/macos/util.rs

+43-37
Original file line numberDiff line numberDiff line change
@@ -402,72 +402,78 @@ pub unsafe fn create_input_context(view: id) -> IdRef {
402402
IdRef::new(input_context)
403403
}
404404

405-
pub enum CursorType {
405+
pub enum Cursor {
406406
Native(&'static str),
407407
Undocumented(&'static str),
408408
WebKit(&'static str),
409409
}
410410

411-
impl From<MouseCursor> for CursorType {
411+
impl From<MouseCursor> for Cursor {
412412
fn from(cursor: MouseCursor) -> Self {
413413
match cursor {
414-
MouseCursor::Arrow | MouseCursor::Default => CursorType::Native("arrowCursor"),
415-
MouseCursor::Hand => CursorType::Native("pointingHandCursor"),
416-
MouseCursor::Grabbing | MouseCursor::Grab => CursorType::Native("closedHandCursor"),
417-
MouseCursor::Text => CursorType::Native("IBeamCursor"),
418-
MouseCursor::VerticalText => CursorType::Native("IBeamCursorForVerticalLayout"),
419-
MouseCursor::Copy => CursorType::Native("dragCopyCursor"),
420-
MouseCursor::Alias => CursorType::Native("dragLinkCursor"),
421-
MouseCursor::NotAllowed | MouseCursor::NoDrop => CursorType::Native("operationNotAllowedCursor"),
422-
MouseCursor::ContextMenu => CursorType::Native("contextualMenuCursor"),
423-
MouseCursor::Crosshair => CursorType::Native("crosshairCursor"),
424-
MouseCursor::EResize => CursorType::Native("resizeRightCursor"),
425-
MouseCursor::NResize => CursorType::Native("resizeUpCursor"),
426-
MouseCursor::WResize => CursorType::Native("resizeLeftCursor"),
427-
MouseCursor::SResize => CursorType::Native("resizeDownCursor"),
428-
MouseCursor::EwResize | MouseCursor::ColResize => CursorType::Native("resizeLeftRightCursor"),
429-
MouseCursor::NsResize | MouseCursor::RowResize => CursorType::Native("resizeUpDownCursor"),
414+
MouseCursor::Arrow | MouseCursor::Default => Cursor::Native("arrowCursor"),
415+
MouseCursor::Hand => Cursor::Native("pointingHandCursor"),
416+
MouseCursor::Grabbing | MouseCursor::Grab => Cursor::Native("closedHandCursor"),
417+
MouseCursor::Text => Cursor::Native("IBeamCursor"),
418+
MouseCursor::VerticalText => Cursor::Native("IBeamCursorForVerticalLayout"),
419+
MouseCursor::Copy => Cursor::Native("dragCopyCursor"),
420+
MouseCursor::Alias => Cursor::Native("dragLinkCursor"),
421+
MouseCursor::NotAllowed | MouseCursor::NoDrop => Cursor::Native("operationNotAllowedCursor"),
422+
MouseCursor::ContextMenu => Cursor::Native("contextualMenuCursor"),
423+
MouseCursor::Crosshair => Cursor::Native("crosshairCursor"),
424+
MouseCursor::EResize => Cursor::Native("resizeRightCursor"),
425+
MouseCursor::NResize => Cursor::Native("resizeUpCursor"),
426+
MouseCursor::WResize => Cursor::Native("resizeLeftCursor"),
427+
MouseCursor::SResize => Cursor::Native("resizeDownCursor"),
428+
MouseCursor::EwResize | MouseCursor::ColResize => Cursor::Native("resizeLeftRightCursor"),
429+
MouseCursor::NsResize | MouseCursor::RowResize => Cursor::Native("resizeUpDownCursor"),
430430

431431
// Undocumented cursors: https://stackoverflow.com/a/46635398/5435443
432-
MouseCursor::Help => CursorType::Undocumented("_helpCursor"),
433-
MouseCursor::ZoomIn => CursorType::Undocumented("_zoomInCursor"),
434-
MouseCursor::ZoomOut => CursorType::Undocumented("_zoomOutCursor"),
435-
MouseCursor::NeResize => CursorType::Undocumented("_windowResizeNorthEastCursor"),
436-
MouseCursor::NwResize => CursorType::Undocumented("_windowResizeNorthWestCursor"),
437-
MouseCursor::SeResize => CursorType::Undocumented("_windowResizeSouthEastCursor"),
438-
MouseCursor::SwResize => CursorType::Undocumented("_windowResizeSouthWestCursor"),
439-
MouseCursor::NeswResize => CursorType::Undocumented("_windowResizeNorthEastSouthWestCursor"),
440-
MouseCursor::NwseResize => CursorType::Undocumented("_windowResizeNorthWestSouthEastCursor"),
432+
MouseCursor::Help => Cursor::Undocumented("_helpCursor"),
433+
MouseCursor::ZoomIn => Cursor::Undocumented("_zoomInCursor"),
434+
MouseCursor::ZoomOut => Cursor::Undocumented("_zoomOutCursor"),
435+
MouseCursor::NeResize => Cursor::Undocumented("_windowResizeNorthEastCursor"),
436+
MouseCursor::NwResize => Cursor::Undocumented("_windowResizeNorthWestCursor"),
437+
MouseCursor::SeResize => Cursor::Undocumented("_windowResizeSouthEastCursor"),
438+
MouseCursor::SwResize => Cursor::Undocumented("_windowResizeSouthWestCursor"),
439+
MouseCursor::NeswResize => Cursor::Undocumented("_windowResizeNorthEastSouthWestCursor"),
440+
MouseCursor::NwseResize => Cursor::Undocumented("_windowResizeNorthWestSouthEastCursor"),
441441

442442
// While these are available, the former just loads a white arrow,
443443
// and the latter loads an ugly deflated beachball!
444-
// MouseCursor::Move => CursorType::Undocumented("_moveCursor"),
445-
// MouseCursor::Wait => CursorType::Undocumented("_waitCursor"),
444+
// MouseCursor::Move => Cursor::Undocumented("_moveCursor"),
445+
// MouseCursor::Wait => Cursor::Undocumented("_waitCursor"),
446446

447447
// An even more undocumented cursor...
448448
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=522349
449449
// This is the wrong semantics for `Wait`, but it's the same as
450450
// what's used in Safari and Chrome.
451-
MouseCursor::Wait | MouseCursor::Progress => CursorType::Undocumented("busyButClickableCursor"),
451+
MouseCursor::Wait | MouseCursor::Progress => Cursor::Undocumented("busyButClickableCursor"),
452452

453453
// For the rest, we can just snatch the cursors from WebKit...
454454
// They fit the style of the native cursors, and will seem
455455
// completely standard to macOS users.
456456
// https://stackoverflow.com/a/21786835/5435443
457-
MouseCursor::Move | MouseCursor::AllScroll => CursorType::WebKit("move"),
458-
MouseCursor::Cell => CursorType::WebKit("cell"),
457+
MouseCursor::Move | MouseCursor::AllScroll => Cursor::WebKit("move"),
458+
MouseCursor::Cell => Cursor::WebKit("cell"),
459459
}
460460
}
461461
}
462462

463-
impl CursorType {
464-
pub unsafe fn load(self) -> id {
463+
impl Default for Cursor {
464+
fn default() -> Self {
465+
Cursor::Native("arrowCursor")
466+
}
467+
}
468+
469+
impl Cursor {
470+
pub unsafe fn load(&self) -> id {
465471
match self {
466-
CursorType::Native(cursor_name) => {
472+
Cursor::Native(cursor_name) => {
467473
let sel = Sel::register(cursor_name);
468474
msg_send![class!(NSCursor), performSelector:sel]
469475
},
470-
CursorType::Undocumented(cursor_name) => {
476+
Cursor::Undocumented(cursor_name) => {
471477
let class = class!(NSCursor);
472478
let sel = Sel::register(cursor_name);
473479
let sel = if msg_send![class, respondsToSelector:sel] {
@@ -478,7 +484,7 @@ impl CursorType {
478484
};
479485
msg_send![class, performSelector:sel]
480486
},
481-
CursorType::WebKit(cursor_name) => load_webkit_cursor(cursor_name),
487+
Cursor::WebKit(cursor_name) => load_webkit_cursor(cursor_name),
482488
}
483489
}
484490
}

‎src/platform_impl/macos/view.rs

+51-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// This is a pretty close port of the implementation in GLFW:
2-
// https://github.com/glfw/glfw/blob/7ef34eb06de54dd9186d3d21a401b2ef819b59e7/src/cocoa_window.m
3-
4-
use std::{boxed::Box, collections::VecDeque, os::raw::*, slice, str};
1+
use std::{
2+
boxed::Box, collections::VecDeque, os::raw::*, slice, str,
3+
sync::{Arc, Mutex, Weak},
4+
};
55

66
use cocoa::{
77
appkit::{NSApp, NSEvent, NSEventModifierFlags, NSEventPhase, NSView, NSWindow},
@@ -32,15 +32,19 @@ struct Modifiers {
3232

3333
struct ViewState {
3434
nswindow: id,
35+
pub cursor: Arc<Mutex<util::Cursor>>,
3536
ime_spot: Option<(f64, f64)>,
3637
raw_characters: Option<String>,
3738
is_key_down: bool,
3839
modifiers: Modifiers,
3940
}
4041

41-
pub fn new_view(nswindow: id) -> IdRef {
42+
pub fn new_view(nswindow: id) -> (IdRef, Weak<Mutex<util::Cursor>>) {
43+
let cursor = Default::default();
44+
let cursor_access = Arc::downgrade(&cursor);
4245
let state = ViewState {
4346
nswindow,
47+
cursor,
4448
ime_spot: None,
4549
raw_characters: None,
4650
is_key_down: false,
@@ -50,23 +54,21 @@ pub fn new_view(nswindow: id) -> IdRef {
5054
// This is free'd in `dealloc`
5155
let state_ptr = Box::into_raw(Box::new(state)) as *mut c_void;
5256
let nsview: id = msg_send![VIEW_CLASS.0, alloc];
53-
IdRef::new(msg_send![nsview, initWithWinit:state_ptr])
57+
(IdRef::new(msg_send![nsview, initWithWinit:state_ptr]), cursor_access)
5458
}
5559
}
5660

57-
pub fn set_ime_spot(nsview: id, input_context: id, x: f64, y: f64) {
58-
unsafe {
59-
let state_ptr: *mut c_void = *(*nsview).get_mut_ivar("winitState");
60-
let state = &mut *(state_ptr as *mut ViewState);
61-
let content_rect = NSWindow::contentRectForFrameRect_(
62-
state.nswindow,
63-
NSWindow::frame(state.nswindow),
64-
);
65-
let base_x = content_rect.origin.x as f64;
66-
let base_y = (content_rect.origin.y + content_rect.size.height) as f64;
67-
state.ime_spot = Some((base_x + x, base_y - y));
68-
let _: () = msg_send![input_context, invalidateCharacterCoordinates];
69-
}
61+
pub unsafe fn set_ime_spot(nsview: id, input_context: id, x: f64, y: f64) {
62+
let state_ptr: *mut c_void = *(*nsview).get_mut_ivar("winitState");
63+
let state = &mut *(state_ptr as *mut ViewState);
64+
let content_rect = NSWindow::contentRectForFrameRect_(
65+
state.nswindow,
66+
NSWindow::frame(state.nswindow),
67+
);
68+
let base_x = content_rect.origin.x as f64;
69+
let base_y = (content_rect.origin.y + content_rect.size.height) as f64;
70+
state.ime_spot = Some((base_x + x, base_y - y));
71+
let _: () = msg_send![input_context, invalidateCharacterCoordinates];
7072
}
7173

7274
struct ViewClass(*const Class);
@@ -93,6 +95,14 @@ lazy_static! {
9395
sel!(acceptsFirstResponder),
9496
accepts_first_responder as extern fn(&Object, Sel) -> BOOL,
9597
);
98+
decl.add_method(
99+
sel!(touchBar),
100+
touch_bar as extern fn(&Object, Sel) -> BOOL,
101+
);
102+
decl.add_method(
103+
sel!(resetCursorRects),
104+
reset_cursor_rects as extern fn(&Object, Sel),
105+
);
96106
decl.add_method(
97107
sel!(hasMarkedText),
98108
has_marked_text as extern fn(&Object, Sel) -> BOOL,
@@ -270,6 +280,28 @@ extern fn accepts_first_responder(_this: &Object, _sel: Sel) -> BOOL {
270280
YES
271281
}
272282

283+
// This is necessary to prevent a beefy terminal error on MacBook Pros:
284+
// IMKInputSession [0x7fc573576ff0 presentFunctionRowItemTextInputViewWithEndpoint:completionHandler:] : [self textInputContext]=0x7fc573558e10 *NO* NSRemoteViewController to client, NSError=Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 0 was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 0 was invalidated from this process.}, com.apple.inputmethod.EmojiFunctionRowItem
285+
// TODO: Add an API extension for using `NSTouchBar`
286+
extern fn touch_bar(_this: &Object, _sel: Sel) -> BOOL {
287+
NO
288+
}
289+
290+
extern fn reset_cursor_rects(this: &Object, _sel: Sel) {
291+
unsafe {
292+
let state_ptr: *mut c_void = *this.get_ivar("winitState");
293+
let state = &mut *(state_ptr as *mut ViewState);
294+
295+
let bounds: NSRect = msg_send![this, bounds];
296+
let cursor = state.cursor.lock().unwrap().load();
297+
let _: () = msg_send![this,
298+
addCursorRect:bounds
299+
cursor:cursor
300+
];
301+
}
302+
}
303+
304+
273305
extern fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
274306
unsafe {
275307
trace!("Triggered `hasMarkedText`");

‎src/platform_impl/macos/window.rs

+24-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
collections::VecDeque, f64, os::raw::c_void,
3-
sync::{Arc, atomic::{Ordering, AtomicBool}, Mutex},
3+
sync::{Arc, atomic::{Ordering, AtomicBool}, Mutex, Weak},
44
};
55

66
use cocoa::{
@@ -24,7 +24,7 @@ use platform::macos::{ActivationPolicy, WindowExtMacOS};
2424
use platform_impl::platform::{
2525
{ffi, util::{self, IdRef}},
2626
monitor::{self, MonitorHandle},
27-
view::{new_view, set_ime_spot},
27+
view::{self, new_view},
2828
window_delegate::{WindowDelegate, WindowDelegateState},
2929
};
3030

@@ -67,8 +67,9 @@ fn create_app(activation_policy: ActivationPolicy) -> Option<id> {
6767
}
6868
}
6969

70-
unsafe fn create_view(nswindow: id) -> Option<IdRef> {
71-
new_view(nswindow).non_nil().map(|nsview| {
70+
unsafe fn create_view(nswindow: id) -> Option<(IdRef, Weak<Mutex<util::Cursor>>)> {
71+
let (nsview, cursor) = new_view(nswindow);
72+
nsview.non_nil().map(|nsview| {
7273
nsview.setWantsBestResolutionOpenGLSurface_(YES);
7374

7475
// On Mojave, views automatically become layer-backed shortly after being added to
@@ -82,7 +83,7 @@ unsafe fn create_view(nswindow: id) -> Option<IdRef> {
8283

8384
nswindow.setContentView_(*nsview);
8485
nswindow.makeFirstResponder_(*nsview);
85-
nsview
86+
(nsview, cursor)
8687
})
8788
}
8889

@@ -234,6 +235,7 @@ pub struct UnownedWindow {
234235
input_context: IdRef, // never changes
235236
pub shared_state: Arc<Mutex<SharedState>>,
236237
decorations: AtomicBool,
238+
cursor: Weak<Mutex<util::Cursor>>,
237239
cursor_hidden: AtomicBool,
238240
}
239241

@@ -263,7 +265,7 @@ impl UnownedWindow {
263265
CreationError::OsError(format!("Couldn't create `NSWindow`"))
264266
})?;
265267

266-
let nsview = unsafe { create_view(*nswindow) }.ok_or_else(|| {
268+
let (nsview, cursor) = unsafe { create_view(*nswindow) }.ok_or_else(|| {
267269
unsafe { pool.drain() };
268270
CreationError::OsError(format!("Couldn't create `NSView`"))
269271
})?;
@@ -305,6 +307,7 @@ impl UnownedWindow {
305307
input_context,
306308
shared_state: Arc::new(Mutex::new(win_attribs.into())),
307309
decorations: AtomicBool::new(decorations),
310+
cursor,
308311
cursor_hidden: Default::default(),
309312
});
310313

@@ -477,9 +480,14 @@ impl UnownedWindow {
477480
}
478481

479482
pub fn set_cursor(&self, cursor: MouseCursor) {
483+
let cursor = util::Cursor::from(cursor);
484+
if let Some(cursor_access) = self.cursor.upgrade() {
485+
*cursor_access.lock().unwrap() = cursor;
486+
}
480487
unsafe {
481-
let cursor = util::CursorType::from(cursor).load();
482-
let _: () = msg_send![cursor, set];
488+
let _: () = msg_send![*self.nswindow,
489+
invalidateCursorRectsForView:*self.nsview
490+
];
483491
}
484492
}
485493

@@ -707,7 +715,14 @@ impl UnownedWindow {
707715

708716
#[inline]
709717
pub fn set_ime_spot(&self, logical_spot: LogicalPosition) {
710-
set_ime_spot(*self.nsview, *self.input_context, logical_spot.x, logical_spot.y);
718+
unsafe {
719+
view::set_ime_spot(
720+
*self.nsview,
721+
*self.input_context,
722+
logical_spot.x,
723+
logical_spot.y,
724+
);
725+
}
711726
}
712727

713728
#[inline]

0 commit comments

Comments
 (0)
Please sign in to comment.