summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-07-08 19:31:45 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-07-08 19:31:45 +0200
commitfa55dff61db47197a961152285c6a6abfab0b217 (patch)
tree44904afb16a0cab9e22fce0d73a5616676cd426b
parent1dd1a2f97fc747e15e12b5188dad6c41b0d052ea (diff)
parent66eb6263003c1bbedd1fd14d6b12f172d20a6211 (diff)
downloadiced-fa55dff61db47197a961152285c6a6abfab0b217.tar.gz
iced-fa55dff61db47197a961152285c6a6abfab0b217.tar.bz2
iced-fa55dff61db47197a961152285c6a6abfab0b217.zip
Merge branch 'master' into theming
-rw-r--r--README.md54
-rw-r--r--examples/README.md5
-rw-r--r--examples/integration_wgpu/src/main.rs18
-rw-r--r--examples/integration_wgpu/src/scene.rs12
-rw-r--r--examples/integration_wgpu/src/shader/frag.wgsl4
-rw-r--r--examples/integration_wgpu/src/shader/vert.wgsl4
-rw-r--r--examples/solar_system/src/main.rs8
-rw-r--r--examples/tour/README.md9
-rw-r--r--futures/Cargo.toml2
-rw-r--r--futures/src/subscription/tracker.rs33
-rw-r--r--graphics/Cargo.toml2
-rw-r--r--graphics/src/widget/canvas/text.rs9
-rw-r--r--graphics/src/widget/pure/canvas.rs3
-rw-r--r--lazy/Cargo.toml2
-rw-r--r--lazy/src/component.rs4
-rw-r--r--lazy/src/pure/component.rs14
-rw-r--r--native/Cargo.toml2
-rw-r--r--native/src/shell.rs5
-rw-r--r--native/src/user_interface.rs71
-rw-r--r--native/src/widget/pane_grid/title_bar.rs73
-rw-r--r--pure/Cargo.toml2
-rw-r--r--pure/src/widget/pane_grid/title_bar.rs80
-rw-r--r--pure/src/widget/text_input.rs28
-rw-r--r--wgpu/Cargo.toml8
-rw-r--r--wgpu/src/image.rs22
-rw-r--r--wgpu/src/quad.rs22
-rw-r--r--wgpu/src/settings.rs2
-rw-r--r--wgpu/src/shader/blit.wgsl20
-rw-r--r--wgpu/src/shader/image.wgsl38
-rw-r--r--wgpu/src/shader/quad.wgsl52
-rw-r--r--wgpu/src/shader/triangle.wgsl24
-rw-r--r--wgpu/src/triangle.rs31
-rw-r--r--wgpu/src/triangle/msaa.rs25
-rw-r--r--wgpu/src/window/compositor.rs101
34 files changed, 448 insertions, 341 deletions
diff --git a/README.md b/README.md
index d4b7b39f..abb5b037 100644
--- a/README.md
+++ b/README.md
@@ -18,27 +18,28 @@ Inspired by [Elm].
<img src="https://thumbs.gfycat.com/LittleSaneHalicore-small.gif" height="350px">
</a>
<a href="https://gfycat.com/politeadorableiberianmole">
- <img src="https://thumbs.gfycat.com/PoliteAdorableIberianmole-small.gif">
+ <img src="https://thumbs.gfycat.com/PoliteAdorableIberianmole-small.gif" height="350px">
</a>
</div>
## Features
- * Simple, easy-to-use, batteries-included API
- * Type-safe, reactive programming model
- * [Cross-platform support] (Windows, macOS, Linux, and [the Web])
- * Responsive layout
- * Built-in widgets (including [text inputs], [scrollables], and more!)
- * Custom widget support (create your own!)
- * [Debug overlay with performance metrics]
- * First-class support for async actions (use futures!)
- * [Modular ecosystem] split into reusable parts:
- * A [renderer-agnostic native runtime] enabling integration with existing systems
- * Two [built-in renderers] leveraging [`wgpu`] and [`glow`]
- * [`iced_wgpu`] supporting Vulkan, Metal and DX12
- * [`iced_glow`] supporting OpenGL 2.1+ and OpenGL ES 2.0+
- * A [windowing shell]
- * A [web runtime] leveraging the DOM
+
+* Simple, easy-to-use, batteries-included API
+* Type-safe, reactive programming model
+* [Cross-platform support] (Windows, macOS, Linux, and [the Web])
+* Responsive layout
+* Built-in widgets (including [text inputs], [scrollables], and more!)
+* Custom widget support (create your own!)
+* [Debug overlay with performance metrics]
+* First-class support for async actions (use futures!)
+* [Modular ecosystem] split into reusable parts:
+ * A [renderer-agnostic native runtime] enabling integration with existing systems
+ * Two [built-in renderers] leveraging [`wgpu`] and [`glow`]
+ * [`iced_wgpu`] supporting Vulkan, Metal and DX12
+ * [`iced_glow`] supporting OpenGL 2.1+ and OpenGL ES 2.0+
+ * A [windowing shell]
+ * A [web runtime] leveraging the DOM
__Iced is currently experimental software.__ [Take a look at the roadmap],
[check out the issues], and [feel free to contribute!]
@@ -63,6 +64,7 @@ __Iced is currently experimental software.__ [Take a look at the roadmap],
[feel free to contribute!]: #contributing--feedback
## Installation
+
Add `iced` as a dependency in your `Cargo.toml`:
```toml
@@ -78,15 +80,16 @@ you want to learn about a specific release, check out [the release list].
[the release list]: https://github.com/iced-rs/iced/releases
## Overview
+
Inspired by [The Elm Architecture], Iced expects you to split user interfaces
into four different concepts:
- * __State__ — the state of your application
- * __Messages__ — user interactions or meaningful events that you care
+* __State__ — the state of your application
+* __Messages__ — user interactions or meaningful events that you care
about
- * __View logic__ — a way to display your __state__ as widgets that
+* __View logic__ — a way to display your __state__ as widgets that
may produce __messages__ on user interaction
- * __Update logic__ — a way to react to __messages__ and update your
+* __Update logic__ — a way to react to __messages__ and update your
__state__
We can build something to see how this works! Let's say we want a simple counter
@@ -179,6 +182,7 @@ to:
Browse the [documentation] and the [examples] to learn more!
## Implementation details
+
Iced was originally born as an attempt at bringing the simplicity of [Elm] and
[The Elm Architecture] into [Coffee], a 2D game engine I am working on.
@@ -204,7 +208,9 @@ end-user-oriented GUI library, while keeping [the ecosystem] modular:
[the ecosystem]: ECOSYSTEM.md
## Troubleshooting
+
### `GraphicsAdapterNotFound`
+
This occurs when the selected [built-in renderer] is not able to create a context.
Often this will occur while using [`iced_wgpu`] as the renderer without
@@ -212,22 +218,25 @@ supported hardware (needs Vulkan, Metal or DX12). In this case, you could try us
[`iced_glow`] renderer:
First, check if it works with
+
```console
-$ cargo run --features iced/glow --package game_of_life
+cargo run --features iced/glow --package game_of_life
```
and then use it in your project with
+
```toml
iced = { version = "0.4", default-features = false, features = ["glow"] }
```
-**NOTE:** Chances are you have hardware that supports at least OpenGL 2.1 or OpenGL ES 2.0,
+__NOTE:__ Chances are you have hardware that supports at least OpenGL 2.1 or OpenGL ES 2.0,
but if you don't, right now there's no software fallback, so it means your hardware
doesn't support Iced.
[built-in renderer]: https://github.com/iced-rs/iced/blob/master/ECOSYSTEM.md#Renderers
## Contributing / Feedback
+
Contributions are greatly appreciated! If you want to contribute, please
read our [contributing guidelines] for more details.
@@ -237,6 +246,7 @@ awesome folks) over the `#games-and-graphics` and `#gui-and-ui` channels in
the [Rust Community Discord]. I go by `lone_scientist#9554` there.
## Sponsors
+
The development of Iced is sponsored by the [Cryptowatch] team at [Kraken.com]
[documentation]: https://docs.rs/iced/
diff --git a/examples/README.md b/examples/README.md
index 137d134c..2b4919df 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -27,10 +27,6 @@ You can run the native version with `cargo run`:
cargo run --package tour
```
-The web version can be run by following [the usage instructions of `iced_web`] or by accessing [iced.rs](https://iced.rs/)!
-
-[the usage instructions of `iced_web`]: https://github.com/iced-rs/iced_web#usage
-
## [Todos](todos)
A todos tracker inspired by [TodoMVC]. It showcases dynamic layout, text input, checkboxes, scrollables, icons, and async actions! It automatically saves your tasks in the background, even if you did not finish typing them.
@@ -46,7 +42,6 @@ You can run the native version with `cargo run`:
```
cargo run --package todos
```
-We have not yet implemented a `LocalStorage` version of the auto-save feature. Therefore, it does not work on web _yet_!
[TodoMVC]: http://todomvc.com/
diff --git a/examples/integration_wgpu/src/main.rs b/examples/integration_wgpu/src/main.rs
index 76f35eef..1108b55d 100644
--- a/examples/integration_wgpu/src/main.rs
+++ b/examples/integration_wgpu/src/main.rs
@@ -7,7 +7,6 @@ use scene::Scene;
use iced_wgpu::{wgpu, Backend, Renderer, Settings, Viewport};
use iced_winit::{conversion, futures, program, winit, Clipboard, Debug, Size};
-use futures::task::SpawnExt;
use winit::{
dpi::PhysicalPosition,
event::{Event, ModifiersState, WindowEvent},
@@ -91,7 +90,9 @@ pub fn main() {
(
surface
- .get_preferred_format(&adapter)
+ .get_supported_formats(&adapter)
+ .first()
+ .copied()
.expect("Get preferred format"),
adapter
.request_device(
@@ -114,15 +115,14 @@ pub fn main() {
format,
width: physical_size.width,
height: physical_size.height,
- present_mode: wgpu::PresentMode::Mailbox,
+ present_mode: wgpu::PresentMode::AutoVsync,
},
);
let mut resized = false;
- // Initialize staging belt and local pool
+ // Initialize staging belt
let mut staging_belt = wgpu::util::StagingBelt::new(5 * 1024);
- let mut local_pool = futures::executor::LocalPool::new();
// Initialize scene and GUI controls
let scene = Scene::new(&mut device, format);
@@ -208,7 +208,7 @@ pub fn main() {
format: format,
width: size.width,
height: size.height,
- present_mode: wgpu::PresentMode::Mailbox,
+ present_mode: wgpu::PresentMode::AutoVsync,
},
);
@@ -263,12 +263,8 @@ pub fn main() {
);
// And recall staging buffers
- local_pool
- .spawner()
- .spawn(staging_belt.recall())
- .expect("Recall staging buffers");
+ staging_belt.recall();
- local_pool.run_until_stalled();
}
Err(error) => match error {
wgpu::SurfaceError::OutOfMemory => {
diff --git a/examples/integration_wgpu/src/scene.rs b/examples/integration_wgpu/src/scene.rs
index fbda1326..af75e67c 100644
--- a/examples/integration_wgpu/src/scene.rs
+++ b/examples/integration_wgpu/src/scene.rs
@@ -23,7 +23,7 @@ impl Scene {
) -> wgpu::RenderPass<'a> {
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
- color_attachments: &[wgpu::RenderPassColorAttachment {
+ color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: target,
resolve_target: None,
ops: wgpu::Operations {
@@ -39,7 +39,7 @@ impl Scene {
}),
store: true,
},
- }],
+ })],
depth_stencil_attachment: None,
})
}
@@ -55,8 +55,8 @@ fn build_pipeline(
texture_format: wgpu::TextureFormat,
) -> wgpu::RenderPipeline {
let (vs_module, fs_module) = (
- device.create_shader_module(&wgpu::include_wgsl!("shader/vert.wgsl")),
- device.create_shader_module(&wgpu::include_wgsl!("shader/frag.wgsl")),
+ device.create_shader_module(wgpu::include_wgsl!("shader/vert.wgsl")),
+ device.create_shader_module(wgpu::include_wgsl!("shader/frag.wgsl")),
);
let pipeline_layout =
@@ -78,14 +78,14 @@ fn build_pipeline(
fragment: Some(wgpu::FragmentState {
module: &fs_module,
entry_point: "main",
- targets: &[wgpu::ColorTargetState {
+ targets: &[Some(wgpu::ColorTargetState {
format: texture_format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent::REPLACE,
alpha: wgpu::BlendComponent::REPLACE,
}),
write_mask: wgpu::ColorWrites::ALL,
- }],
+ })],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
diff --git a/examples/integration_wgpu/src/shader/frag.wgsl b/examples/integration_wgpu/src/shader/frag.wgsl
index a6f61336..cf27bb56 100644
--- a/examples/integration_wgpu/src/shader/frag.wgsl
+++ b/examples/integration_wgpu/src/shader/frag.wgsl
@@ -1,4 +1,4 @@
-[[stage(fragment)]]
-fn main() -> [[location(0)]] vec4<f32> {
+@fragment
+fn main() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}
diff --git a/examples/integration_wgpu/src/shader/vert.wgsl b/examples/integration_wgpu/src/shader/vert.wgsl
index 7ef47fb2..e353e6ba 100644
--- a/examples/integration_wgpu/src/shader/vert.wgsl
+++ b/examples/integration_wgpu/src/shader/vert.wgsl
@@ -1,5 +1,5 @@
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] in_vertex_index: u32) -> [[builtin(position)]] vec4<f32> {
+@vertex
+fn main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
let x = f32(1 - i32(in_vertex_index)) * 0.5;
let y = f32(1 - i32(in_vertex_index & 1u) * 2) * 0.5;
return vec4<f32>(x, y, 0.0, 1.0);
diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs
index 5f6c309d..7e0e06b0 100644
--- a/examples/solar_system/src/main.rs
+++ b/examples/solar_system/src/main.rs
@@ -73,6 +73,10 @@ impl Application for SolarSystem {
.height(Length::Fill)
.into()
}
+
+ fn theme(&self) -> Theme {
+ Theme::Dark
+ }
}
#[derive(Debug)]
@@ -142,16 +146,12 @@ impl<Message> canvas::Program<Message> for State {
use std::f32::consts::PI;
let background = self.space_cache.draw(bounds.size(), |frame| {
- let space = Path::rectangle(Point::new(0.0, 0.0), frame.size());
-
let stars = Path::new(|path| {
for (p, size) in &self.stars {
path.rectangle(*p, Size::new(*size, *size));
}
});
- frame.fill(&space, Color::BLACK);
-
frame.translate(frame.center() - Point::ORIGIN);
frame.fill(&stars, Color::WHITE);
});
diff --git a/examples/tour/README.md b/examples/tour/README.md
index e7cd2d5c..731e7e66 100644
--- a/examples/tour/README.md
+++ b/examples/tour/README.md
@@ -23,6 +23,11 @@ You can run the native version with `cargo run`:
cargo run --package tour
```
-The web version can be run by following [the usage instructions of `iced_web`] or by accessing [iced.rs](https://iced.rs/)!
+The web version can be run with [`trunk`]:
-[the usage instructions of `iced_web`]: https://github.com/iced-rs/iced_web#usage
+```
+cd examples/tour
+trunk serve
+```
+
+[`trunk`]: https://trunkrs.dev/
diff --git a/futures/Cargo.toml b/futures/Cargo.toml
index ed99d79a..61ee00a5 100644
--- a/futures/Cargo.toml
+++ b/futures/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_futures"
-version = "0.4.0"
+version = "0.4.1"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2021"
description = "Commands, subscriptions, and runtimes for Iced"
diff --git a/futures/src/subscription/tracker.rs b/futures/src/subscription/tracker.rs
index 421fb917..2cf98284 100644
--- a/futures/src/subscription/tracker.rs
+++ b/futures/src/subscription/tracker.rs
@@ -1,6 +1,9 @@
use crate::{BoxFuture, MaybeSend, Subscription};
-use futures::{channel::mpsc, sink::Sink};
+use futures::{
+ channel::mpsc,
+ sink::{Sink, SinkExt},
+};
use std::{collections::HashMap, marker::PhantomData};
/// A registry of subscription streams.
@@ -64,7 +67,7 @@ where
+ MaybeSend
+ Clone,
{
- use futures::{future::FutureExt, stream::StreamExt};
+ use futures::stream::StreamExt;
let mut futures: Vec<BoxFuture<()>> = Vec::new();
@@ -85,19 +88,29 @@ where
continue;
}
- let (cancel, cancelled) = futures::channel::oneshot::channel();
+ let (cancel, mut canceled) = futures::channel::oneshot::channel();
// TODO: Use bus if/when it supports async
let (event_sender, event_receiver) =
futures::channel::mpsc::channel(100);
- let stream = recipe.stream(event_receiver.boxed());
-
- let future = futures::future::select(
- cancelled,
- stream.map(Ok).forward(receiver.clone()),
- )
- .map(|_| ());
+ let mut receiver = receiver.clone();
+ let mut stream = recipe.stream(event_receiver.boxed());
+
+ let future = async move {
+ loop {
+ let select =
+ futures::future::select(&mut canceled, stream.next());
+
+ match select.await {
+ futures::future::Either::Left(_)
+ | futures::future::Either::Right((None, _)) => break,
+ futures::future::Either::Right((Some(message), _)) => {
+ let _ = receiver.send(message).await;
+ }
+ }
+ }
+ };
let _ = self.subscriptions.insert(
id,
diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml
index e916975d..a27c5d7c 100644
--- a/graphics/Cargo.toml
+++ b/graphics/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_graphics"
-version = "0.3.0"
+version = "0.3.1"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2021"
description = "A bunch of backend-agnostic types that can be leveraged to build a renderer for Iced"
diff --git a/graphics/src/widget/canvas/text.rs b/graphics/src/widget/canvas/text.rs
index ab070a70..056f8204 100644
--- a/graphics/src/widget/canvas/text.rs
+++ b/graphics/src/widget/canvas/text.rs
@@ -6,7 +6,14 @@ use crate::{Color, Font, Point};
pub struct Text {
/// The contents of the text
pub content: String,
- /// The position where to begin drawing the text (top-left corner coordinates)
+ /// The position of the text relative to the alignment properties.
+ /// By default, this position will be relative to the top-left corner coordinate meaning that
+ /// if the horizontal and vertical alignments are unchanged, this property will tell where the
+ /// top-left corner of the text should be placed.
+ /// By changing the horizontal_alignment and vertical_alignment properties, you are are able to
+ /// change what part of text is placed at this positions.
+ /// For example, when the horizontal_alignment and vertical_alignment are set to Center, the
+ /// center of the text will be placed at the given position NOT the top-left coordinate.
pub position: Point,
/// The color of the text
pub color: Color,
diff --git a/graphics/src/widget/pure/canvas.rs b/graphics/src/widget/pure/canvas.rs
index d9c7e66b..0eeff3d1 100644
--- a/graphics/src/widget/pure/canvas.rs
+++ b/graphics/src/widget/pure/canvas.rs
@@ -111,7 +111,8 @@ where
B: Backend,
{
fn tag(&self) -> tree::Tag {
- tree::Tag::of::<P::State>()
+ struct Tag<T>(T);
+ tree::Tag::of::<Tag<P::State>>()
}
fn state(&self) -> tree::State {
diff --git a/lazy/Cargo.toml b/lazy/Cargo.toml
index 7d439e47..9a184dd1 100644
--- a/lazy/Cargo.toml
+++ b/lazy/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_lazy"
-version = "0.1.0"
+version = "0.1.1"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2021"
description = "Lazy widgets for Iced"
diff --git a/lazy/src/component.rs b/lazy/src/component.rs
index 3f22bc7d..2c6b6ffb 100644
--- a/lazy/src/component.rs
+++ b/lazy/src/component.rs
@@ -419,9 +419,7 @@ where
Some(
CacheBuilder {
element: state.view(),
- overlay_builder: |element| {
- element.overlay(layout, renderer)
- },
+ overlay_builder: |_| None,
}
.build(),
)
diff --git a/lazy/src/pure/component.rs b/lazy/src/pure/component.rs
index b19913ae..9b29b628 100644
--- a/lazy/src/pure/component.rs
+++ b/lazy/src/pure/component.rs
@@ -70,8 +70,6 @@ where
})
}
-struct Tag<T>(T);
-
struct Instance<'a, Message, Renderer, Event, S> {
state: RefCell<Option<State<'a, Message, Renderer, Event, S>>>,
}
@@ -132,6 +130,7 @@ where
Renderer: iced_native::Renderer,
{
fn tag(&self) -> tree::Tag {
+ struct Tag<T>(T);
tree::Tag::of::<Tag<S>>()
}
@@ -467,16 +466,7 @@ where
instance_ref_builder: |instance| instance.state.borrow(),
tree: overlay.tree,
types: PhantomData,
- overlay_builder: |instance, tree| {
- instance
- .as_ref()
- .unwrap()
- .borrow_element()
- .as_ref()
- .unwrap()
- .as_widget()
- .overlay(&mut tree.children[0], layout, renderer)
- },
+ overlay_builder: |_, _| None,
}
.build(),
);
diff --git a/native/Cargo.toml b/native/Cargo.toml
index a21385de..b4945c05 100644
--- a/native/Cargo.toml
+++ b/native/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_native"
-version = "0.5.0"
+version = "0.5.1"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2021"
description = "A renderer-agnostic library for native GUIs"
diff --git a/native/src/shell.rs b/native/src/shell.rs
index 4a0aa9c6..b96d23e5 100644
--- a/native/src/shell.rs
+++ b/native/src/shell.rs
@@ -31,6 +31,11 @@ impl<'a, Message> Shell<'a, Message> {
}
}
+ /// Returns whether the current layout is invalid or not.
+ pub fn is_layout_invalid(&self) -> bool {
+ self.is_layout_invalid
+ }
+
/// Publish the given `Message` for an application to process it.
pub fn publish(&mut self, message: Message) {
self.messages.push(message);
diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 26850f0a..d682a880 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -179,40 +179,61 @@ where
clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>,
) -> (State, Vec<event::Status>) {
+ use std::mem::ManuallyDrop;
+
let mut state = State::Updated;
+ let mut manual_overlay = ManuallyDrop::new(
+ self.root.overlay(Layout::new(&self.base), renderer),
+ );
- let (base_cursor, overlay_statuses) = if let Some(mut overlay) =
- self.root.overlay(Layout::new(&self.base), renderer)
- {
+ let (base_cursor, overlay_statuses) = if manual_overlay.is_some() {
let bounds = self.bounds;
+
+ let mut overlay = manual_overlay.as_mut().unwrap();
let mut layout = overlay.layout(renderer, bounds);
+ let mut event_statuses = Vec::new();
- let event_statuses = events
- .iter()
- .cloned()
- .map(|event| {
- let mut shell = Shell::new(messages);
+ for event in events.iter().cloned() {
+ let mut shell = Shell::new(messages);
- let event_status = overlay.on_event(
- event,
- Layout::new(&layout),
- cursor_position,
- renderer,
- clipboard,
- &mut shell,
+ let event_status = overlay.on_event(
+ event,
+ Layout::new(&layout),
+ cursor_position,
+ renderer,
+ clipboard,
+ &mut shell,
+ );
+
+ event_statuses.push(event_status);
+
+ if shell.is_layout_invalid() {
+ let _ = ManuallyDrop::into_inner(manual_overlay);
+
+ self.base = renderer.layout(
+ &self.root,
+ &layout::Limits::new(Size::ZERO, self.bounds),
);
+ manual_overlay = ManuallyDrop::new(
+ self.root.overlay(Layout::new(&self.base), renderer),
+ );
+
+ if manual_overlay.is_none() {
+ break;
+ }
+
+ overlay = manual_overlay.as_mut().unwrap();
+
shell.revalidate_layout(|| {
layout = overlay.layout(renderer, bounds);
});
+ }
- if shell.are_widgets_invalid() {
- state = State::Outdated;
- }
-
- event_status
- })
- .collect();
+ if shell.are_widgets_invalid() {
+ state = State::Outdated;
+ }
+ }
let base_cursor = if layout.bounds().contains(cursor_position) {
// TODO: Type-safe cursor availability
@@ -228,11 +249,17 @@ where
(cursor_position, vec![event::Status::Ignored; events.len()])
};
+ let _ = ManuallyDrop::into_inner(manual_overlay);
+
let event_statuses = events
.iter()
.cloned()
.zip(overlay_statuses.into_iter())
.map(|(event, overlay_status)| {
+ if matches!(overlay_status, event::Status::Captured) {
+ return overlay_status;
+ }
+
let mut shell = Shell::new(messages);
let event_status = self.root.widget.on_event(
diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs
index 2a028dd5..14c3ab4e 100644
--- a/native/src/widget/pane_grid/title_bar.rs
+++ b/native/src/widget/pane_grid/title_bar.rs
@@ -114,20 +114,17 @@ where
let mut children = padded.children();
let title_layout = children.next().unwrap();
-
- self.content.draw(
- renderer,
- theme,
- &inherited_style,
- title_layout,
- cursor_position,
- viewport,
- );
+ let mut show_title = true;
if let Some(controls) = &self.controls {
let controls_layout = children.next().unwrap();
if show_controls || self.always_show_controls {
+ if title_layout.bounds().width + controls_layout.bounds().width
+ > padded.bounds().width
+ {
+ show_title = false;
+ }
controls.draw(
renderer,
theme,
@@ -138,6 +135,17 @@ where
);
}
}
+
+ if show_title {
+ self.content.draw(
+ renderer,
+ theme,
+ &inherited_style,
+ title_layout,
+ cursor_position,
+ viewport,
+ );
+ }
}
/// Returns whether the mouse cursor is over the pick area of the
@@ -225,9 +233,15 @@ where
let mut children = padded.children();
let title_layout = children.next().unwrap();
+ let mut show_title = true;
let control_status = if let Some(controls) = &mut self.controls {
let controls_layout = children.next().unwrap();
+ if title_layout.bounds().width + controls_layout.bounds().width
+ > padded.bounds().width
+ {
+ show_title = false;
+ }
controls.on_event(
event.clone(),
@@ -241,14 +255,18 @@ where
event::Status::Ignored
};
- let title_status = self.content.on_event(
- event,
- title_layout,
- cursor_position,
- renderer,
- clipboard,
- shell,
- );
+ let title_status = if show_title {
+ self.content.on_event(
+ event,
+ title_layout,
+ cursor_position,
+ renderer,
+ clipboard,
+ shell,
+ )
+ } else {
+ event::Status::Ignored
+ };
control_status.merge(title_status)
}
@@ -275,15 +293,20 @@ where
if let Some(controls) = &self.controls {
let controls_layout = children.next().unwrap();
+ let controls_interaction = controls.mouse_interaction(
+ controls_layout,
+ cursor_position,
+ viewport,
+ renderer,
+ );
- controls
- .mouse_interaction(
- controls_layout,
- cursor_position,
- viewport,
- renderer,
- )
- .max(title_interaction)
+ if title_layout.bounds().width + controls_layout.bounds().width
+ > padded.bounds().width
+ {
+ controls_interaction
+ } else {
+ controls_interaction.max(title_interaction)
+ }
} else {
title_interaction
}
diff --git a/pure/Cargo.toml b/pure/Cargo.toml
index 2301031d..b57e4c5a 100644
--- a/pure/Cargo.toml
+++ b/pure/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_pure"
-version = "0.2.1"
+version = "0.2.2"
edition = "2021"
description = "Pure widgets for Iced"
license = "MIT"
diff --git a/pure/src/widget/pane_grid/title_bar.rs b/pure/src/widget/pane_grid/title_bar.rs
index 950fd990..de9591a2 100644
--- a/pure/src/widget/pane_grid/title_bar.rs
+++ b/pure/src/widget/pane_grid/title_bar.rs
@@ -141,19 +141,15 @@ where
let mut children = padded.children();
let title_layout = children.next().unwrap();
-
- self.content.as_widget().draw(
- &tree.children[0],
- renderer,
- theme,
- &inherited_style,
- title_layout,
- cursor_position,
- viewport,
- );
+ let mut show_title = true;
if let Some(controls) = &self.controls {
let controls_layout = children.next().unwrap();
+ if title_layout.bounds().width + controls_layout.bounds().width
+ > padded.bounds().width
+ {
+ show_title = false;
+ }
if show_controls || self.always_show_controls {
controls.as_widget().draw(
@@ -167,6 +163,18 @@ where
);
}
}
+
+ if show_title {
+ self.content.as_widget().draw(
+ &tree.children[0],
+ renderer,
+ theme,
+ &inherited_style,
+ title_layout,
+ cursor_position,
+ viewport,
+ );
+ }
}
/// Returns whether the mouse cursor is over the pick area of the
@@ -258,9 +266,15 @@ where
let mut children = padded.children();
let title_layout = children.next().unwrap();
+ let mut show_title = true;
let control_status = if let Some(controls) = &mut self.controls {
let controls_layout = children.next().unwrap();
+ if title_layout.bounds().width + controls_layout.bounds().width
+ > padded.bounds().width
+ {
+ show_title = false;
+ }
controls.as_widget_mut().on_event(
&mut tree.children[1],
@@ -275,15 +289,19 @@ where
event::Status::Ignored
};
- let title_status = self.content.as_widget_mut().on_event(
- &mut tree.children[0],
- event,
- title_layout,
- cursor_position,
- renderer,
- clipboard,
- shell,
- );
+ let title_status = if show_title {
+ self.content.as_widget_mut().on_event(
+ &mut tree.children[0],
+ event,
+ title_layout,
+ cursor_position,
+ renderer,
+ clipboard,
+ shell,
+ )
+ } else {
+ event::Status::Ignored
+ };
control_status.merge(title_status)
}
@@ -312,17 +330,21 @@ where
if let Some(controls) = &self.controls {
let controls_layout = children.next().unwrap();
+ let controls_interaction = controls.as_widget().mouse_interaction(
+ &tree.children[1],
+ controls_layout,
+ cursor_position,
+ viewport,
+ renderer,
+ );
- controls
- .as_widget()
- .mouse_interaction(
- &tree.children[1],
- controls_layout,
- cursor_position,
- viewport,
- renderer,
- )
- .max(title_interaction)
+ if title_layout.bounds().width + controls_layout.bounds().width
+ > padded.bounds().width
+ {
+ controls_interaction
+ } else {
+ controls_interaction.max(title_interaction)
+ }
} else {
title_interaction
}
diff --git a/pure/src/widget/text_input.rs b/pure/src/widget/text_input.rs
index d3e642a5..9b0a466a 100644
--- a/pure/src/widget/text_input.rs
+++ b/pure/src/widget/text_input.rs
@@ -126,6 +126,34 @@ where
self.style = style.into();
self
}
+
+ /// Draws the [`TextInput`] with the given [`Renderer`], overriding its
+ /// [`text_input::Value`] if provided.
+ ///
+ /// [`Renderer`]: text::Renderer
+ pub fn draw(
+ &self,
+ tree: &Tree,
+ renderer: &mut Renderer,
+ theme: &Renderer::Theme,
+ layout: Layout<'_>,
+ cursor_position: Point,
+ value: Option<&text_input::Value>,
+ ) {
+ text_input::draw(
+ renderer,
+ theme,
+ layout,
+ cursor_position,
+ tree.state.downcast_ref::<text_input::State>(),
+ value.unwrap_or(&self.value),
+ &self.placeholder,
+ self.size,
+ &self.font,
+ self.is_secure,
+ self.style,
+ )
+ }
}
impl<'a, Message, Renderer> Widget<Message, Renderer>
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml
index 6911ff56..586f97d3 100644
--- a/wgpu/Cargo.toml
+++ b/wgpu/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_wgpu"
-version = "0.5.0"
+version = "0.5.1"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2021"
description = "A wgpu renderer for Iced"
@@ -28,8 +28,8 @@ spirv = ["wgpu/spirv"]
webgl = ["wgpu/webgl"]
[dependencies]
-wgpu = "0.12"
-wgpu_glyph = "0.16"
+wgpu = "0.13"
+wgpu_glyph = "0.17"
glyph_brush = "0.7"
raw-window-handle = "0.4"
log = "0.4"
@@ -39,7 +39,7 @@ kamadak-exif = "0.5"
bitflags = "1.2"
[dependencies.bytemuck]
-version = "1.4"
+version = "1.9"
features = ["derive"]
[dependencies.iced_native]
diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs
index 0fefbfaf..750ad62a 100644
--- a/wgpu/src/image.rs
+++ b/wgpu/src/image.rs
@@ -136,7 +136,7 @@ impl Pipeline {
});
let shader =
- device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu::image::shader"),
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
include_str!("shader/image.wgsl"),
@@ -176,7 +176,7 @@ impl Pipeline {
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
- targets: &[wgpu::ColorTargetState {
+ targets: &[Some(wgpu::ColorTargetState {
format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent {
@@ -191,7 +191,7 @@ impl Pipeline {
},
}),
write_mask: wgpu::ColorWrites::ALL,
- }],
+ })],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
@@ -406,14 +406,16 @@ impl Pipeline {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::image render pass"),
- color_attachments: &[wgpu::RenderPassColorAttachment {
- view: target,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: true,
+ color_attachments: &[Some(
+ wgpu::RenderPassColorAttachment {
+ view: target,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: true,
+ },
},
- }],
+ )],
depth_stencil_attachment: None,
});
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs
index 22f3b815..a117df64 100644
--- a/wgpu/src/quad.rs
+++ b/wgpu/src/quad.rs
@@ -59,7 +59,7 @@ impl Pipeline {
});
let shader =
- device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu::quad::shader"),
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
include_str!("shader/quad.wgsl"),
@@ -100,7 +100,7 @@ impl Pipeline {
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
- targets: &[wgpu::ColorTargetState {
+ targets: &[Some(wgpu::ColorTargetState {
format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent {
@@ -115,7 +115,7 @@ impl Pipeline {
},
}),
write_mask: wgpu::ColorWrites::ALL,
- }],
+ })],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
@@ -211,14 +211,16 @@ impl Pipeline {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::quad render pass"),
- color_attachments: &[wgpu::RenderPassColorAttachment {
- view: target,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: true,
+ color_attachments: &[Some(
+ wgpu::RenderPassColorAttachment {
+ view: target,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: true,
+ },
},
- }],
+ )],
depth_stencil_attachment: None,
});
diff --git a/wgpu/src/settings.rs b/wgpu/src/settings.rs
index 23b55904..7bc752ff 100644
--- a/wgpu/src/settings.rs
+++ b/wgpu/src/settings.rs
@@ -63,7 +63,7 @@ impl Settings {
impl Default for Settings {
fn default() -> Settings {
Settings {
- present_mode: wgpu::PresentMode::Mailbox,
+ present_mode: wgpu::PresentMode::AutoVsync,
internal_backend: wgpu::Backends::all(),
default_font: None,
default_text_size: 20,
diff --git a/wgpu/src/shader/blit.wgsl b/wgpu/src/shader/blit.wgsl
index f8f6e2d4..c2ea223f 100644
--- a/wgpu/src/shader/blit.wgsl
+++ b/wgpu/src/shader/blit.wgsl
@@ -16,19 +16,19 @@ var<private> uvs: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
vec2<f32>(1.0, 1.0)
);
-[[group(0), binding(0)]] var u_sampler: sampler;
-[[group(1), binding(0)]] var u_texture: texture_2d<f32>;
+@group(0) @binding(0) var u_sampler: sampler;
+@group(1) @binding(0) var u_texture: texture_2d<f32>;
struct VertexInput {
- [[builtin(vertex_index)]] vertex_index: u32;
-};
+ @builtin(vertex_index) vertex_index: u32,
+}
struct VertexOutput {
- [[builtin(position)]] position: vec4<f32>;
- [[location(0)]] uv: vec2<f32>;
-};
+ @builtin(position) position: vec4<f32>,
+ @location(0) uv: vec2<f32>,
+}
-[[stage(vertex)]]
+@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
var out: VertexOutput;
out.uv = uvs[input.vertex_index];
@@ -37,7 +37,7 @@ fn vs_main(input: VertexInput) -> VertexOutput {
return out;
}
-[[stage(fragment)]]
-fn fs_main(input: VertexOutput) -> [[location(0)]] vec4<f32> {
+@fragment
+fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
return textureSample(u_texture, u_sampler, input.uv);
}
diff --git a/wgpu/src/shader/image.wgsl b/wgpu/src/shader/image.wgsl
index ff304422..5e22cdf4 100644
--- a/wgpu/src/shader/image.wgsl
+++ b/wgpu/src/shader/image.wgsl
@@ -1,27 +1,27 @@
struct Globals {
- transform: mat4x4<f32>;
-};
+ transform: mat4x4<f32>,
+}
-[[group(0), binding(0)]] var<uniform> globals: Globals;
-[[group(0), binding(1)]] var u_sampler: sampler;
-[[group(1), binding(0)]] var u_texture: texture_2d_array<f32>;
+@group(0) @binding(0) var<uniform> globals: Globals;
+@group(0) @binding(1) var u_sampler: sampler;
+@group(1) @binding(0) var u_texture: texture_2d_array<f32>;
struct VertexInput {
- [[location(0)]] v_pos: vec2<f32>;
- [[location(1)]] pos: vec2<f32>;
- [[location(2)]] scale: vec2<f32>;
- [[location(3)]] atlas_pos: vec2<f32>;
- [[location(4)]] atlas_scale: vec2<f32>;
- [[location(5)]] layer: i32;
-};
+ @location(0) v_pos: vec2<f32>,
+ @location(1) pos: vec2<f32>,
+ @location(2) scale: vec2<f32>,
+ @location(3) atlas_pos: vec2<f32>,
+ @location(4) atlas_scale: vec2<f32>,
+ @location(5) layer: i32,
+}
struct VertexOutput {
- [[builtin(position)]] position: vec4<f32>;
- [[location(0)]] uv: vec2<f32>;
- [[location(1)]] layer: f32; // this should be an i32, but naga currently reads that as requiring interpolation.
-};
+ @builtin(position) position: vec4<f32>,
+ @location(0) uv: vec2<f32>,
+ @location(1) layer: f32, // this should be an i32, but naga currently reads that as requiring interpolation.
+}
-[[stage(vertex)]]
+@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
var out: VertexOutput;
@@ -40,7 +40,7 @@ fn vs_main(input: VertexInput) -> VertexOutput {
return out;
}
-[[stage(fragment)]]
-fn fs_main(input: VertexOutput) -> [[location(0)]] vec4<f32> {
+@fragment
+fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
return textureSample(u_texture, u_sampler, input.uv, i32(input.layer));
}
diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl
index 73f5d597..73edd97c 100644
--- a/wgpu/src/shader/quad.wgsl
+++ b/wgpu/src/shader/quad.wgsl
@@ -1,31 +1,31 @@
struct Globals {
- transform: mat4x4<f32>;
- scale: f32;
-};
+ transform: mat4x4<f32>,
+ scale: f32,
+}
-[[group(0), binding(0)]] var<uniform> globals: Globals;
+@group(0) @binding(0) var<uniform> globals: Globals;
struct VertexInput {
- [[location(0)]] v_pos: vec2<f32>;
- [[location(1)]] pos: vec2<f32>;
- [[location(2)]] scale: vec2<f32>;
- [[location(3)]] color: vec4<f32>;
- [[location(4)]] border_color: vec4<f32>;
- [[location(5)]] border_radius: f32;
- [[location(6)]] border_width: f32;
-};
+ @location(0) v_pos: vec2<f32>,
+ @location(1) pos: vec2<f32>,
+ @location(2) scale: vec2<f32>,
+ @location(3) color: vec4<f32>,
+ @location(4) border_color: vec4<f32>,
+ @location(5) border_radius: f32,
+ @location(6) border_width: f32,
+}
struct VertexOutput {
- [[builtin(position)]] position: vec4<f32>;
- [[location(0)]] color: vec4<f32>;
- [[location(1)]] border_color: vec4<f32>;
- [[location(2)]] pos: vec2<f32>;
- [[location(3)]] scale: vec2<f32>;
- [[location(4)]] border_radius: f32;
- [[location(5)]] border_width: f32;
-};
-
-[[stage(vertex)]]
+ @builtin(position) position: vec4<f32>,
+ @location(0) color: vec4<f32>,
+ @location(1) border_color: vec4<f32>,
+ @location(2) pos: vec2<f32>,
+ @location(3) scale: vec2<f32>,
+ @location(4) border_radius: f32,
+ @location(5) border_width: f32,
+}
+
+@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
var out: VertexOutput;
@@ -77,10 +77,10 @@ fn distance_alg(
}
-[[stage(fragment)]]
+@fragment
fn fs_main(
input: VertexOutput
-) -> [[location(0)]] vec4<f32> {
+) -> @location(0) vec4<f32> {
var mixed_color: vec4<f32> = input.color;
if (input.border_width > 0.0) {
@@ -96,7 +96,7 @@ fn fs_main(
internal_border
);
- var border_mix: f32 = smoothStep(
+ var border_mix: f32 = smoothstep(
max(internal_border - 0.5, 0.0),
internal_border + 0.5,
internal_distance
@@ -112,7 +112,7 @@ fn fs_main(
input.border_radius
);
- var radius_alpha: f32 = 1.0 - smoothStep(
+ var radius_alpha: f32 = 1.0 - smoothstep(
max(input.border_radius - 0.5, 0.0),
input.border_radius + 0.5,
dist);
diff --git a/wgpu/src/shader/triangle.wgsl b/wgpu/src/shader/triangle.wgsl
index 61d9c5a4..b24402f8 100644
--- a/wgpu/src/shader/triangle.wgsl
+++ b/wgpu/src/shader/triangle.wgsl
@@ -1,20 +1,20 @@
struct Globals {
- transform: mat4x4<f32>;
-};
+ transform: mat4x4<f32>,
+}
-[[group(0), binding(0)]] var<uniform> globals: Globals;
+@group(0) @binding(0) var<uniform> globals: Globals;
struct VertexInput {
- [[location(0)]] position: vec2<f32>;
- [[location(1)]] color: vec4<f32>;
-};
+ @location(0) position: vec2<f32>,
+ @location(1) color: vec4<f32>,
+}
struct VertexOutput {
- [[builtin(position)]] position: vec4<f32>;
- [[location(0)]] color: vec4<f32>;
-};
+ @builtin(position) position: vec4<f32>,
+ @location(0) color: vec4<f32>,
+}
-[[stage(vertex)]]
+@vertex
fn vs_main(input: VertexInput) -> VertexOutput {
var out: VertexOutput;
@@ -24,7 +24,7 @@ fn vs_main(input: VertexInput) -> VertexOutput {
return out;
}
-[[stage(fragment)]]
-fn fs_main(input: VertexOutput) -> [[location(0)]] vec4<f32> {
+@fragment
+fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
return input.color;
}
diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs
index c702243b..40e2f855 100644
--- a/wgpu/src/triangle.rs
+++ b/wgpu/src/triangle.rs
@@ -132,7 +132,7 @@ impl Pipeline {
});
let shader =
- device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu::triangle::shader"),
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
include_str!("shader/triangle.wgsl"),
@@ -160,22 +160,11 @@ impl Pipeline {
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
- targets: &[wgpu::ColorTargetState {
+ targets: &[Some(wgpu::ColorTargetState {
format,
- blend: Some(wgpu::BlendState {
- color: wgpu::BlendComponent {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha: wgpu::BlendComponent {
- src_factor: wgpu::BlendFactor::One,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- }),
+ blend: Some(wgpu::BlendState::ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
- }],
+ })],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
@@ -361,11 +350,13 @@ impl Pipeline {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::triangle render pass"),
- color_attachments: &[wgpu::RenderPassColorAttachment {
- view: attachment,
- resolve_target,
- ops: wgpu::Operations { load, store: true },
- }],
+ color_attachments: &[Some(
+ wgpu::RenderPassColorAttachment {
+ view: attachment,
+ resolve_target,
+ ops: wgpu::Operations { load, store: true },
+ },
+ )],
depth_stencil_attachment: None,
});
diff --git a/wgpu/src/triangle/msaa.rs b/wgpu/src/triangle/msaa.rs
index 9fb87544..7edeeb94 100644
--- a/wgpu/src/triangle/msaa.rs
+++ b/wgpu/src/triangle/msaa.rs
@@ -74,7 +74,7 @@ impl Blit {
});
let shader =
- device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu::triangle::blit_shader"),
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
include_str!("../shader/blit.wgsl"),
@@ -93,22 +93,13 @@ impl Blit {
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
- targets: &[wgpu::ColorTargetState {
+ targets: &[Some(wgpu::ColorTargetState {
format,
- blend: Some(wgpu::BlendState {
- color: wgpu::BlendComponent {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha: wgpu::BlendComponent {
- src_factor: wgpu::BlendFactor::One,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- }),
+ blend: Some(
+ wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
+ ),
write_mask: wgpu::ColorWrites::ALL,
- }],
+ })],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
@@ -178,14 +169,14 @@ impl Blit {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::triangle::msaa render pass"),
- color_attachments: &[wgpu::RenderPassColorAttachment {
+ color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: target,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
store: true,
},
- }],
+ })],
depth_stencil_attachment: None,
});
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index bfb18bfa..fa1f441a 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -1,6 +1,7 @@
use crate::{Backend, Color, Error, Renderer, Settings, Viewport};
-use futures::task::SpawnExt;
+use futures::stream::{self, StreamExt};
+
use iced_graphics::compositor;
use iced_native::futures;
use raw_window_handle::HasRawWindowHandle;
@@ -16,7 +17,6 @@ pub struct Compositor<Theme> {
device: wgpu::Device,
queue: wgpu::Queue,
staging_belt: wgpu::util::StagingBelt,
- local_pool: futures::executor::LocalPool,
format: wgpu::TextureFormat,
theme: PhantomData<Theme>,
}
@@ -62,38 +62,43 @@ impl<Theme> Compositor<Theme> {
log::info!("Selected: {:#?}", adapter.get_info());
- let format = compatible_surface
- .as_ref()
- .and_then(|surface| surface.get_preferred_format(&adapter))?;
+ let format = compatible_surface.as_ref().and_then(|surface| {
+ surface.get_supported_formats(&adapter).first().copied()
+ })?;
log::info!("Selected format: {:?}", format);
#[cfg(target_arch = "wasm32")]
- let limits = wgpu::Limits::downlevel_webgl2_defaults()
- .using_resolution(adapter.limits());
+ let limits = [wgpu::Limits::downlevel_webgl2_defaults()
+ .using_resolution(adapter.limits())];
#[cfg(not(target_arch = "wasm32"))]
- let limits = wgpu::Limits::downlevel_defaults();
-
- let (device, queue) = adapter
- .request_device(
- &wgpu::DeviceDescriptor {
- label: Some(
- "iced_wgpu::window::compositor device descriptor",
- ),
- features: wgpu::Features::empty(),
- limits: wgpu::Limits {
- max_bind_groups: 2,
- ..limits
+ let limits =
+ [wgpu::Limits::default(), wgpu::Limits::downlevel_defaults()];
+
+ let limits = limits.into_iter().map(|limits| wgpu::Limits {
+ max_bind_groups: 2,
+ ..limits
+ });
+
+ let (device, queue) = stream::iter(limits)
+ .filter_map(|limits| async {
+ adapter.request_device(
+ &wgpu::DeviceDescriptor {
+ label: Some(
+ "iced_wgpu::window::compositor device descriptor",
+ ),
+ features: wgpu::Features::empty(),
+ limits,
},
- },
- None,
- )
- .await
- .ok()?;
+ None,
+ ).await.ok()
+ })
+ .boxed()
+ .next()
+ .await?;
let staging_belt = wgpu::util::StagingBelt::new(Self::CHUNK_SIZE);
- let local_pool = futures::executor::LocalPool::new();
Some(Compositor {
instance,
@@ -102,7 +107,6 @@ impl<Theme> Compositor<Theme> {
device,
queue,
staging_belt,
- local_pool,
format,
theme: PhantomData,
})
@@ -196,24 +200,26 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
label: Some(
"iced_wgpu::window::Compositor render pass",
),
- color_attachments: &[wgpu::RenderPassColorAttachment {
- view,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Clear({
- let [r, g, b, a] =
- background_color.into_linear();
-
- wgpu::Color {
- r: f64::from(r),
- g: f64::from(g),
- b: f64::from(b),
- a: f64::from(a),
- }
- }),
- store: true,
+ color_attachments: &[Some(
+ wgpu::RenderPassColorAttachment {
+ view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Clear({
+ let [r, g, b, a] =
+ background_color.into_linear();
+
+ wgpu::Color {
+ r: f64::from(r),
+ g: f64::from(g),
+ b: f64::from(b),
+ a: f64::from(a),
+ }
+ }),
+ store: true,
+ },
},
- }],
+ )],
depth_stencil_attachment: None,
});
@@ -231,16 +237,11 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
// Submit work
self.staging_belt.finish();
- self.queue.submit(Some(encoder.finish()));
+ let _submission = self.queue.submit(Some(encoder.finish()));
frame.present();
// Recall staging buffers
- self.local_pool
- .spawner()
- .spawn(self.staging_belt.recall())
- .expect("Recall staging belt");
-
- self.local_pool.run_until_stalled();
+ self.staging_belt.recall();
Ok(())
}