diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 2d98a8ecd7..f5907ca3ef 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -66,6 +66,7 @@ fn main() { position.y += 10.0 * sign; position }), + Q => window.request_redraw(), R => window.set_resizable(state), S => window.set_inner_size(match state { true => (WINDOW_SIZE.0 + 100, WINDOW_SIZE.1 + 100), diff --git a/src/platform_impl/macos/app_state.rs b/src/platform_impl/macos/app_state.rs index 71aab15758..a03d440452 100644 --- a/src/platform_impl/macos/app_state.rs +++ b/src/platform_impl/macos/app_state.rs @@ -7,8 +7,9 @@ use std::{ use cocoa::{appkit::NSApp, base::nil}; use { - event::{Event, StartCause}, + event::{Event, StartCause, WindowEvent}, event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget}, + window::WindowId, }; use platform_impl::platform::{observer::EventLoopWaker, util::Never}; @@ -86,6 +87,7 @@ struct Handler { start_time: Mutex>, callback: Mutex>>, pending_events: Mutex>>, + pending_redraw: Mutex>, waker: Mutex, } @@ -97,6 +99,10 @@ impl Handler { self.pending_events.lock().unwrap() } + fn redraw<'a>(&'a self) -> MutexGuard<'a, Vec> { + self.pending_redraw.lock().unwrap() + } + fn waker<'a>(&'a self) -> MutexGuard<'a, EventLoopWaker> { self.waker.lock().unwrap() } @@ -137,6 +143,10 @@ impl Handler { mem::replace(&mut *self.events(), Default::default()) } + fn should_redraw(&self) -> Vec { + mem::replace(&mut *self.redraw(), Default::default()) + } + fn handle_nonuser_event(&self, event: Event) { if let Some(ref mut callback) = *self.callback.lock().unwrap() { callback.handle_nonuser_event( @@ -207,6 +217,14 @@ impl AppState { HANDLER.handle_nonuser_event(Event::NewEvents(cause)); } + // This is called from multiple threads at present + pub fn queue_redraw(window_id: WindowId) { + let mut pending_redraw = HANDLER.redraw(); + if !pending_redraw.contains(&window_id) { + pending_redraw.push(window_id); + } + } + pub fn queue_event(event: Event) { if !unsafe { msg_send![class!(NSThread), isMainThread] } { panic!("uh-oh"); @@ -227,6 +245,12 @@ impl AppState { for event in HANDLER.take_events() { HANDLER.handle_nonuser_event(event); } + for window_id in HANDLER.should_redraw() { + HANDLER.handle_nonuser_event(Event::WindowEvent { + window_id, + event: WindowEvent::RedrawRequested, + }); + } HANDLER.handle_nonuser_event(Event::EventsCleared); if HANDLER.should_exit() { let _: () = unsafe { msg_send![NSApp(), stop:nil] }; diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index f46df164a6..cceba6eeee 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -91,6 +91,10 @@ lazy_static! { sel!(viewDidMoveToWindow), view_did_move_to_window as extern fn(&Object, Sel), ); + decl.add_method( + sel!(drawRect:), + draw_rect as extern fn(&Object, Sel, id), + ); decl.add_method( sel!(acceptsFirstResponder), accepts_first_responder as extern fn(&Object, Sel) -> BOOL, @@ -276,6 +280,18 @@ extern fn view_did_move_to_window(this: &Object, _sel: Sel) { trace!("Completed `viewDidMoveToWindow`"); } +extern fn draw_rect(this: &Object, _sel: Sel, rect: id) { + unsafe { + let state_ptr: *mut c_void = *this.get_ivar("winitState"); + let state = &mut *(state_ptr as *mut ViewState); + + AppState::queue_redraw(WindowId(get_window_id(state.nswindow))); + + let superclass = util::superclass(this); + let () = msg_send![super(this, superclass), drawRect:rect]; + } +} + extern fn accepts_first_responder(_this: &Object, _sel: Sel) -> BOOL { YES } diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 2d9d221026..39d0e27749 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -18,13 +18,14 @@ use objc::{runtime::{Class, Object, Sel, BOOL, YES, NO}, declare::ClassDecl}; use { dpi::{LogicalPosition, LogicalSize}, icon::Icon, monitor::MonitorHandle as RootMonitorHandle, - window::{CreationError, MouseCursor, WindowAttributes}, + window::{ + CreationError, MouseCursor, WindowAttributes, WindowId as RootWindowId, + }, }; use platform::macos::{ActivationPolicy, WindowExtMacOS}; use platform_impl::platform::{ - {ffi, util::{self, IdRef}}, - monitor::{self, MonitorHandle}, - view::{self, new_view}, + app_state::AppState, ffi, monitor::{self, MonitorHandle}, + util::{self, IdRef}, view::{self, new_view}, window_delegate::{WindowDelegate, WindowDelegateState}, }; @@ -377,7 +378,6 @@ impl UnownedWindow { #[inline] pub fn show(&self) { - //unsafe { NSWindow::makeKeyAndOrderFront_(*self.nswindow, nil); } unsafe { util::make_key_and_order_front_async(*self.nswindow) }; } @@ -387,7 +387,7 @@ impl UnownedWindow { } pub fn request_redraw(&self) { - unimplemented!(); + AppState::queue_redraw(RootWindowId(self.id())); } pub fn get_position(&self) -> Option {