WIP raw-window-handle 0.6

This commit is contained in:
Ian Douglas Scott 2024-01-09 07:19:15 -08:00
parent ff268c8c42
commit 7289b6091b
8 changed files with 142 additions and 102 deletions

View file

@ -70,6 +70,8 @@ thiserror.workspace = true
image.workspace = true image.workspace = true
image.optional = true image.optional = true
winit.workspace = true
[profile.release-opt] [profile.release-opt]
inherits = "release" inherits = "release"
codegen-units = 1 codegen-units = 1
@ -126,7 +128,10 @@ bytemuck = { version = "1.0", features = ["derive"] }
cosmic-text = "0.10" cosmic-text = "0.10"
futures = "0.3" futures = "0.3"
glam = "0.24" glam = "0.24"
glyphon = "0.4" # glyphon = "0.4"
# TODO update for wgpu 0.19
# https://github.com/grovesNL/glyphon/pull/80
glyphon = { git = "https://github.com/EggShark/glyphon" }
guillotiere = "0.6" guillotiere = "0.6"
half = "2.2" half = "2.2"
image = "0.24" image = "0.24"
@ -140,12 +145,12 @@ once_cell = "1.0"
ouroboros = "0.17" ouroboros = "0.17"
palette = "0.7" palette = "0.7"
qrcode = { version = "0.12", default-features = false } qrcode = { version = "0.12", default-features = false }
raw-window-handle = "0.5" raw-window-handle = "0.6"
resvg = "0.36" resvg = "0.36"
rustc-hash = "1.0" rustc-hash = "1.0"
smol = "1.0" smol = "1.0"
smol_str = "0.2" smol_str = "0.2"
softbuffer = "0.3.4" softbuffer = "0.4.1"
syntect = "5.1" syntect = "5.1"
sysinfo = "0.28" sysinfo = "0.28"
thiserror = "1.0" thiserror = "1.0"
@ -158,7 +163,8 @@ wasm-bindgen-futures = "0.4"
wasm-timer = "0.2" wasm-timer = "0.2"
web-sys = "0.3" web-sys = "0.3"
web-time = "0.2" web-time = "0.2"
wgpu = "0.18" wgpu = "0.19"
winapi = "0.3" winapi = "0.3"
window_clipboard = "0.3" # window_clipboard = "0.3"
winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5", features = ["rwh_05"] } window_clipboard = { git = "https://github.com/ids1024/window_clipboard", branch = "raw-window-handle-0.6" }
winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5", features = ["rwh_06"] }

View file

