Skip to content

Split Application::run to expose EventLoop and Window.#50

Closed
Matthias-Fauconneau wants to merge 12 commits into
iced-rs:masterfrom
Matthias-Fauconneau:feature-config
Closed

Split Application::run to expose EventLoop and Window.#50
Matthias-Fauconneau wants to merge 12 commits into
iced-rs:masterfrom
Matthias-Fauconneau:feature-config

Conversation

@Matthias-Fauconneau
Copy link
Copy Markdown
Contributor

I'm not sure what iced platform abstraction plan is, since winit does it already (including web).
This splits Application::run in new+run to expose EventLoop and Window.
I don't think wrapping platform details makes much sense, so, for iced_winit, I chose to directly expose winit::event_loop::EventLoop and winit::window::Window for now.
If this was stable, that would mean the other iced platform(s) would need to be wrapped to match the exposed winit interface.
On the other hand, that seems a good solution to rely on since the exposed winit interface should be exactly the interface we actually want.

So for now, it is up to the user to be careful in which interface are used if all iced platform are to be supported.
A feature could be used to choose between restricted (wrapped only) and direct (no cross iced platform compatibility guarantees).

Besides EventLoop and Window, iced_winit currently also exposes winit::dpi.
This is currently not needed directly in the iced inteface but allows the user to avoid explicitly directly use winit::dpi, which makes it possible for another iced platform to be source compatible with the user code.

Intended usage :
winit::EventLoop needs to be created on the main thread on some platforms while we might want to Application::run in another thread.
Instead of using Application::new, compatible EventLoop and Window can be provided directly by the user to Application::run.
For example, create a window (Window::new), maybe get display information (current_monitor().size, hidpi_factor) and configure (set_inner_size).

let event_loop = iced::EventLoop::new();
let window = iced::Window::new(&event_loop).unwrap();
let size = window.current_monitor().size();
       window.set_inner_size(iced::dpi::LogicalSize::from_physical(iced::dpi::PhysicalSize{width: size.width/2., height: size.height/2.}, window.hidpi_factor()));
use iced::Application;
UserApplication::new().run(event_loop, window);

https://github.com/Matthias-Fauconneau/notify-server/blob/master/src/main.rs

P.S: I recently started using Rust, so if this all makes no sense at all, please help me out :D

… iced: Make user directly implement Application trait to remove wrapper boilerplate (Downside: Needs user to explicitly mixin associated type Renderer = platform::Renderer).
@hecrj
Copy link
Copy Markdown
Member

hecrj commented Nov 10, 2019

Thanks for the use case report!

I think we should tackle the use case directly here, instead of exposing internals.

The idea I had in mind was to expose a Settings struct in iced, allowing you to pass the initial window dimensions and additional configuration (like renderer-specific parameters) to Application::run. The window dimensions, in particular, would be ignored by iced_web for the most part.

Is there any reason why this may not work for your use case?

@hecrj
Copy link
Copy Markdown
Member

hecrj commented Nov 11, 2019

Oh, I see. You are trying to take control of the event loop.

I don't think this is something that we should allow. There are many guarantees that can only be held when the application is in charge (smooth resizing, state changes, relayouting, etc.).

Do you need to listen to background events and change your app state based on that? This is what event subscriptions (see #29) are meant to be used for! They are still not implemented, but I will get to it soon!

@Matthias-Fauconneau
Copy link
Copy Markdown
Contributor Author

Matthias-Fauconneau commented Nov 11, 2019 via email

@hecrj
Copy link
Copy Markdown
Member

hecrj commented Nov 11, 2019

Thank you for exploring this!

This is exactly what winit::WindowBuilder does, so might as well use their interface.

Exposing internal libraries directly is not recommended unless your library is meant to extend them. iced_winit exposing winit may make sense, but the fact that we are using iced_winit to power iced should be hidden from our users.

For instance, in the future we may want to offer our users the possibility of using SDL instead of winit. That change should not affect end-user code, the same way using iced_web over iced_winit does not affect it either.

If you don't need it, you can just forward the Platform(EventLoop,WindowBuilder) and not be exposed to any internals.

The API is still leaking the internals. When there is a breaking change, we cannot assume users have been using the library in a particular way.

In my app both UI and the (DBus) notification server are good candidates to
take control of the event loop. It happens to be that with (experimental) rust-notify notificationserver.start I need to return to keep processing messages, but also it makes sense for app (IPC) processing to be the main loop over UI.

As I said earlier, the only way to keep iced_winit guarantees is for iced to take control of the event loop.

A notification server or a heavy processing task can be run, while keeping guarantees, by using event subscriptions (#29) and async actions (#28), respectively.


Overall, I don't think this is a direction we should be headed in. There are many breaking changes here that don't line up with my current vision.

As an alternative proposal, I think you would have a much better time if you used iced_winit directly instead of iced, leveraging the conversion module to build your own custom event loop.

Then, we could review your use cases and needs, identify shortcomings, and design based on that. Let me know how that sounds!

pub window_background : Color /*= Color::WHITE*/,
pub text_color : Color /*= Color::BLACK*/,
pub text_size: f32 /*= 20.0*/,
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is similar to what I had in mind to configure renderers. The plan, however, is to make each renderer define its own configuration!

@Matthias-Fauconneau
Copy link
Copy Markdown
Contributor Author

Matthias-Fauconneau commented Nov 12, 2019 via email

@Matthias-Fauconneau
Copy link
Copy Markdown
Contributor Author

Matthias-Fauconneau commented Nov 12, 2019 via email

…reserve run impl versioning link to pre-split application.rs for easier merging with older non-splitted versions
…y user (optionally through iced wrapper), used by platform.rs
…e without commiting a revert before every merge?)
@hecrj
Copy link
Copy Markdown
Member

hecrj commented Nov 14, 2019

For example, in my case, the server guarantees are more important and also the UI lifetime is shorter, it is only active when there are notifications to be shown (if a display is active at all).

Could you describe your use case from a high-level POV? Why does the server need to control the GUI loop? As I understand, you want to run a server that opens a GUI application for a short amount of time (?).

Well, in the end it seems that's what I'm doing.

Not exactly. You should be able to satisfy your use case without changing any code on this repository and/or maintaining a fork. iced_winit offers a conversion module that can serve you to build your own event loop by using winit directly.

Of course, though I would like to keep the discussion alive to minimize fork maintenance. I don't know what channel is best for this.

It would be great if you could open a new topic in our Zulip server describing your use case! If you want to talk to me personally, you can also message me on Discord (lone_scientist#9554).

@Matthias-Fauconneau
Copy link
Copy Markdown
Contributor Author

Matthias-Fauconneau commented Nov 14, 2019 via email

@hecrj
Copy link
Copy Markdown
Member

hecrj commented Mar 6, 2020

I think the new integration example can be adapted to satisfy this use case somewhat easily.

Therefore, I am closing this. Please, let me know if you have any questions or hit any issues.

@hecrj hecrj closed this Mar 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants