Merge branch 'main' into add-collab-tests
This commit is contained in:
@@ -87,7 +87,7 @@ impl MetalRenderer {
|
||||
MTLResourceOptions::StorageModeManaged,
|
||||
);
|
||||
|
||||
let paths_rasterization_pipeline_state = build_pipeline_state(
|
||||
let paths_rasterization_pipeline_state = build_path_rasterization_pipeline_state(
|
||||
&device,
|
||||
&library,
|
||||
"paths_rasterization",
|
||||
@@ -823,7 +823,40 @@ fn build_pipeline_state(
|
||||
color_attachment.set_source_alpha_blend_factor(metal::MTLBlendFactor::One);
|
||||
color_attachment.set_destination_rgb_blend_factor(metal::MTLBlendFactor::OneMinusSourceAlpha);
|
||||
color_attachment.set_destination_alpha_blend_factor(metal::MTLBlendFactor::One);
|
||||
descriptor.set_depth_attachment_pixel_format(MTLPixelFormat::Invalid);
|
||||
|
||||
device
|
||||
.new_render_pipeline_state(&descriptor)
|
||||
.expect("could not create render pipeline state")
|
||||
}
|
||||
|
||||
fn build_path_rasterization_pipeline_state(
|
||||
device: &metal::DeviceRef,
|
||||
library: &metal::LibraryRef,
|
||||
label: &str,
|
||||
vertex_fn_name: &str,
|
||||
fragment_fn_name: &str,
|
||||
pixel_format: metal::MTLPixelFormat,
|
||||
) -> metal::RenderPipelineState {
|
||||
let vertex_fn = library
|
||||
.get_function(vertex_fn_name, None)
|
||||
.expect("error locating vertex function");
|
||||
let fragment_fn = library
|
||||
.get_function(fragment_fn_name, None)
|
||||
.expect("error locating fragment function");
|
||||
|
||||
let descriptor = metal::RenderPipelineDescriptor::new();
|
||||
descriptor.set_label(label);
|
||||
descriptor.set_vertex_function(Some(vertex_fn.as_ref()));
|
||||
descriptor.set_fragment_function(Some(fragment_fn.as_ref()));
|
||||
let color_attachment = descriptor.color_attachments().object_at(0).unwrap();
|
||||
color_attachment.set_pixel_format(pixel_format);
|
||||
color_attachment.set_blending_enabled(true);
|
||||
color_attachment.set_rgb_blend_operation(metal::MTLBlendOperation::Add);
|
||||
color_attachment.set_alpha_blend_operation(metal::MTLBlendOperation::Add);
|
||||
color_attachment.set_source_rgb_blend_factor(metal::MTLBlendFactor::One);
|
||||
color_attachment.set_source_alpha_blend_factor(metal::MTLBlendFactor::One);
|
||||
color_attachment.set_destination_rgb_blend_factor(metal::MTLBlendFactor::One);
|
||||
color_attachment.set_destination_alpha_blend_factor(metal::MTLBlendFactor::One);
|
||||
|
||||
device
|
||||
.new_render_pipeline_state(&descriptor)
|
||||
|
||||
@@ -5,10 +5,11 @@ using namespace metal;
|
||||
|
||||
float4 hsla_to_rgba(Hsla hsla);
|
||||
float4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||
Bounds_ScaledPixels clip_bounds,
|
||||
constant Size_DevicePixels *viewport_size);
|
||||
float2 to_tile_position(float2 unit_vertex, AtlasTile tile,
|
||||
constant Size_DevicePixels *atlas_size);
|
||||
float4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||
Bounds_ScaledPixels clip_bounds);
|
||||
float quad_sdf(float2 point, Bounds_ScaledPixels bounds,
|
||||
Corners_ScaledPixels corner_radii);
|
||||
float gaussian(float x, float sigma);
|
||||
@@ -21,6 +22,14 @@ struct QuadVertexOutput {
|
||||
float4 background_color [[flat]];
|
||||
float4 border_color [[flat]];
|
||||
uint quad_id [[flat]];
|
||||
float clip_distance [[clip_distance]][4];
|
||||
};
|
||||
|
||||
struct QuadFragmentInput {
|
||||
float4 position [[position]];
|
||||
float4 background_color [[flat]];
|
||||
float4 border_color [[flat]];
|
||||
uint quad_id [[flat]];
|
||||
};
|
||||
|
||||
vertex QuadVertexOutput quad_vertex(uint unit_vertex_id [[vertex_id]],
|
||||
@@ -33,15 +42,21 @@ vertex QuadVertexOutput quad_vertex(uint unit_vertex_id [[vertex_id]],
|
||||
[[buffer(QuadInputIndex_ViewportSize)]]) {
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
Quad quad = quads[quad_id];
|
||||
float4 device_position = to_device_position(
|
||||
unit_vertex, quad.bounds, quad.content_mask.bounds, viewport_size);
|
||||
float4 device_position =
|
||||
to_device_position(unit_vertex, quad.bounds, viewport_size);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds,
|
||||
quad.content_mask.bounds);
|
||||
float4 background_color = hsla_to_rgba(quad.background);
|
||||
float4 border_color = hsla_to_rgba(quad.border_color);
|
||||
return QuadVertexOutput{device_position, background_color, border_color,
|
||||
quad_id};
|
||||
return QuadVertexOutput{
|
||||
device_position,
|
||||
background_color,
|
||||
border_color,
|
||||
quad_id,
|
||||
{clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};
|
||||
}
|
||||
|
||||
fragment float4 quad_fragment(QuadVertexOutput input [[stage_in]],
|
||||
fragment float4 quad_fragment(QuadFragmentInput input [[stage_in]],
|
||||
constant Quad *quads
|
||||
[[buffer(QuadInputIndex_Quads)]]) {
|
||||
Quad quad = quads[input.quad_id];
|
||||
@@ -117,6 +132,13 @@ struct ShadowVertexOutput {
|
||||
float4 position [[position]];
|
||||
float4 color [[flat]];
|
||||
uint shadow_id [[flat]];
|
||||
float clip_distance [[clip_distance]][4];
|
||||
};
|
||||
|
||||
struct ShadowFragmentInput {
|
||||
float4 position [[position]];
|
||||
float4 color [[flat]];
|
||||
uint shadow_id [[flat]];
|
||||
};
|
||||
|
||||
vertex ShadowVertexOutput shadow_vertex(
|
||||
@@ -137,18 +159,20 @@ vertex ShadowVertexOutput shadow_vertex(
|
||||
bounds.size.width += 2. * margin;
|
||||
bounds.size.height += 2. * margin;
|
||||
|
||||
float4 device_position = to_device_position(
|
||||
unit_vertex, bounds, shadow.content_mask.bounds, viewport_size);
|
||||
float4 device_position =
|
||||
to_device_position(unit_vertex, bounds, viewport_size);
|
||||
float4 clip_distance =
|
||||
distance_from_clip_rect(unit_vertex, bounds, shadow.content_mask.bounds);
|
||||
float4 color = hsla_to_rgba(shadow.color);
|
||||
|
||||
return ShadowVertexOutput{
|
||||
device_position,
|
||||
color,
|
||||
shadow_id,
|
||||
};
|
||||
{clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};
|
||||
}
|
||||
|
||||
fragment float4 shadow_fragment(ShadowVertexOutput input [[stage_in]],
|
||||
fragment float4 shadow_fragment(ShadowFragmentInput input [[stage_in]],
|
||||
constant Shadow *shadows
|
||||
[[buffer(ShadowInputIndex_Shadows)]]) {
|
||||
Shadow shadow = shadows[input.shadow_id];
|
||||
@@ -197,6 +221,13 @@ struct UnderlineVertexOutput {
|
||||
float4 position [[position]];
|
||||
float4 color [[flat]];
|
||||
uint underline_id [[flat]];
|
||||
float clip_distance [[clip_distance]][4];
|
||||
};
|
||||
|
||||
struct UnderlineFragmentInput {
|
||||
float4 position [[position]];
|
||||
float4 color [[flat]];
|
||||
uint underline_id [[flat]];
|
||||
};
|
||||
|
||||
vertex UnderlineVertexOutput underline_vertex(
|
||||
@@ -208,13 +239,18 @@ vertex UnderlineVertexOutput underline_vertex(
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
Underline underline = underlines[underline_id];
|
||||
float4 device_position =
|
||||
to_device_position(unit_vertex, underline.bounds,
|
||||
underline.content_mask.bounds, viewport_size);
|
||||
to_device_position(unit_vertex, underline.bounds, viewport_size);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds,
|
||||
underline.content_mask.bounds);
|
||||
float4 color = hsla_to_rgba(underline.color);
|
||||
return UnderlineVertexOutput{device_position, color, underline_id};
|
||||
return UnderlineVertexOutput{
|
||||
device_position,
|
||||
color,
|
||||
underline_id,
|
||||
{clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};
|
||||
}
|
||||
|
||||
fragment float4 underline_fragment(UnderlineVertexOutput input [[stage_in]],
|
||||
fragment float4 underline_fragment(UnderlineFragmentInput input [[stage_in]],
|
||||
constant Underline *underlines
|
||||
[[buffer(UnderlineInputIndex_Underlines)]]) {
|
||||
Underline underline = underlines[input.underline_id];
|
||||
@@ -244,7 +280,13 @@ struct MonochromeSpriteVertexOutput {
|
||||
float4 position [[position]];
|
||||
float2 tile_position;
|
||||
float4 color [[flat]];
|
||||
uint sprite_id [[flat]];
|
||||
float clip_distance [[clip_distance]][4];
|
||||
};
|
||||
|
||||
struct MonochromeSpriteFragmentInput {
|
||||
float4 position [[position]];
|
||||
float2 tile_position;
|
||||
float4 color [[flat]];
|
||||
};
|
||||
|
||||
vertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(
|
||||
@@ -255,32 +297,31 @@ vertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(
|
||||
[[buffer(SpriteInputIndex_ViewportSize)]],
|
||||
constant Size_DevicePixels *atlas_size
|
||||
[[buffer(SpriteInputIndex_AtlasTextureSize)]]) {
|
||||
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
MonochromeSprite sprite = sprites[sprite_id];
|
||||
// Don't apply content mask at the vertex level because we don't have time
|
||||
// to make sampling from the texture match the mask.
|
||||
float4 device_position = to_device_position(unit_vertex, sprite.bounds,
|
||||
sprite.bounds, viewport_size);
|
||||
float4 device_position =
|
||||
to_device_position(unit_vertex, sprite.bounds, viewport_size);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,
|
||||
sprite.content_mask.bounds);
|
||||
float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);
|
||||
float4 color = hsla_to_rgba(sprite.color);
|
||||
return MonochromeSpriteVertexOutput{device_position, tile_position, color,
|
||||
sprite_id};
|
||||
return MonochromeSpriteVertexOutput{
|
||||
device_position,
|
||||
tile_position,
|
||||
color,
|
||||
{clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};
|
||||
}
|
||||
|
||||
fragment float4 monochrome_sprite_fragment(
|
||||
MonochromeSpriteVertexOutput input [[stage_in]],
|
||||
MonochromeSpriteFragmentInput input [[stage_in]],
|
||||
constant MonochromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],
|
||||
texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {
|
||||
MonochromeSprite sprite = sprites[input.sprite_id];
|
||||
constexpr sampler atlas_texture_sampler(mag_filter::linear,
|
||||
min_filter::linear);
|
||||
float4 sample =
|
||||
atlas_texture.sample(atlas_texture_sampler, input.tile_position);
|
||||
float clip_distance = quad_sdf(input.position.xy, sprite.content_mask.bounds,
|
||||
Corners_ScaledPixels{0., 0., 0., 0.});
|
||||
float4 color = input.color;
|
||||
color.a *= sample.a * saturate(0.5 - clip_distance);
|
||||
color.a *= sample.a;
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -288,6 +329,13 @@ struct PolychromeSpriteVertexOutput {
|
||||
float4 position [[position]];
|
||||
float2 tile_position;
|
||||
uint sprite_id [[flat]];
|
||||
float clip_distance [[clip_distance]][4];
|
||||
};
|
||||
|
||||
struct PolychromeSpriteFragmentInput {
|
||||
float4 position [[position]];
|
||||
float2 tile_position;
|
||||
uint sprite_id [[flat]];
|
||||
};
|
||||
|
||||
vertex PolychromeSpriteVertexOutput polychrome_sprite_vertex(
|
||||
@@ -301,17 +349,20 @@ vertex PolychromeSpriteVertexOutput polychrome_sprite_vertex(
|
||||
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
PolychromeSprite sprite = sprites[sprite_id];
|
||||
// Don't apply content mask at the vertex level because we don't have time
|
||||
// to make sampling from the texture match the mask.
|
||||
float4 device_position = to_device_position(unit_vertex, sprite.bounds,
|
||||
sprite.bounds, viewport_size);
|
||||
float4 device_position =
|
||||
to_device_position(unit_vertex, sprite.bounds, viewport_size);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,
|
||||
sprite.content_mask.bounds);
|
||||
float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);
|
||||
return PolychromeSpriteVertexOutput{device_position, tile_position,
|
||||
sprite_id};
|
||||
return PolychromeSpriteVertexOutput{
|
||||
device_position,
|
||||
tile_position,
|
||||
sprite_id,
|
||||
{clip_distance.x, clip_distance.y, clip_distance.z, clip_distance.w}};
|
||||
}
|
||||
|
||||
fragment float4 polychrome_sprite_fragment(
|
||||
PolychromeSpriteVertexOutput input [[stage_in]],
|
||||
PolychromeSpriteFragmentInput input [[stage_in]],
|
||||
constant PolychromeSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],
|
||||
texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {
|
||||
PolychromeSprite sprite = sprites[input.sprite_id];
|
||||
@@ -319,11 +370,8 @@ fragment float4 polychrome_sprite_fragment(
|
||||
min_filter::linear);
|
||||
float4 sample =
|
||||
atlas_texture.sample(atlas_texture_sampler, input.tile_position);
|
||||
float quad_distance =
|
||||
float distance =
|
||||
quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii);
|
||||
float clip_distance = quad_sdf(input.position.xy, sprite.content_mask.bounds,
|
||||
Corners_ScaledPixels{0., 0., 0., 0.});
|
||||
float distance = max(quad_distance, clip_distance);
|
||||
|
||||
float4 color = sample;
|
||||
if (sprite.grayscale) {
|
||||
@@ -385,7 +433,6 @@ struct PathSpriteVertexOutput {
|
||||
float4 position [[position]];
|
||||
float2 tile_position;
|
||||
float4 color [[flat]];
|
||||
uint sprite_id [[flat]];
|
||||
};
|
||||
|
||||
vertex PathSpriteVertexOutput path_sprite_vertex(
|
||||
@@ -401,19 +448,17 @@ vertex PathSpriteVertexOutput path_sprite_vertex(
|
||||
PathSprite sprite = sprites[sprite_id];
|
||||
// Don't apply content mask because it was already accounted for when
|
||||
// rasterizing the path.
|
||||
float4 device_position = to_device_position(unit_vertex, sprite.bounds,
|
||||
sprite.bounds, viewport_size);
|
||||
float4 device_position =
|
||||
to_device_position(unit_vertex, sprite.bounds, viewport_size);
|
||||
float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);
|
||||
float4 color = hsla_to_rgba(sprite.color);
|
||||
return PathSpriteVertexOutput{device_position, tile_position, color,
|
||||
sprite_id};
|
||||
return PathSpriteVertexOutput{device_position, tile_position, color};
|
||||
}
|
||||
|
||||
fragment float4 path_sprite_fragment(
|
||||
PathSpriteVertexOutput input [[stage_in]],
|
||||
constant PathSprite *sprites [[buffer(SpriteInputIndex_Sprites)]],
|
||||
texture2d<float> atlas_texture [[texture(SpriteInputIndex_AtlasTexture)]]) {
|
||||
PathSprite sprite = sprites[input.sprite_id];
|
||||
constexpr sampler atlas_texture_sampler(mag_filter::linear,
|
||||
min_filter::linear);
|
||||
float4 sample =
|
||||
@@ -473,16 +518,10 @@ float4 hsla_to_rgba(Hsla hsla) {
|
||||
}
|
||||
|
||||
float4 to_device_position(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||
Bounds_ScaledPixels clip_bounds,
|
||||
constant Size_DevicePixels *input_viewport_size) {
|
||||
float2 position =
|
||||
unit_vertex * float2(bounds.size.width, bounds.size.height) +
|
||||
float2(bounds.origin.x, bounds.origin.y);
|
||||
position.x = max(clip_bounds.origin.x, position.x);
|
||||
position.x = min(clip_bounds.origin.x + clip_bounds.size.width, position.x);
|
||||
position.y = max(clip_bounds.origin.y, position.y);
|
||||
position.y = min(clip_bounds.origin.y + clip_bounds.size.height, position.y);
|
||||
|
||||
float2 viewport_size = float2((float)input_viewport_size->width,
|
||||
(float)input_viewport_size->height);
|
||||
float2 device_position =
|
||||
@@ -551,3 +590,14 @@ float blur_along_x(float x, float y, float sigma, float corner,
|
||||
0.5 + 0.5 * erf((x + float2(-curved, curved)) * (sqrt(0.5) / sigma));
|
||||
return integral.y - integral.x;
|
||||
}
|
||||
|
||||
float4 distance_from_clip_rect(float2 unit_vertex, Bounds_ScaledPixels bounds,
|
||||
Bounds_ScaledPixels clip_bounds) {
|
||||
float2 position =
|
||||
unit_vertex * float2(bounds.size.width, bounds.size.height) +
|
||||
float2(bounds.origin.x, bounds.origin.y);
|
||||
return float4(position.x - clip_bounds.origin.x,
|
||||
clip_bounds.origin.x + clip_bounds.size.width - position.x,
|
||||
position.y - clip_bounds.origin.y,
|
||||
clip_bounds.origin.y + clip_bounds.size.height - position.y);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
mod dispatcher;
|
||||
mod display;
|
||||
mod platform;
|
||||
mod window;
|
||||
|
||||
pub use dispatcher::*;
|
||||
pub use display::*;
|
||||
pub use platform::*;
|
||||
pub use window::*;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
use anyhow::{Ok, Result};
|
||||
|
||||
use crate::{Bounds, DisplayId, GlobalPixels, PlatformDisplay, Point};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TestDisplay {
|
||||
id: DisplayId,
|
||||
uuid: uuid::Uuid,
|
||||
bounds: Bounds<GlobalPixels>,
|
||||
}
|
||||
|
||||
impl TestDisplay {
|
||||
pub fn new() -> Self {
|
||||
TestDisplay {
|
||||
id: DisplayId(1),
|
||||
uuid: uuid::Uuid::new_v4(),
|
||||
bounds: Bounds::from_corners(
|
||||
Point::zero(),
|
||||
Point::new(GlobalPixels(1920.), GlobalPixels(1080.)),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformDisplay for TestDisplay {
|
||||
fn id(&self) -> crate::DisplayId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn uuid(&self) -> Result<uuid::Uuid> {
|
||||
Ok(self.uuid)
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn bounds(&self) -> crate::Bounds<crate::GlobalPixels> {
|
||||
self.bounds
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,18 @@
|
||||
use crate::{BackgroundExecutor, DisplayId, ForegroundExecutor, Platform, PlatformTextSystem};
|
||||
use crate::{
|
||||
AnyWindowHandle, BackgroundExecutor, CursorStyle, DisplayId, ForegroundExecutor, Platform,
|
||||
PlatformDisplay, PlatformTextSystem, TestDisplay, TestWindow, WindowOptions,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::sync::Arc;
|
||||
use parking_lot::Mutex;
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
|
||||
pub struct TestPlatform {
|
||||
background_executor: BackgroundExecutor,
|
||||
foreground_executor: ForegroundExecutor,
|
||||
|
||||
active_window: Arc<Mutex<Option<AnyWindowHandle>>>,
|
||||
active_display: Rc<dyn PlatformDisplay>,
|
||||
active_cursor: Mutex<CursorStyle>,
|
||||
}
|
||||
|
||||
impl TestPlatform {
|
||||
@@ -12,6 +20,10 @@ impl TestPlatform {
|
||||
TestPlatform {
|
||||
background_executor: executor,
|
||||
foreground_executor,
|
||||
|
||||
active_cursor: Default::default(),
|
||||
active_display: Rc::new(TestDisplay::new()),
|
||||
active_window: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,11 +71,11 @@ impl Platform for TestPlatform {
|
||||
}
|
||||
|
||||
fn displays(&self) -> Vec<std::rc::Rc<dyn crate::PlatformDisplay>> {
|
||||
unimplemented!()
|
||||
vec![self.active_display.clone()]
|
||||
}
|
||||
|
||||
fn display(&self, _id: DisplayId) -> Option<std::rc::Rc<dyn crate::PlatformDisplay>> {
|
||||
unimplemented!()
|
||||
fn display(&self, id: DisplayId) -> Option<std::rc::Rc<dyn crate::PlatformDisplay>> {
|
||||
self.displays().iter().find(|d| d.id() == id).cloned()
|
||||
}
|
||||
|
||||
fn main_window(&self) -> Option<crate::AnyWindowHandle> {
|
||||
@@ -72,10 +84,11 @@ impl Platform for TestPlatform {
|
||||
|
||||
fn open_window(
|
||||
&self,
|
||||
_handle: crate::AnyWindowHandle,
|
||||
_options: crate::WindowOptions,
|
||||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
) -> Box<dyn crate::PlatformWindow> {
|
||||
unimplemented!()
|
||||
*self.active_window.lock() = Some(handle);
|
||||
Box::new(TestWindow::new(options, self.active_display.clone()))
|
||||
}
|
||||
|
||||
fn set_display_link_output_callback(
|
||||
@@ -164,8 +177,8 @@ impl Platform for TestPlatform {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, _style: crate::CursorStyle) {
|
||||
unimplemented!()
|
||||
fn set_cursor_style(&self, style: crate::CursorStyle) {
|
||||
*self.active_cursor.lock() = style;
|
||||
}
|
||||
|
||||
fn should_auto_hide_scrollbars(&self) -> bool {
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use crate::{
|
||||
px, Pixels, PlatformAtlas, PlatformDisplay, PlatformWindow, Point, Scene, Size,
|
||||
WindowAppearance, WindowBounds, WindowOptions,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
struct Handlers {
|
||||
active_status_change: Vec<Box<dyn FnMut(bool)>>,
|
||||
input: Vec<Box<dyn FnMut(crate::InputEvent) -> bool>>,
|
||||
moved: Vec<Box<dyn FnMut()>>,
|
||||
resize: Vec<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||
}
|
||||
|
||||
pub struct TestWindow {
|
||||
bounds: WindowBounds,
|
||||
current_scene: Mutex<Option<Scene>>,
|
||||
display: Rc<dyn PlatformDisplay>,
|
||||
|
||||
handlers: Mutex<Handlers>,
|
||||
sprite_atlas: Arc<dyn PlatformAtlas>,
|
||||
}
|
||||
impl TestWindow {
|
||||
pub fn new(options: WindowOptions, display: Rc<dyn PlatformDisplay>) -> Self {
|
||||
Self {
|
||||
bounds: options.bounds,
|
||||
current_scene: Default::default(),
|
||||
display,
|
||||
|
||||
sprite_atlas: Arc::new(TestAtlas),
|
||||
handlers: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformWindow for TestWindow {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
self.bounds
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
let bounds = match self.bounds {
|
||||
WindowBounds::Fixed(bounds) => bounds,
|
||||
WindowBounds::Maximized | WindowBounds::Fullscreen => self.display().bounds(),
|
||||
};
|
||||
bounds.size.map(|p| px(p.0))
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f32 {
|
||||
2.0
|
||||
}
|
||||
|
||||
fn titlebar_height(&self) -> Pixels {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn appearance(&self) -> WindowAppearance {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn display(&self) -> std::rc::Rc<dyn crate::PlatformDisplay> {
|
||||
self.display.clone()
|
||||
}
|
||||
|
||||
fn mouse_position(&self) -> Point<Pixels> {
|
||||
Point::zero()
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_input_handler(&mut self, _input_handler: Box<dyn crate::PlatformInputHandler>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn prompt(
|
||||
&self,
|
||||
_level: crate::PromptLevel,
|
||||
_msg: &str,
|
||||
_answers: &[&str],
|
||||
) -> futures::channel::oneshot::Receiver<usize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn activate(&self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_title(&mut self, _title: &str) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn set_edited(&mut self, _edited: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn show_character_palette(&self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn minimize(&self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn zoom(&self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn toggle_full_screen(&self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_input(&self, callback: Box<dyn FnMut(crate::InputEvent) -> bool>) {
|
||||
self.handlers.lock().input.push(callback)
|
||||
}
|
||||
|
||||
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
|
||||
self.handlers.lock().active_status_change.push(callback)
|
||||
}
|
||||
|
||||
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
|
||||
self.handlers.lock().resize.push(callback)
|
||||
}
|
||||
|
||||
fn on_fullscreen(&self, _callback: Box<dyn FnMut(bool)>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_moved(&self, callback: Box<dyn FnMut()>) {
|
||||
self.handlers.lock().moved.push(callback)
|
||||
}
|
||||
|
||||
fn on_should_close(&self, _callback: Box<dyn FnMut() -> bool>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_close(&self, _callback: Box<dyn FnOnce()>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_appearance_changed(&self, _callback: Box<dyn FnMut()>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn is_topmost_for_position(&self, _position: crate::Point<Pixels>) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn draw(&self, scene: crate::Scene) {
|
||||
self.current_scene.lock().replace(scene);
|
||||
}
|
||||
|
||||
fn sprite_atlas(&self) -> std::sync::Arc<dyn crate::PlatformAtlas> {
|
||||
self.sprite_atlas.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TestAtlas;
|
||||
|
||||
impl PlatformAtlas for TestAtlas {
|
||||
fn get_or_insert_with<'a>(
|
||||
&self,
|
||||
_key: &crate::AtlasKey,
|
||||
_build: &mut dyn FnMut() -> anyhow::Result<(
|
||||
Size<crate::DevicePixels>,
|
||||
std::borrow::Cow<'a, [u8]>,
|
||||
)>,
|
||||
) -> anyhow::Result<crate::AtlasTile> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn clear(&self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user