summaryrefslogtreecommitdiffstats
path: root/glutin
diff options
context:
space:
mode:
Diffstat (limited to 'glutin')
-rw-r--r--glutin/Cargo.toml30
-rw-r--r--glutin/README.md27
-rw-r--r--glutin/src/application.rs209
-rw-r--r--glutin/src/lib.rs23
4 files changed, 289 insertions, 0 deletions
diff --git a/glutin/Cargo.toml b/glutin/Cargo.toml
new file mode 100644
index 00000000..4652112c
--- /dev/null
+++ b/glutin/Cargo.toml
@@ -0,0 +1,30 @@
+[package]
+name = "iced_glutin"
+version = "0.1.0"
+authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
+edition = "2018"
+description = "A glutin runtime for Iced"
+license = "MIT"
+repository = "https://github.com/hecrj/iced"
+documentation = "https://docs.rs/iced_glutin"
+keywords = ["gui", "ui", "graphics", "interface", "widgets"]
+categories = ["gui"]
+
+[features]
+debug = ["iced_winit/debug"]
+
+[dependencies]
+glutin = "0.24"
+
+[dependencies.iced_native]
+version = "0.2"
+path = "../native"
+
+[dependencies.iced_winit]
+version = "0.1"
+path = "../winit"
+
+[dependencies.iced_graphics]
+version = "0.1"
+path = "../graphics"
+features = ["opengl"]
diff --git a/glutin/README.md b/glutin/README.md
new file mode 100644
index 00000000..34dec1b3
--- /dev/null
+++ b/glutin/README.md
@@ -0,0 +1,27 @@
+# `iced_winit`
+[![Documentation](https://docs.rs/iced_winit/badge.svg)][documentation]
+[![Crates.io](https://img.shields.io/crates/v/iced_winit.svg)](https://crates.io/crates/iced_winit)
+[![License](https://img.shields.io/crates/l/iced_winit.svg)](https://github.com/hecrj/iced/blob/master/LICENSE)
+[![project chat](https://img.shields.io/badge/chat-on_zulip-brightgreen.svg)](https://iced.zulipchat.com)
+
+`iced_winit` offers some convenient abstractions on top of [`iced_native`] to quickstart development when using [`winit`].
+
+It exposes a renderer-agnostic `Application` trait that can be implemented and then run with a simple call. The use of this trait is optional. A `conversion` module is provided for users that decide to implement a custom event loop.
+
+![iced_winit](../docs/graphs/winit.png)
+
+[documentation]: https://docs.rs/iced_winit
+[`iced_native`]: ../native
+[`winit`]: https://github.com/rust-windowing/winit
+
+## Installation
+Add `iced_winit` as a dependency in your `Cargo.toml`:
+
+```toml
+iced_winit = "0.1"
+```
+
+__Iced moves fast and the `master` branch can contain breaking changes!__ If
+you want to learn about a specific release, check out [the release list].
+
+[the release list]: https://github.com/hecrj/iced/releases
diff --git a/glutin/src/application.rs b/glutin/src/application.rs
new file mode 100644
index 00000000..c777a13b
--- /dev/null
+++ b/glutin/src/application.rs
@@ -0,0 +1,209 @@
+//! Create interactive, native cross-platform applications.
+use crate::{mouse, Executor, Runtime, Size};
+use iced_graphics::window;
+use iced_graphics::Viewport;
+use iced_winit::application;
+use iced_winit::conversion;
+use iced_winit::{Clipboard, Debug, Proxy, Settings};
+
+pub use iced_winit::Application;
+pub use iced_winit::{program, Program};
+
+/// Runs an [`Application`] with an executor, compositor, and the provided
+/// settings.
+///
+/// [`Application`]: trait.Application.html
+pub fn run<A, E, C>(
+ settings: Settings<A::Flags>,
+ compositor_settings: C::Settings,
+) where
+ A: Application + 'static,
+ E: Executor + 'static,
+ C: window::GLCompositor<Renderer = A::Renderer> + 'static,
+{
+ use glutin::{
+ event,
+ event_loop::{ControlFlow, EventLoop},
+ ContextBuilder,
+ };
+
+ let mut debug = Debug::new();
+ debug.startup_started();
+
+ let event_loop = EventLoop::with_user_event();
+ let mut runtime = {
+ let executor = E::new().expect("Create executor");
+ let proxy = Proxy::new(event_loop.create_proxy());
+
+ Runtime::new(executor, proxy)
+ };
+
+ let flags = settings.flags;
+ let (application, init_command) = runtime.enter(|| A::new(flags));
+ runtime.spawn(init_command);
+
+ let subscription = application.subscription();
+ runtime.track(subscription);
+
+ let mut title = application.title();
+ let mut mode = application.mode();
+
+ let context = {
+ let builder = settings.window.into_builder(
+ &title,
+ mode,
+ event_loop.primary_monitor(),
+ );
+
+ let context = ContextBuilder::new()
+ .with_vsync(true)
+ .with_multisampling(C::sample_count(&compositor_settings) as u16)
+ .build_windowed(builder, &event_loop)
+ .expect("Open window");
+
+ #[allow(unsafe_code)]
+ unsafe {
+ context.make_current().expect("Make OpenGL context current")
+ }
+ };
+
+ let clipboard = Clipboard::new(&context.window());
+ let mut mouse_interaction = mouse::Interaction::default();
+ let mut modifiers = glutin::event::ModifiersState::default();
+
+ let physical_size = context.window().inner_size();
+ let mut viewport = Viewport::with_physical_size(
+ Size::new(physical_size.width, physical_size.height),
+ context.window().scale_factor(),
+ );
+ let mut resized = false;
+
+ #[allow(unsafe_code)]
+ let (mut compositor, mut renderer) = unsafe {
+ C::new(compositor_settings, |address| {
+ context.get_proc_address(address)
+ })
+ };
+
+ let mut state = program::State::new(
+ application,
+ viewport.logical_size(),
+ &mut renderer,
+ &mut debug,
+ );
+ debug.startup_finished();
+
+ event_loop.run(move |event, _, control_flow| match event {
+ event::Event::MainEventsCleared => {
+ let command = runtime.enter(|| {
+ state.update(
+ clipboard.as_ref().map(|c| c as _),
+ viewport.logical_size(),
+ &mut renderer,
+ &mut debug,
+ )
+ });
+
+ // If the application was updated
+ if let Some(command) = command {
+ runtime.spawn(command);
+
+ let program = state.program();
+
+ // Update subscriptions
+ let subscription = program.subscription();
+ runtime.track(subscription);
+
+ // Update window title
+ let new_title = program.title();
+
+ if title != new_title {
+ context.window().set_title(&new_title);
+
+ title = new_title;
+ }
+
+ // Update window mode
+ let new_mode = program.mode();
+
+ if mode != new_mode {
+ context.window().set_fullscreen(conversion::fullscreen(
+ context.window().current_monitor(),
+ new_mode,
+ ));
+
+ mode = new_mode;
+ }
+ }
+
+ context.window().request_redraw();
+ }
+ event::Event::UserEvent(message) => {
+ state.queue_message(message);
+ }
+ event::Event::RedrawRequested(_) => {
+ debug.render_started();
+
+ if resized {
+ let physical_size = viewport.physical_size();
+
+ context.resize(glutin::dpi::PhysicalSize::new(
+ physical_size.width,
+ physical_size.height,
+ ));
+
+ compositor.resize_viewport(physical_size);
+
+ resized = false;
+ }
+
+ let new_mouse_interaction = compositor.draw(
+ &mut renderer,
+ &viewport,
+ state.primitive(),
+ &debug.overlay(),
+ );
+
+ context.swap_buffers().expect("Swap buffers");
+
+ debug.render_finished();
+
+ if new_mouse_interaction != mouse_interaction {
+ context.window().set_cursor_icon(
+ conversion::mouse_interaction(new_mouse_interaction),
+ );
+
+ mouse_interaction = new_mouse_interaction;
+ }
+
+ // TODO: Handle animations!
+ // Maybe we can use `ControlFlow::WaitUntil` for this.
+ }
+ event::Event::WindowEvent {
+ event: window_event,
+ ..
+ } => {
+ application::handle_window_event(
+ &window_event,
+ context.window(),
+ control_flow,
+ &mut modifiers,
+ &mut viewport,
+ &mut resized,
+ &mut debug,
+ );
+
+ if let Some(event) = conversion::window_event(
+ &window_event,
+ viewport.scale_factor(),
+ modifiers,
+ ) {
+ state.queue_event(event.clone());
+ runtime.broadcast(event);
+ }
+ }
+ _ => {
+ *control_flow = ControlFlow::Wait;
+ }
+ })
+}
diff --git a/glutin/src/lib.rs b/glutin/src/lib.rs
new file mode 100644
index 00000000..b0e0bdd4
--- /dev/null
+++ b/glutin/src/lib.rs
@@ -0,0 +1,23 @@
+//! A windowing shell for [`iced`], on top of [`glutin`].
+//!
+//! [`iced`]: https://github.com/hecrj/iced
+//! [`glutin`]: https://github.com/rust-windowing/glutin
+#![deny(missing_docs)]
+#![deny(missing_debug_implementations)]
+#![deny(unused_results)]
+#![deny(unsafe_code)]
+#![forbid(rust_2018_idioms)]
+
+pub use glutin;
+#[doc(no_inline)]
+pub use iced_native::*;
+
+pub mod application;
+
+pub use iced_winit::settings;
+pub use iced_winit::Mode;
+
+#[doc(no_inline)]
+pub use application::Application;
+#[doc(no_inline)]
+pub use settings::Settings;