@ -4,11 +4,11 @@ use crate::{Error, Viewport};
use iced_core::Color; use iced_core::Color;
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use thiserror::Error; use thiserror::Error;
/// A graphics compositor that can draw to windows. /// A graphics compositor that can draw to windows.
pub trait Compositor: Sized { pub trait Compositor<W: HasWindowHandle + HasDisplayHandle>: Sized {
/// The settings of the backend. /// The settings of the backend.
type Settings: Default; type Settings: Default;
@ -19,9 +19,9 @@ pub trait Compositor: Sized {
type Surface; type Surface;
/// Creates a new [`Compositor`]. /// Creates a new [`Compositor`].
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( fn new(
settings: Self::Settings, settings: Self::Settings,
compatible_window: Option<&W>, compatible_window: Option<W>,
) -> Result<Self, Error>; ) -> Result<Self, Error>;
/// Creates a [`Self::Renderer`] for the [`Compositor`]. /// Creates a [`Self::Renderer`] for the [`Compositor`].
@ -30,9 +30,9 @@ pub trait Compositor: Sized {
/// Crates a new [`Surface`] for the given window. /// Crates a new [`Surface`] for the given window.
/// ///
/// [`Surface`]: Self::Surface /// [`Surface`]: Self::Surface
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( fn create_surface(
&mut self, &mut self,
window: &W, window: W,
width: u32, width: u32,
height: u32, height: u32,
) -> Self::Surface; ) -> Self::Surface;

View file

@ -3,29 +3,36 @@ use crate::graphics::compositor::{Information, SurfaceError};
use crate::graphics::{Error, Viewport}; use crate::graphics::{Error, Viewport};
use crate::{Renderer, Settings}; use crate::{Renderer, Settings};
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::env; use std::env;
pub enum Compositor<Theme> { pub enum Compositor<W: HasWindowHandle + HasDisplayHandle, Theme> {
TinySkia(iced_tiny_skia::window::Compositor<Theme>), TinySkia(iced_tiny_skia::window::Compositor<W, Theme>),
#[cfg(feature = "wgpu")] #[cfg(feature = "wgpu")]
Wgpu(iced_wgpu::window::Compositor<Theme>), Wgpu(iced_wgpu::window::Compositor<W, Theme>),
} }
pub enum Surface { pub enum Surface<W: HasWindowHandle + HasDisplayHandle> {
TinySkia(iced_tiny_skia::window::Surface), TinySkia(iced_tiny_skia::window::Surface<W>),
#[cfg(feature = "wgpu")] #[cfg(feature = "wgpu")]
Wgpu(iced_wgpu::window::Surface), Wgpu(iced_wgpu::window::Surface<'static>),
} }
impl<Theme> crate::graphics::Compositor for Compositor<Theme> { // XXX Clone bound
// XXX Send/Sync?
// 'static?
impl<
W: Clone + Send + Sync + HasWindowHandle + HasDisplayHandle + 'static,
Theme,
> crate::graphics::Compositor<W> for Compositor<W, Theme>
{
type Settings = Settings; type Settings = Settings;
type Renderer = Renderer<Theme>; type Renderer = Renderer<Theme>;
type Surface = Surface; type Surface = Surface<W>;
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( fn new(
settings: Self::Settings, settings: Self::Settings,
compatible_window: Option<&W>, compatible_window: Option<W>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let candidates = let candidates =
Candidate::list_from_env().unwrap_or(Candidate::default_list()); Candidate::list_from_env().unwrap_or(Candidate::default_list());
@ -33,7 +40,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
let mut error = Error::GraphicsAdapterNotFound; let mut error = Error::GraphicsAdapterNotFound;
for candidate in candidates { for candidate in candidates {
match candidate.build(settings, compatible_window) { match candidate.build(settings, compatible_window.clone()) {
Ok(compositor) => return Ok(compositor), Ok(compositor) => return Ok(compositor),
Err(new_error) => { Err(new_error) => {
error = new_error; error = new_error;
@ -56,12 +63,12 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
} }
} }
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( fn create_surface(
&mut self, &mut self,
window: &W, window: W,
width: u32, width: u32,
height: u32, height: u32,
) -> Surface { ) -> Surface<W> {
match self { match self {
Self::TinySkia(compositor) => Surface::TinySkia( Self::TinySkia(compositor) => Surface::TinySkia(
compositor.create_surface(window, width, height), compositor.create_surface(window, width, height),
@ -75,7 +82,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
fn configure_surface( fn configure_surface(
&mut self, &mut self,
surface: &mut Surface, surface: &mut Surface<W>,
width: u32, width: u32,
height: u32, height: u32,
) { ) {
@ -114,7 +121,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
( (
Self::TinySkia(_compositor), Self::TinySkia(_compositor),
crate::Renderer::TinySkia(renderer), crate::Renderer::TinySkia(renderer),
Surface::TinySkia(surface), Surface::TinySkia(ref mut surface),
) => renderer.with_primitives(|backend, primitives| { ) => renderer.with_primitives(|backend, primitives| {
iced_tiny_skia::window::compositor::present( iced_tiny_skia::window::compositor::present(
backend, backend,
@ -129,7 +136,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
( (
Self::Wgpu(compositor), Self::Wgpu(compositor),
crate::Renderer::Wgpu(renderer), crate::Renderer::Wgpu(renderer),
Surface::Wgpu(surface), Surface::Wgpu(ref mut surface),
) => renderer.with_primitives(|backend, primitives| { ) => renderer.with_primitives(|backend, primitives| {
iced_wgpu::window::compositor::present( iced_wgpu::window::compositor::present(
compositor, compositor,
@ -161,7 +168,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
( (
Self::TinySkia(_compositor), Self::TinySkia(_compositor),
Renderer::TinySkia(renderer), Renderer::TinySkia(renderer),
Surface::TinySkia(surface), Surface::TinySkia(ref mut surface),
) => renderer.with_primitives(|backend, primitives| { ) => renderer.with_primitives(|backend, primitives| {
iced_tiny_skia::window::compositor::screenshot( iced_tiny_skia::window::compositor::screenshot(
surface, surface,
@ -226,11 +233,11 @@ impl Candidate {
) )
} }
fn build<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>( fn build<Theme, W: HasWindowHandle + HasDisplayHandle + Send + Sync>(
self, self,
settings: Settings, settings: Settings,
_compatible_window: Option<&W>, _compatible_window: Option<W>,
) -> Result<Compositor<Theme>, Error> { ) -> Result<Compositor<W, Theme>, Error> {
match self { match self {
Self::TinySkia => { Self::TinySkia => {
let compositor = iced_tiny_skia::window::compositor::new( let compositor = iced_tiny_skia::window::compositor::new(

View file

@ -1,6 +1,8 @@
//! Build interactive cross-platform applications. //! Build interactive cross-platform applications.
use crate::{Command, Element, Executor, Settings, Subscription}; use crate::{Command, Element, Executor, Settings, Subscription};
use std::sync::Arc;
pub use crate::style::application::{Appearance, StyleSheet}; pub use crate::style::application::{Appearance, StyleSheet};
/// An interactive cross-platform application. /// An interactive cross-platform application.
@ -208,7 +210,10 @@ pub trait Application: Sized {
Ok(crate::shell::application::run::< Ok(crate::shell::application::run::<
Instance<Self>, Instance<Self>,
Self::Executor, Self::Executor,
crate::renderer::Compositor<Self::Theme>, crate::renderer::Compositor<
Arc<winit::window::Window>,
Self::Theme,
>,
>(settings.into(), renderer_settings)?) >(settings.into(), renderer_settings)?)
} }
} }

View file

@ -4,33 +4,36 @@ use crate::graphics::damage;
use crate::graphics::{Error, Viewport}; use crate::graphics::{Error, Viewport};
use crate::{Backend, Primitive, Renderer, Settings}; use crate::{Backend, Primitive, Renderer, Settings};
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::num::NonZeroU32; use std::num::NonZeroU32;
pub struct Compositor<Theme> { pub struct Compositor<W: HasDisplayHandle + HasWindowHandle, Theme> {
context: Option<softbuffer::Context>, context: Option<softbuffer::Context<W>>,
settings: Settings, settings: Settings,
_theme: PhantomData<Theme>, _theme: PhantomData<Theme>,
} }
pub struct Surface { pub struct Surface<W: HasDisplayHandle + HasWindowHandle> {
window: softbuffer::Surface, window: softbuffer::Surface<W, W>,
clip_mask: tiny_skia::Mask, clip_mask: tiny_skia::Mask,
// Primitives of existing buffers, by decreasing age // Primitives of existing buffers, by decreasing age
primitives: VecDeque<Vec<Primitive>>, primitives: VecDeque<Vec<Primitive>>,
background_color: Color, background_color: Color,
} }
impl<Theme> crate::graphics::Compositor for Compositor<Theme> { // XXX avoid clone bound?
impl<W: HasDisplayHandle + HasWindowHandle + Clone, Theme>
crate::graphics::Compositor<W> for Compositor<W, Theme>
{
type Settings = Settings; type Settings = Settings;
type Renderer = Renderer<Theme>; type Renderer = Renderer<Theme>;
type Surface = Surface; type Surface = Surface<W>;
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( fn new(
settings: Self::Settings, settings: Self::Settings,
compatible_window: Option<&W>, compatible_window: Option<W>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Ok(new(settings, compatible_window)) Ok(new(settings, compatible_window))
} }
@ -43,20 +46,19 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
) )
} }
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( fn create_surface(
&mut self, &mut self,
window: &W, window: W,
width: u32, width: u32,
height: u32, height: u32,
) -> Surface { ) -> Surface<W> {
#[allow(unsafe_code)]
let window = if let Some(context) = self.context.as_ref() { let window = if let Some(context) = self.context.as_ref() {
unsafe { softbuffer::Surface::new(context, window) } softbuffer::Surface::new(context, window)
.expect("Create softbuffer surface for window") .expect("Create softbuffer surface for window")
} else { } else {
let context = unsafe { softbuffer::Context::new(window) } let context = softbuffer::Context::new(window.clone())
.expect("Create softbuffer context for window"); .expect("Create softbuffer context for window");
unsafe { softbuffer::Surface::new(&context, window) } softbuffer::Surface::new(&context, window)
.expect("Create softbuffer surface for window") .expect("Create softbuffer surface for window")
}; };
@ -71,7 +73,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
fn configure_surface( fn configure_surface(
&mut self, &mut self,
surface: &mut Surface, surface: &mut Surface<W>,
width: u32, width: u32,
height: u32, height: u32,
) { ) {
@ -90,7 +92,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
fn present<T: AsRef<str>>( fn present<T: AsRef<str>>(
&mut self, &mut self,
renderer: &mut Self::Renderer, renderer: &mut Self::Renderer,
surface: &mut Self::Surface, surface: &mut Surface<W>,
viewport: &Viewport, viewport: &Viewport,
background_color: Color, background_color: Color,
overlay: &[T], overlay: &[T],
@ -128,13 +130,13 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
} }
} }
pub fn new<W: HasRawWindowHandle + HasRawDisplayHandle, Theme>( pub fn new<W: HasWindowHandle + HasDisplayHandle, Theme>(
settings: Settings, settings: Settings,
compatible_window: Option<&W>, compatible_window: Option<W>,
) -> Compositor<Theme> { ) -> Compositor<W, Theme> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
let context = compatible_window let context =
.and_then(|w| unsafe { softbuffer::Context::new(w) }.ok()); compatible_window.and_then(|w| softbuffer::Context::new(w).ok());
Compositor { Compositor {
context, context,
settings, settings,
@ -142,9 +144,9 @@ pub fn new<W: HasRawWindowHandle + HasRawDisplayHandle, Theme>(
} }
} }
pub fn present<T: AsRef<str>>( pub fn present<W: HasDisplayHandle + HasWindowHandle, T: AsRef<str>>(
backend: &mut Backend, backend: &mut Backend,
surface: &mut Surface, surface: &mut Surface<W>,
primitives: &[Primitive], primitives: &[Primitive],
viewport: &Viewport, viewport: &Viewport,
background_color: Color, background_color: Color,
@ -216,8 +218,8 @@ pub fn present<T: AsRef<str>>(
buffer.present().map_err(|_| compositor::SurfaceError::Lost) buffer.present().map_err(|_| compositor::SurfaceError::Lost)
} }
pub fn screenshot<T: AsRef<str>>( pub fn screenshot<W: HasDisplayHandle + HasWindowHandle, T: AsRef<str>>(
surface: &mut Surface, surface: &mut Surface<W>,
backend: &mut Backend, backend: &mut Backend,
primitives: &[Primitive], primitives: &[Primitive],
viewport: &Viewport, viewport: &Viewport,

View file

@ -6,13 +6,13 @@ use crate::graphics::compositor;
use crate::graphics::{Error, Viewport}; use crate::graphics::{Error, Viewport};
use crate::{Backend, Primitive, Renderer, Settings}; use crate::{Backend, Primitive, Renderer, Settings};
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::marker::PhantomData; use std::marker::PhantomData;
/// A window graphics backend for iced powered by `wgpu`. /// A window graphics backend for iced powered by `wgpu`.
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Compositor<Theme> { pub struct Compositor<W, Theme> {
settings: Settings, settings: Settings,
instance: wgpu::Instance, instance: wgpu::Instance,
adapter: wgpu::Adapter, adapter: wgpu::Adapter,
@ -20,15 +20,18 @@ pub struct Compositor<Theme> {
queue: wgpu::Queue, queue: wgpu::Queue,
format: wgpu::TextureFormat, format: wgpu::TextureFormat,
theme: PhantomData<Theme>, theme: PhantomData<Theme>,
w: PhantomData<W>,
} }
impl<Theme> Compositor<Theme> { impl<W: HasWindowHandle + HasDisplayHandle + wgpu::WasmNotSendSync, Theme>
Compositor<W, Theme>
{
/// Requests a new [`Compositor`] with the given [`Settings`]. /// Requests a new [`Compositor`] with the given [`Settings`].
/// ///
/// Returns `None` if no compatible graphics adapter could be found. /// Returns `None` if no compatible graphics adapter could be found.
pub async fn request<W: HasRawWindowHandle + HasRawDisplayHandle>( pub async fn request(
settings: Settings, settings: Settings,
compatible_window: Option<&W>, compatible_window: Option<W>,
) -> Option<Self> { ) -> Option<Self> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: settings.internal_backend, backends: settings.internal_backend,
@ -41,6 +44,7 @@ impl<Theme> Compositor<Theme> {
if log::max_level() >= log::LevelFilter::Info { if log::max_level() >= log::LevelFilter::Info {
let available_adapters: Vec<_> = instance let available_adapters: Vec<_> = instance
.enumerate_adapters(settings.internal_backend) .enumerate_adapters(settings.internal_backend)
.iter()
.map(|adapter| adapter.get_info()) .map(|adapter| adapter.get_info())
.collect(); .collect();
log::info!("Available adapters: {available_adapters:#?}"); log::info!("Available adapters: {available_adapters:#?}");
@ -48,7 +52,7 @@ impl<Theme> Compositor<Theme> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
let compatible_surface = compatible_window let compatible_surface = compatible_window
.and_then(|window| unsafe { instance.create_surface(window).ok() }); .and_then(|window| instance.create_surface(window).ok());
let adapter = instance let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions { .request_adapter(&wgpu::RequestAdapterOptions {
@ -100,14 +104,14 @@ impl<Theme> Compositor<Theme> {
let (device, queue) = let (device, queue) =
loop { loop {
let limits = limits.next()?; let required_limits = limits.next()?;
let device = adapter.request_device( let device = adapter.request_device(
&wgpu::DeviceDescriptor { &wgpu::DeviceDescriptor {
label: Some( label: Some(
"iced_wgpu::window::compositor device descriptor", "iced_wgpu::window::compositor device descriptor",
), ),
features: wgpu::Features::empty(), required_features: wgpu::Features::empty(),
limits, required_limits,
}, },
None, None,
).await.ok(); ).await.ok();
@ -125,6 +129,7 @@ impl<Theme> Compositor<Theme> {
queue, queue,
format, format,
theme: PhantomData, theme: PhantomData,
w: PhantomData,
}) })
} }
@ -136,10 +141,13 @@ impl<Theme> Compositor<Theme> {
/// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and /// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and
/// window. /// window.
pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>( pub fn new<
Theme,
W: HasWindowHandle + HasDisplayHandle + wgpu::WasmNotSendSync,
>(
settings: Settings, settings: Settings,
compatible_window: Option<&W>, compatible_window: Option<W>,
) -> Result<Compositor<Theme>, Error> { ) -> Result<Compositor<W, Theme>, Error> {
let compositor = futures::executor::block_on(Compositor::request( let compositor = futures::executor::block_on(Compositor::request(
settings, settings,
compatible_window, compatible_window,
@ -150,10 +158,10 @@ pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>(
} }
/// Presents the given primitives with the given [`Compositor`] and [`Backend`]. /// Presents the given primitives with the given [`Compositor`] and [`Backend`].
pub fn present<Theme, T: AsRef<str>>( pub fn present<W, Theme, T: AsRef<str>>(
compositor: &mut Compositor<Theme>, compositor: &mut Compositor<W, Theme>,
backend: &mut Backend, backend: &mut Backend,
surface: &mut wgpu::Surface, surface: &mut wgpu::Surface<'static>,
primitives: &[Primitive], primitives: &[Primitive],
viewport: &Viewport, viewport: &Viewport,
background_color: Color, background_color: Color,
@ -204,14 +212,19 @@ pub fn present<Theme, T: AsRef<str>>(
} }
} }
impl<Theme> graphics::Compositor for Compositor<Theme> { impl<
W: HasDisplayHandle + HasWindowHandle + wgpu::WasmNotSendSync + 'static,
Theme,
> graphics::Compositor<W> for Compositor<W, Theme>
{
type Settings = Settings; type Settings = Settings;
type Renderer = Renderer<Theme>; type Renderer = Renderer<Theme>;
type Surface = wgpu::Surface; // XXX generic instead of 'static
type Surface = wgpu::Surface<'static>;
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( fn new(
settings: Self::Settings, settings: Self::Settings,
compatible_window: Option<&W>, compatible_window: Option<W>,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
new(settings, compatible_window) new(settings, compatible_window)
} }
@ -224,14 +237,15 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
) )
} }
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( fn create_surface(
&mut self, &mut self,
window: &W, window: W,
width: u32, width: u32,
height: u32, height: u32,
) -> wgpu::Surface { ) -> wgpu::Surface<'static> {
#[allow(unsafe_code)] let mut surface = self
let mut surface = unsafe { self.instance.create_surface(window) } .instance
.create_surface(window)
.expect("Create surface"); .expect("Create surface");
self.configure_surface(&mut surface, width, height); self.configure_surface(&mut surface, width, height);
@ -241,7 +255,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
fn configure_surface( fn configure_surface(
&mut self, &mut self,
surface: &mut Self::Surface, surface: &mut wgpu::Surface<'static>,
width: u32, width: u32,
height: u32, height: u32,
) { ) {
@ -255,6 +269,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
height, height,
alpha_mode: wgpu::CompositeAlphaMode::Auto, alpha_mode: wgpu::CompositeAlphaMode::Auto,
view_formats: vec![], view_formats: vec![],
desired_maximum_frame_latency: 2,
}, },
); );
} }
@ -271,7 +286,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
fn present<T: AsRef<str>>( fn present<T: AsRef<str>>(
&mut self, &mut self,
renderer: &mut Self::Renderer, renderer: &mut Self::Renderer,
surface: &mut Self::Surface, surface: &mut wgpu::Surface<'static>,
viewport: &Viewport, viewport: &Viewport,
background_color: Color, background_color: Color,
overlay: &[T], overlay: &[T],
@ -292,7 +307,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
fn screenshot<T: AsRef<str>>( fn screenshot<T: AsRef<str>>(
&mut self, &mut self,
renderer: &mut Self::Renderer, renderer: &mut Self::Renderer,
_surface: &mut Self::Surface, _surface: &mut wgpu::Surface<'static>,
viewport: &Viewport, viewport: &Viewport,
background_color: Color, background_color: Color,
overlay: &[T], overlay: &[T],
@ -313,8 +328,8 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
/// Renders the current surface to an offscreen buffer. /// Renders the current surface to an offscreen buffer.
/// ///
/// Returns RGBA bytes of the texture data. /// Returns RGBA bytes of the texture data.
pub fn screenshot<Theme, T: AsRef<str>>( pub fn screenshot<W, Theme, T: AsRef<str>>(
compositor: &Compositor<Theme>, compositor: &Compositor<W, Theme>,
backend: &mut Backend, backend: &mut Backend,
primitives: &[Primitive], primitives: &[Primitive],
viewport: &Viewport, viewport: &Viewport,

View file

@ -24,6 +24,7 @@ use crate::{Clipboard, Error, Proxy, Settings};
use futures::channel::mpsc; use futures::channel::mpsc;
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
use std::sync::Arc;
/// An interactive, native cross-platform application. /// An interactive, native cross-platform application.
/// ///
@ -105,7 +106,7 @@ pub fn run<A, E, C>(
where where
A: Application + 'static, A: Application + 'static,
E: Executor + 'static, E: Executor + 'static,
C: Compositor<Renderer = A::Renderer> + 'static, C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
<A::Renderer as core::Renderer>::Theme: StyleSheet, <A::Renderer as core::Renderer>::Theme: StyleSheet,
{ {
use futures::task; use futures::task;
@ -149,9 +150,12 @@ where
log::debug!("Window builder: {builder:#?}"); log::debug!("Window builder: {builder:#?}");
let window = builder // XXX Arc?
.build(&event_loop) let window = Arc::new(
.map_err(Error::WindowCreationFailed)?; builder
.build(&event_loop)
.map_err(Error::WindowCreationFailed)?,
);
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
{ {
@ -183,7 +187,7 @@ where
}; };
} }
let compositor = C::new(compositor_settings, Some(&window))?; let compositor = C::new(compositor_settings, Some(window.clone()))?;
let mut renderer = compositor.create_renderer(); let mut renderer = compositor.create_renderer();
for font in settings.fonts { for font in settings.fonts {
@ -248,13 +252,13 @@ async fn run_instance<A, E, C>(
>, >,
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>, mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
init_command: Command<A::Message>, init_command: Command<A::Message>,
window: winit::window::Window, window: Arc<winit::window::Window>,
should_be_visible: bool, should_be_visible: bool,
exit_on_close_request: bool, exit_on_close_request: bool,
) where ) where
A: Application + 'static, A: Application + 'static,
E: Executor + 'static, E: Executor + 'static,
C: Compositor<Renderer = A::Renderer> + 'static, C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
<A::Renderer as core::Renderer>::Theme: StyleSheet, <A::Renderer as core::Renderer>::Theme: StyleSheet,
{ {
use futures::stream::StreamExt; use futures::stream::StreamExt;
@ -268,7 +272,7 @@ async fn run_instance<A, E, C>(
let mut clipboard = Clipboard::connect(&window); let mut clipboard = Clipboard::connect(&window);
let mut cache = user_interface::Cache::default(); let mut cache = user_interface::Cache::default();
let mut surface = compositor.create_surface( let mut surface = compositor.create_surface(
&window, window.clone(),
physical_size.width, physical_size.width,
physical_size.height, physical_size.height,
); );
@ -608,7 +612,7 @@ pub fn update<A: Application, C, E: Executor>(
messages: &mut Vec<A::Message>, messages: &mut Vec<A::Message>,
window: &winit::window::Window, window: &winit::window::Window,
) where ) where
C: Compositor<Renderer = A::Renderer> + 'static, C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
<A::Renderer as core::Renderer>::Theme: StyleSheet, <A::Renderer as core::Renderer>::Theme: StyleSheet,
{ {
for message in messages.drain(..) { for message in messages.drain(..) {
@ -659,7 +663,7 @@ pub fn run_command<A, C, E>(
) where ) where
A: Application, A: Application,
E: Executor, E: Executor,
C: Compositor<Renderer = A::Renderer> + 'static, C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
<A::Renderer as core::Renderer>::Theme: StyleSheet, <A::Renderer as core::Renderer>::Theme: StyleSheet,
{ {
use crate::runtime::command; use crate::runtime::command;

View file

@ -15,7 +15,8 @@ enum State {
impl Clipboard { impl Clipboard {
/// Creates a new [`Clipboard`] for the given window. /// Creates a new [`Clipboard`] for the given window.
pub fn connect(window: &winit::window::Window) -> Clipboard { pub fn connect(window: &winit::window::Window) -> Clipboard {
let state = window_clipboard::Clipboard::connect(window) #[allow(unsafe_code)]
let state = unsafe { window_clipboard::Clipboard::connect(window) }
.ok() .ok()
.map(State::Connected) .map(State::Connected)
.unwrap_or(State::Unavailable); .unwrap_or(State::Unavailable);