Defer drawing the scene until macOS's display_layer callback
Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
co-authored by
Max Brunsfeld
parent
b9bbc4a698
commit
f1ebad22db
@@ -3,7 +3,8 @@ use crate::{
|
||||
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
||||
ForegroundExecutor, InputEvent, Keymap, MacDispatcher, MacDisplay, MacDisplayLinker,
|
||||
MacTextSystem, MacWindow, Menu, MenuItem, PathPromptOptions, Platform, PlatformDisplay,
|
||||
PlatformTextSystem, PlatformWindow, Result, SemanticVersion, VideoTimestamp, WindowOptions,
|
||||
PlatformTextSystem, PlatformWindow, Result, Scene, SemanticVersion, VideoTimestamp,
|
||||
WindowOptions,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use block::ConcreteBlock;
|
||||
@@ -490,8 +491,14 @@ impl Platform for MacPlatform {
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
draw: Box<dyn FnMut() -> Result<Scene>>,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
Box::new(MacWindow::open(handle, options, self.foreground_executor()))
|
||||
Box::new(MacWindow::open(
|
||||
handle,
|
||||
options,
|
||||
draw,
|
||||
self.foreground_executor(),
|
||||
))
|
||||
}
|
||||
|
||||
fn set_display_link_output_callback(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use super::{display_bounds_from_native, ns_string, MacDisplay, MetalRenderer, NSRange};
|
||||
use crate::{
|
||||
display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, ExternalPaths,
|
||||
display_bounds_to_native, point, px, size, AnyWindowHandle, Bounds, DrawWindow, ExternalPaths,
|
||||
FileDropEvent, ForegroundExecutor, GlobalPixels, InputEvent, KeyDownEvent, Keystroke,
|
||||
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||
Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
|
||||
PromptLevel, Scene, Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions,
|
||||
PromptLevel, Size, Timer, WindowAppearance, WindowBounds, WindowKind, WindowOptions,
|
||||
};
|
||||
use block::ConcreteBlock;
|
||||
use cocoa::{
|
||||
@@ -45,6 +45,7 @@ use std::{
|
||||
sync::{Arc, Weak},
|
||||
time::Duration,
|
||||
};
|
||||
use util::ResultExt;
|
||||
|
||||
const WINDOW_STATE_IVAR: &str = "windowState";
|
||||
|
||||
@@ -318,7 +319,7 @@ struct MacWindowState {
|
||||
executor: ForegroundExecutor,
|
||||
native_window: id,
|
||||
renderer: MetalRenderer,
|
||||
scene_to_render: Option<Scene>,
|
||||
draw: Option<DrawWindow>,
|
||||
kind: WindowKind,
|
||||
event_callback: Option<Box<dyn FnMut(InputEvent) -> bool>>,
|
||||
activate_callback: Option<Box<dyn FnMut(bool)>>,
|
||||
@@ -454,6 +455,7 @@ impl MacWindow {
|
||||
pub fn open(
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
draw: DrawWindow,
|
||||
executor: ForegroundExecutor,
|
||||
) -> Self {
|
||||
unsafe {
|
||||
@@ -545,7 +547,7 @@ impl MacWindow {
|
||||
executor,
|
||||
native_window,
|
||||
renderer: MetalRenderer::new(true),
|
||||
scene_to_render: None,
|
||||
draw: Some(draw),
|
||||
kind: options.kind,
|
||||
event_callback: None,
|
||||
activate_callback: None,
|
||||
@@ -958,9 +960,8 @@ impl PlatformWindow for MacWindow {
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, scene: Scene) {
|
||||
let mut this = self.0.lock();
|
||||
this.scene_to_render = Some(scene);
|
||||
fn invalidate(&self) {
|
||||
let this = self.0.lock();
|
||||
unsafe {
|
||||
let _: () = msg_send![this.native_window.contentView(), setNeedsDisplay: YES];
|
||||
}
|
||||
@@ -1442,8 +1443,11 @@ extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
|
||||
extern "C" fn display_layer(this: &Object, _: Sel, _: id) {
|
||||
unsafe {
|
||||
let window_state = get_window_state(this);
|
||||
let mut window_state = window_state.as_ref().lock();
|
||||
if let Some(scene) = window_state.scene_to_render.take() {
|
||||
let mut draw = window_state.lock().draw.take().unwrap();
|
||||
let scene = draw().log_err();
|
||||
let mut window_state = window_state.lock();
|
||||
window_state.draw = Some(draw);
|
||||
if let Some(scene) = scene {
|
||||
window_state.renderer.draw(&scene);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId, ForegroundExecutor,
|
||||
Keymap, Platform, PlatformDisplay, PlatformTextSystem, TestDisplay, TestWindow, WindowOptions,
|
||||
Keymap, Platform, PlatformDisplay, PlatformTextSystem, Scene, TestDisplay, TestWindow,
|
||||
WindowOptions,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use collections::VecDeque;
|
||||
@@ -135,6 +136,7 @@ impl Platform for TestPlatform {
|
||||
&self,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
_draw: Box<dyn FnMut() -> Result<Scene>>,
|
||||
) -> Box<dyn crate::PlatformWindow> {
|
||||
*self.active_window.lock() = Some(handle);
|
||||
Box::new(TestWindow::new(
|
||||
|
||||
@@ -166,9 +166,7 @@ impl PlatformWindow for TestWindow {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn draw(&self, scene: crate::Scene) {
|
||||
self.current_scene.lock().replace(scene);
|
||||
}
|
||||
fn invalidate(&self) {}
|
||||
|
||||
fn sprite_atlas(&self) -> sync::Arc<dyn crate::PlatformAtlas> {
|
||||
self.sprite_atlas.clone()
|
||||
|
||||
Reference in New Issue
Block a user