summaryrefslogtreecommitdiffstats
path: root/winit
diff options
context:
space:
mode:
Diffstat (limited to 'winit')
-rw-r--r--winit/Cargo.toml18
-rw-r--r--winit/README.md2
-rw-r--r--winit/src/application.rs398
-rw-r--r--winit/src/clipboard.rs19
-rw-r--r--winit/src/conversion.rs134
-rw-r--r--winit/src/debug/basic.rs5
-rw-r--r--winit/src/debug/null.rs2
-rw-r--r--winit/src/lib.rs24
-rw-r--r--winit/src/mode.rs9
-rw-r--r--winit/src/proxy.rs58
-rw-r--r--winit/src/settings.rs29
-rw-r--r--winit/src/settings/mod.rs53
-rw-r--r--winit/src/settings/not_windows.rs6
-rw-r--r--winit/src/settings/windows.rs9
-rw-r--r--winit/src/size.rs30
15 files changed, 559 insertions, 237 deletions
diff --git a/winit/Cargo.toml b/winit/Cargo.toml
index 2a33255d..63df1d63 100644
--- a/winit/Cargo.toml
+++ b/winit/Cargo.toml
@@ -6,12 +6,24 @@ edition = "2018"
description = "A winit runtime for Iced"
license = "MIT"
repository = "https://github.com/hecrj/iced"
+documentation = "https://docs.rs/iced_winit"
+keywords = ["gui", "ui", "graphics", "interface", "widgets"]
+categories = ["gui"]
[features]
debug = []
[dependencies]
-iced_native = { version = "0.1.0-alpha", path = "../native" }
-winit = { version = "0.20.0-alpha3", git = "https://github.com/rust-windowing/winit", rev = "709808eb4e69044705fcb214bcc30556db761405"}
-futures = { version = "0.3", features = ["thread-pool"] }
+winit = "0.21"
log = "0.4"
+
+[dependencies.iced_native]
+version = "0.1.0-alpha"
+path = "../native"
+
+[dependencies.window_clipboard]
+git = "https://github.com/hecrj/window_clipboard"
+rev = "22c6dd6c04cd05d528029b50a30c56417cd4bebf"
+
+[target.'cfg(target_os = "windows")'.dependencies.winapi]
+version = "0.3.6"
diff --git a/winit/README.md b/winit/README.md
index 01785150..d3309e49 100644
--- a/winit/README.md
+++ b/winit/README.md
@@ -10,7 +10,7 @@ It exposes a renderer-agnostic `Application` trait that can be implemented and t
![iced_winit](../docs/graphs/winit.png)
-[documentation]: https://docs.rs/iced_winit
+[documentation]: https://docs.rs/iced_winit/0.1.0-alpha.1/iced_winit/
[`iced_native`]: ../native
[`winit`]: https://github.com/rust-windowing/winit
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 1042b412..f5aa799c 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -1,9 +1,7 @@
use crate::{
- conversion,
- input::{keyboard, mouse},
- renderer::{Target, Windowed},
- Cache, Command, Container, Debug, Element, Event, Length, MouseCursor,
- Settings, UserInterface,
+ conversion, size::Size, window, Cache, Clipboard, Command, Debug, Element,
+ Executor, Mode, MouseCursor, Proxy, Runtime, Settings, Subscription,
+ UserInterface,
};
/// An interactive, native cross-platform application.
@@ -15,10 +13,15 @@ use crate::{
/// An [`Application`](trait.Application.html) can execute asynchronous actions
/// by returning a [`Command`](struct.Command.html) in some of its methods.
pub trait Application: Sized {
- /// The renderer to use to draw the [`Application`].
+ /// The graphics backend to use to draw the [`Application`].
///
/// [`Application`]: trait.Application.html
- type Renderer: Windowed;
+ type Backend: window::Backend;
+
+ /// The [`Executor`] that will run commands and subscriptions.
+ ///
+ /// [`Executor`]: trait.Executor.html
+ type Executor: Executor;
/// The type of __messages__ your [`Application`] will produce.
///
@@ -57,12 +60,35 @@ pub trait Application: Sized {
/// [`Command`]: struct.Command.html
fn update(&mut self, message: Self::Message) -> Command<Self::Message>;
+ /// Returns the event `Subscription` for the current state of the
+ /// application.
+ ///
+ /// The messages produced by the `Subscription` will be handled by
+ /// [`update`](#tymethod.update).
+ ///
+ /// A `Subscription` will be kept alive as long as you keep returning it!
+ fn subscription(&self) -> Subscription<Self::Message>;
+
/// Returns the widgets to display in the [`Application`].
///
/// These widgets can produce __messages__ based on user interaction.
///
/// [`Application`]: trait.Application.html
- fn view(&mut self) -> Element<'_, Self::Message, Self::Renderer>;
+ fn view(
+ &mut self,
+ ) -> Element<'_, Self::Message, <Self::Backend as window::Backend>::Renderer>;
+
+ /// Returns the current [`Application`] mode.
+ ///
+ /// The runtime will automatically transition your application if a new mode
+ /// is returned.
+ ///
+ /// By default, an application will run in windowed mode.
+ ///
+ /// [`Application`]: trait.Application.html
+ fn mode(&self) -> Mode {
+ Mode::Windowed
+ }
/// Runs the [`Application`].
///
@@ -72,10 +98,13 @@ pub trait Application: Sized {
/// It should probably be that last thing you call in your `main` function.
///
/// [`Application`]: trait.Application.html
- fn run(settings: Settings)
- where
+ fn run(
+ settings: Settings,
+ backend_settings: <Self::Backend as window::Backend>::Settings,
+ ) where
Self: 'static,
{
+ use window::Backend as _;
use winit::{
event::{self, WindowEvent},
event_loop::{ControlFlow, EventLoop},
@@ -86,49 +115,75 @@ pub trait Application: Sized {
debug.startup_started();
let event_loop = EventLoop::with_user_event();
- let proxy = event_loop.create_proxy();
- let mut thread_pool =
- futures::executor::ThreadPool::new().expect("Create thread pool");
let mut external_messages = Vec::new();
- let (mut application, init_command) = Self::new();
- spawn(init_command, &mut thread_pool, &proxy);
+ let mut runtime = {
+ let executor = Self::Executor::new().expect("Create executor");
+
+ Runtime::new(executor, Proxy::new(event_loop.create_proxy()))
+ };
+
+ let (mut application, init_command) = runtime.enter(|| Self::new());
+ runtime.spawn(init_command);
+
+ let subscription = application.subscription();
+ runtime.track(subscription);
let mut title = application.title();
+ let mut mode = application.mode();
+
+ let window = {
+ let mut window_builder = WindowBuilder::new();
- let (width, height) = settings.window.size;
+ let (width, height) = settings.window.size;
- let window = WindowBuilder::new()
- .with_title(&title)
- .with_inner_size(winit::dpi::LogicalSize {
- width: f64::from(width),
- height: f64::from(height),
- })
- .with_resizable(settings.window.resizable)
- .build(&event_loop)
- .expect("Open window");
+ window_builder = window_builder
+ .with_title(&title)
+ .with_inner_size(winit::dpi::LogicalSize { width, height })
+ .with_resizable(settings.window.resizable)
+ .with_decorations(settings.window.decorations)
+ .with_fullscreen(conversion::fullscreen(
+ event_loop.primary_monitor(),
+ mode,
+ ));
- let dpi = window.hidpi_factor();
- let mut size = window.inner_size();
- let mut new_size: Option<winit::dpi::LogicalSize> = None;
+ #[cfg(target_os = "windows")]
+ {
+ use winit::platform::windows::WindowBuilderExtWindows;
- let mut renderer = Self::Renderer::new();
+ if let Some(parent) = settings.window.platform_specific.parent {
+ window_builder = window_builder.with_parent_window(parent);
+ }
+ }
+
+ window_builder.build(&event_loop).expect("Open window")
+ };
- let mut target = {
- let (width, height) = to_physical(size, dpi);
+ let mut size = Size::new(window.inner_size(), window.scale_factor());
+ let mut resized = false;
- <Self::Renderer as Windowed>::Target::new(
- &window, width, height, dpi as f32, &renderer,
+ let clipboard = Clipboard::new(&window);
+ let (mut backend, mut renderer) = Self::Backend::new(backend_settings);
+
+ let surface = backend.create_surface(&window);
+
+ let mut swap_chain = {
+ let physical_size = size.physical();
+
+ backend.create_swap_chain(
+ &surface,
+ physical_size.width,
+ physical_size.height,
)
};
- debug.layout_started();
- let user_interface = UserInterface::build(
- document(&mut application, size, &mut debug),
+ let user_interface = build_user_interface(
+ &mut application,
Cache::default(),
&mut renderer,
+ size.logical(),
+ &mut debug,
);
- debug.layout_finished();
debug.draw_started();
let mut primitive = user_interface.draw(&mut renderer);
@@ -137,28 +192,43 @@ pub trait Application: Sized {
let mut cache = Some(user_interface.into_cache());
let mut events = Vec::new();
let mut mouse_cursor = MouseCursor::OutOfBounds;
+ let mut modifiers = winit::event::ModifiersState::default();
debug.startup_finished();
window.request_redraw();
event_loop.run(move |event, _, control_flow| match event {
event::Event::MainEventsCleared => {
+ if events.is_empty() && external_messages.is_empty() {
+ return;
+ }
+
// TODO: We should be able to keep a user interface alive
// between events once we remove state references.
//
// This will allow us to rebuild it only when a message is
// handled.
- debug.layout_started();
- let mut user_interface = UserInterface::build(
- document(&mut application, size, &mut debug),
+ let mut user_interface = build_user_interface(
+ &mut application,
cache.take().unwrap(),
&mut renderer,
+ size.logical(),
+ &mut debug,
);
- debug.layout_finished();
debug.event_processing_started();
- let mut messages =
- user_interface.update(&renderer, events.drain(..));
+ events
+ .iter()
+ .cloned()
+ .for_each(|event| runtime.broadcast(event));
+
+ let mut messages = user_interface.update(
+ events.drain(..),
+ clipboard
+ .as_ref()
+ .map(|c| c as &dyn iced_native::Clipboard),
+ &renderer,
+ );
messages.extend(external_messages.drain(..));
debug.event_processing_finished();
@@ -179,12 +249,15 @@ pub trait Application: Sized {
debug.log_message(&message);
debug.update_started();
- let command = application.update(message);
-
- spawn(command, &mut thread_pool, &proxy);
+ let command =
+ runtime.enter(|| application.update(message));
+ runtime.spawn(command);
debug.update_finished();
}
+ let subscription = application.subscription();
+ runtime.track(subscription);
+
// Update window title
let new_title = application.title();
@@ -194,13 +267,25 @@ pub trait Application: Sized {
title = new_title;
}
- debug.layout_started();
- let user_interface = UserInterface::build(
- document(&mut application, size, &mut debug),
+ // Update window mode
+ let new_mode = application.mode();
+
+ if mode != new_mode {
+ window.set_fullscreen(conversion::fullscreen(
+ window.current_monitor(),
+ new_mode,
+ ));
+
+ mode = new_mode;
+ }
+
+ let user_interface = build_user_interface(
+ &mut application,
temp_cache,
&mut renderer,
+ size.logical(),
+ &mut debug,
);
- debug.layout_finished();
debug.draw_started();
primitive = user_interface.draw(&mut renderer);
@@ -217,22 +302,25 @@ pub trait Application: Sized {
event::Event::RedrawRequested(_) => {
debug.render_started();
- if let Some(new_size) = new_size.take() {
- let dpi = window.hidpi_factor();
- let (width, height) = to_physical(new_size, dpi);
+ if resized {
+ let physical_size = size.physical();
- target.resize(
- width,
- height,
- window.hidpi_factor() as f32,
- &renderer,
+ swap_chain = backend.create_swap_chain(
+ &surface,
+ physical_size.width,
+ physical_size.height,
);
- size = new_size;
+ resized = false;
}
- let new_mouse_cursor =
- renderer.draw(&primitive, &debug.overlay(), &mut target);
+ let new_mouse_cursor = backend.draw(
+ &mut renderer,
+ &mut swap_chain,
+ &primitive,
+ size.scale_factor(),
+ &debug.overlay(),
+ );
debug.render_finished();
@@ -250,83 +338,56 @@ pub trait Application: Sized {
event::Event::WindowEvent {
event: window_event,
..
- } => match window_event {
- WindowEvent::CursorMoved { position, .. } => {
- events.push(Event::Mouse(mouse::Event::CursorMoved {
- x: position.x as f32,
- y: position.y as f32,
- }));
- }
- WindowEvent::MouseInput { button, state, .. } => {
- events.push(Event::Mouse(mouse::Event::Input {
- button: conversion::mouse_button(button),
- state: conversion::button_state(state),
- }));
- }
- WindowEvent::MouseWheel { delta, .. } => match delta {
- winit::event::MouseScrollDelta::LineDelta(
- delta_x,
- delta_y,
- ) => {
- events.push(Event::Mouse(
- mouse::Event::WheelScrolled {
- delta: mouse::ScrollDelta::Lines {
- x: delta_x,
- y: delta_y,
- },
- },
- ));
+ } => {
+ match window_event {
+ WindowEvent::Resized(new_size) => {
+ size = Size::new(new_size, window.scale_factor());
+ resized = true;
}
- winit::event::MouseScrollDelta::PixelDelta(position) => {
- events.push(Event::Mouse(
- mouse::Event::WheelScrolled {
- delta: mouse::ScrollDelta::Pixels {
- x: position.x as f32,
- y: position.y as f32,
- },
- },
- ));
+ WindowEvent::CloseRequested => {
+ *control_flow = ControlFlow::Exit;
}
- },
- WindowEvent::ReceivedCharacter(c)
- if !is_private_use_character(c) =>
- {
- events.push(Event::Keyboard(
- keyboard::Event::CharacterReceived(c),
- ));
- }
- WindowEvent::KeyboardInput {
- input:
- winit::event::KeyboardInput {
- virtual_keycode: Some(virtual_keycode),
- state,
- ..
- },
- ..
- } => {
- match (virtual_keycode, state) {
- (
- winit::event::VirtualKeyCode::F12,
- winit::event::ElementState::Pressed,
- ) => debug.toggle(),
- _ => {}
+ #[cfg(target_os = "macos")]
+ WindowEvent::KeyboardInput {
+ input:
+ winit::event::KeyboardInput {
+ virtual_keycode:
+ Some(winit::event::VirtualKeyCode::Q),
+ state: winit::event::ElementState::Pressed,
+ ..
+ },
+ ..
+ } if modifiers.logo() => {
+ *control_flow = ControlFlow::Exit;
}
-
- events.push(Event::Keyboard(keyboard::Event::Input {
- key_code: conversion::key_code(virtual_keycode),
- state: conversion::button_state(state),
- }));
- }
- WindowEvent::CloseRequested => {
- *control_flow = ControlFlow::Exit;
+ #[cfg(feature = "debug")]
+ WindowEvent::KeyboardInput {
+ input:
+ winit::event::KeyboardInput {
+ virtual_keycode:
+ Some(winit::event::VirtualKeyCode::F12),
+ state: winit::event::ElementState::Pressed,
+ ..
+ },
+ ..
+ } => debug.toggle(),
+ _ => {}
}
- WindowEvent::Resized(size) => {
- new_size = Some(size.into());
- log::debug!("Resized: {:?}", new_size);
+ if let Some(event) = conversion::window_event(
+ window_event,
+ size.scale_factor(),
+ modifiers,
+ ) {
+ events.push(event);
}
- _ => {}
- },
+ }
+ event::Event::DeviceEvent {
+ event: event::DeviceEvent::ModifiersChanged(new_modifiers),
+ ..
+ } => {
+ modifiers = new_modifiers;
+ }
_ => {
*control_flow = ControlFlow::Wait;
}
@@ -334,63 +395,28 @@ pub trait Application: Sized {
}
}
-fn to_physical(size: winit::dpi::LogicalSize, dpi: f64) -> (u16, u16) {
- let physical_size = size.to_physical(dpi);
-
- (
- physical_size.width.round() as u16,
- physical_size.height.round() as u16,
- )
-}
-
-fn document<'a, Application>(
- application: &'a mut Application,
- size: winit::dpi::LogicalSize,
+fn build_user_interface<'a, A: Application>(
+ application: &'a mut A,
+ cache: Cache,
+ renderer: &mut <A::Backend as window::Backend>::Renderer,
+ size: winit::dpi::LogicalSize<f64>,
debug: &mut Debug,
-) -> Element<'a, Application::Message, Application::Renderer>
-where
- Application: self::Application,
- Application::Message: 'static,
-{
+) -> UserInterface<'a, A::Message, <A::Backend as window::Backend>::Renderer> {
debug.view_started();
let view = application.view();
debug.view_finished();
- Container::new(view)
- .width(Length::Units(size.width.round() as u16))
- .height(Length::Units(size.height.round() as u16))
- .into()
-}
-
-fn spawn<Message: Send>(
- command: Command<Message>,
- thread_pool: &mut futures::executor::ThreadPool,
- proxy: &winit::event_loop::EventLoopProxy<Message>,
-) {
- use futures::FutureExt;
-
- let futures = command.futures();
-
- for future in futures {
- let proxy = proxy.clone();
-
- let future = future.map(move |message| {
- proxy
- .send_event(message)
- .expect("Send command result to event loop");
- });
-
- thread_pool.spawn_ok(future);
- }
-}
-
-// As defined in: http://www.unicode.org/faq/private_use.html
-// TODO: Remove once https://github.com/rust-windowing/winit/pull/1254 lands
-fn is_private_use_character(c: char) -> bool {
- match c {
- '\u{E000}'..='\u{F8FF}'
- | '\u{F0000}'..='\u{FFFFD}'
- | '\u{100000}'..='\u{10FFFD}' => true,
- _ => false,
- }
+ debug.layout_started();
+ let user_interface = UserInterface::build(
+ view,
+ iced_native::Size::new(
+ size.width.round() as f32,
+ size.height.round() as f32,
+ ),
+ cache,
+ renderer,
+ );
+ debug.layout_finished();
+
+ user_interface
}
diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs
new file mode 100644
index 00000000..1ff029ab
--- /dev/null
+++ b/winit/src/clipboard.rs
@@ -0,0 +1,19 @@
+/// A buffer for short-term storage and transfer within and between
+/// applications.
+#[allow(missing_debug_implementations)]
+pub struct Clipboard(window_clipboard::Clipboard);
+
+impl Clipboard {
+ /// Creates a new [`Clipboard`] for the given window.
+ ///
+ /// [`Clipboard`]: struct.Clipboard.html
+ pub fn new(window: &winit::window::Window) -> Option<Clipboard> {
+ window_clipboard::Clipboard::new(window).map(Clipboard).ok()
+ }
+}
+
+impl iced_native::Clipboard for Clipboard {
+ fn content(&self) -> Option<String> {
+ self.0.read().ok()
+ }
+}
diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs
index 03d583fb..b6a0b64b 100644
--- a/winit/src/conversion.rs
+++ b/winit/src/conversion.rs
@@ -3,11 +3,107 @@
//! [`winit`]: https://github.com/rust-windowing/winit
//! [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
use crate::{
- input::{keyboard::KeyCode, mouse, ButtonState},
- MouseCursor,
+ input::{
+ keyboard::{self, KeyCode, ModifiersState},
+ mouse, ButtonState,
+ },
+ window, Event, Mode, MouseCursor,
};
-/// Convert a `MouseCursor` from [`iced_native`] to a [`winit`] cursor icon.
+/// Converts a winit window event into an iced event.
+pub fn window_event(
+ event: winit::event::WindowEvent<'_>,
+ scale_factor: f64,
+ modifiers: winit::event::ModifiersState,
+) -> Option<Event> {
+ use winit::event::WindowEvent;
+
+ match event {
+ WindowEvent::Resized(new_size) => {
+ let logical_size = new_size.to_logical(scale_factor);
+
+ Some(Event::Window(window::Event::Resized {
+ width: logical_size.width,
+ height: logical_size.height,
+ }))
+ }
+ WindowEvent::CursorMoved { position, .. } => {
+ let position = position.to_logical::<f64>(scale_factor);
+
+ Some(Event::Mouse(mouse::Event::CursorMoved {
+ x: position.x as f32,
+ y: position.y as f32,
+ }))
+ }
+ WindowEvent::MouseInput { button, state, .. } => {
+ Some(Event::Mouse(mouse::Event::Input {
+ button: mouse_button(button),
+ state: button_state(state),
+ }))
+ }
+ WindowEvent::MouseWheel { delta, .. } => match delta {
+ winit::event::MouseScrollDelta::LineDelta(delta_x, delta_y) => {
+ Some(Event::Mouse(mouse::Event::WheelScrolled {
+ delta: mouse::ScrollDelta::Lines {
+ x: delta_x,
+ y: delta_y,
+ },
+ }))
+ }
+ winit::event::MouseScrollDelta::PixelDelta(position) => {
+ Some(Event::Mouse(mouse::Event::WheelScrolled {
+ delta: mouse::ScrollDelta::Pixels {
+ x: position.x as f32,
+ y: position.y as f32,
+ },
+ }))
+ }
+ },
+ WindowEvent::ReceivedCharacter(c) if !is_private_use_character(c) => {
+ Some(Event::Keyboard(keyboard::Event::CharacterReceived(c)))
+ }
+ WindowEvent::KeyboardInput {
+ input:
+ winit::event::KeyboardInput {
+ virtual_keycode: Some(virtual_keycode),
+ state,
+ ..
+ },
+ ..
+ } => Some(Event::Keyboard(keyboard::Event::Input {
+ key_code: key_code(virtual_keycode),
+ state: button_state(state),
+ modifiers: modifiers_state(modifiers),
+ })),
+ WindowEvent::HoveredFile(path) => {
+ Some(Event::Window(window::Event::FileHovered(path)))
+ }
+ WindowEvent::DroppedFile(path) => {
+ Some(Event::Window(window::Event::FileDropped(path)))
+ }
+ WindowEvent::HoveredFileCancelled => {
+ Some(Event::Window(window::Event::FilesHoveredLeft))
+ }
+ _ => None,
+ }
+}
+
+/// Converts a [`Mode`] to a [`winit`] fullscreen mode.
+///
+/// [`Mode`]:
+pub fn fullscreen(
+ monitor: winit::monitor::MonitorHandle,
+ mode: Mode,
+) -> Option<winit::window::Fullscreen> {
+ match mode {
+ Mode::Windowed => None,
+ Mode::Fullscreen => {
+ Some(winit::window::Fullscreen::Borderless(monitor))
+ }
+ }
+}
+
+/// Converts a `MouseCursor` from [`iced_native`] to a [`winit`] cursor icon.
///
/// [`winit`]: https://github.com/rust-windowing/winit
/// [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
@@ -23,7 +119,7 @@ pub fn mouse_cursor(mouse_cursor: MouseCursor) -> winit::window::CursorIcon {
}
}
-/// Convert a `MouseButton` from [`winit`] to an [`iced_native`] mouse button.
+/// Converts a `MouseButton` from [`winit`] to an [`iced_native`] mouse button.
///
/// [`winit`]: https://github.com/rust-windowing/winit
/// [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
@@ -36,7 +132,7 @@ pub fn mouse_button(mouse_button: winit::event::MouseButton) -> mouse::Button {
}
}
-/// Convert an `ElementState` from [`winit`] to an [`iced_native`] button state.
+/// Converts an `ElementState` from [`winit`] to an [`iced_native`] button state.
///
/// [`winit`]: https://github.com/rust-windowing/winit
/// [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
@@ -47,7 +143,23 @@ pub fn button_state(element_state: winit::event::ElementState) -> ButtonState {
}
}
-/// Convert a `VirtualKeyCode` from [`winit`] to an [`iced_native`] key code.
+/// Converts some `ModifiersState` from [`winit`] to an [`iced_native`]
+/// modifiers state.
+///
+/// [`winit`]: https://github.com/rust-windowing/winit
+/// [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
+pub fn modifiers_state(
+ modifiers: winit::event::ModifiersState,
+) -> ModifiersState {
+ ModifiersState {
+ shift: modifiers.shift(),
+ control: modifiers.ctrl(),
+ alt: modifiers.alt(),
+ logo: modifiers.logo(),
+ }
+}
+
+/// Converts a `VirtualKeyCode` from [`winit`] to an [`iced_native`] key code.
///
/// [`winit`]: https://github.com/rust-windowing/winit
/// [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
@@ -220,3 +332,13 @@ pub fn key_code(virtual_keycode: winit::event::VirtualKeyCode) -> KeyCode {
winit::event::VirtualKeyCode::Cut => KeyCode::Cut,
}
}
+
+// As defined in: http://www.unicode.org/faq/private_use.html
+pub(crate) fn is_private_use_character(c: char) -> bool {
+ match c {
+ '\u{E000}'..='\u{F8FF}'
+ | '\u{F0000}'..='\u{FFFFD}'
+ | '\u{100000}'..='\u{10FFFD}' => true,
+ _ => false,
+ }
+}
diff --git a/winit/src/debug/basic.rs b/winit/src/debug/basic.rs
index 67c6d8a2..d46edba6 100644
--- a/winit/src/debug/basic.rs
+++ b/winit/src/debug/basic.rs
@@ -1,5 +1,4 @@
-use std::collections::VecDeque;
-use std::time;
+use std::{collections::VecDeque, time};
#[derive(Debug)]
pub struct Debug {
@@ -146,7 +145,7 @@ impl Debug {
let mut lines = Vec::new();
fn key_value<T: std::fmt::Debug>(key: &str, value: T) -> String {
- format!("{: <30} {:?}", key, value)
+ format!("{} {:?}", key, value)
}
lines.push(format!(
diff --git a/winit/src/debug/null.rs b/winit/src/debug/null.rs
index 9c809dd4..2a9430cd 100644
--- a/winit/src/debug/null.rs
+++ b/winit/src/debug/null.rs
@@ -6,8 +6,6 @@ impl Debug {
Self
}
- pub fn toggle(&mut self) {}
-
pub fn startup_started(&mut self) {}
pub fn startup_finished(&mut self) {}
diff --git a/winit/src/lib.rs b/winit/src/lib.rs
index 00d200f9..f99e1290 100644
--- a/winit/src/lib.rs
+++ b/winit/src/lib.rs
@@ -18,8 +18,8 @@
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
-#![deny(unsafe_code)]
-#![deny(rust_2018_idioms)]
+#![forbid(unsafe_code)]
+#![forbid(rust_2018_idioms)]
#[doc(no_inline)]
pub use iced_native::*;
@@ -29,14 +29,24 @@ pub mod conversion;
pub mod settings;
mod application;
-
-pub use application::Application;
-pub use settings::Settings;
+mod clipboard;
+mod mode;
+mod proxy;
+mod size;
// We disable debug capabilities on release builds unless the `debug` feature
// is explicitly enabled.
-#[cfg_attr(feature = "debug", path = "debug/basic.rs")]
-#[cfg_attr(not(feature = "debug"), path = "debug/null.rs")]
+#[cfg(feature = "debug")]
+#[path = "debug/basic.rs"]
+mod debug;
+#[cfg(not(feature = "debug"))]
+#[path = "debug/null.rs"]
mod debug;
+pub use application::Application;
+pub use clipboard::Clipboard;
+pub use mode::Mode;
+pub use settings::Settings;
+
use debug::Debug;
+use proxy::Proxy;
diff --git a/winit/src/mode.rs b/winit/src/mode.rs
new file mode 100644
index 00000000..37464711
--- /dev/null
+++ b/winit/src/mode.rs
@@ -0,0 +1,9 @@
+/// The mode of a window-based application.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Mode {
+ /// The application appears in its own window.
+ Windowed,
+
+ /// The application takes the whole screen of its current monitor.
+ Fullscreen,
+}
diff --git a/winit/src/proxy.rs b/winit/src/proxy.rs
new file mode 100644
index 00000000..cff6ca72
--- /dev/null
+++ b/winit/src/proxy.rs
@@ -0,0 +1,58 @@
+use iced_native::futures::{
+ channel::mpsc,
+ task::{Context, Poll},
+ Sink,
+};
+use std::pin::Pin;
+
+pub struct Proxy<Message: 'static> {
+ raw: winit::event_loop::EventLoopProxy<Message>,
+}
+
+impl<Message: 'static> Clone for Proxy<Message> {
+ fn clone(&self) -> Self {
+ Self {
+ raw: self.raw.clone(),
+ }
+ }
+}
+
+impl<Message: 'static> Proxy<Message> {
+ pub fn new(raw: winit::event_loop::EventLoopProxy<Message>) -> Self {
+ Self { raw }
+ }
+}
+
+impl<Message: 'static> Sink<Message> for Proxy<Message> {
+ type Error = mpsc::SendError;
+
+ fn poll_ready(
+ self: Pin<&mut Self>,
+ _cx: &mut Context<'_>,
+ ) -> Poll<Result<(), Self::Error>> {
+ Poll::Ready(Ok(()))
+ }
+
+ fn start_send(
+ self: Pin<&mut Self>,
+ message: Message,
+ ) -> Result<(), Self::Error> {
+ let _ = self.raw.send_event(message);
+
+ Ok(())
+ }
+
+ fn poll_flush(
+ self: Pin<&mut Self>,
+ _cx: &mut Context<'_>,
+ ) -> Poll<Result<(), Self::Error>> {
+ Poll::Ready(Ok(()))
+ }
+
+ fn poll_close(
+ self: Pin<&mut Self>,
+ _cx: &mut Context<'_>,
+ ) -> Poll<Result<(), Self::Error>> {
+ Poll::Ready(Ok(()))
+ }
+}
diff --git a/winit/src/settings.rs b/winit/src/settings.rs
deleted file mode 100644
index d257ecd8..00000000
--- a/winit/src/settings.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-//! Configure your application.
-
-/// The settings of an application.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
-pub struct Settings {
- /// The [`Window`] settings
- ///
- /// [`Window`]: struct.Window.html
- pub window: Window,
-}
-
-/// The window settings of an application.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct Window {
- /// The size of the window.
- pub size: (u32, u32),
-
- /// Whether the window should be resizable or not.
- pub resizable: bool,
-}
-
-impl Default for Window {
- fn default() -> Window {
- Window {
- size: (1024, 768),
- resizable: true,
- }
- }
-}
diff --git a/winit/src/settings/mod.rs b/winit/src/settings/mod.rs
new file mode 100644
index 00000000..b2290b46
--- /dev/null
+++ b/winit/src/settings/mod.rs
@@ -0,0 +1,53 @@
+//! Configure your application.
+#[cfg(target_os = "windows")]
+#[path = "windows.rs"]
+mod platform;
+#[cfg(not(target_os = "windows"))]
+#[path = "not_windows.rs"]
+mod platform;
+
+pub use platform::PlatformSpecific;
+
+/// The settings of an application.
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct Settings {
+ /// The [`Window`] settings
+ ///
+ /// [`Window`]: struct.Window.html
+ pub window: Window,
+}
+
+impl Default for Settings {
+ fn default() -> Settings {
+ Settings {
+ window: Window::default(),
+ }
+ }
+}
+
+/// The window settings of an application.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Window {
+ /// The size of the window.
+ pub size: (u32, u32),
+
+ /// Whether the window should be resizable or not.
+ pub resizable: bool,
+
+ /// Whether the window should have a border, a title bar, etc.
+ pub decorations: bool,
+
+ /// Platform specific settings.
+ pub platform_specific: platform::PlatformSpecific,
+}
+
+impl Default for Window {
+ fn default() -> Window {
+ Window {
+ size: (1024, 768),
+ resizable: true,
+ decorations: true,
+ platform_specific: Default::default(),
+ }
+ }
+}
diff --git a/winit/src/settings/not_windows.rs b/winit/src/settings/not_windows.rs
new file mode 100644
index 00000000..5d703f84
--- /dev/null
+++ b/winit/src/settings/not_windows.rs
@@ -0,0 +1,6 @@
+#![cfg(not(target_os = "windows"))]
+//! Platform specific settings for not Windows.
+
+/// The platform specific window settings of an application.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+pub struct PlatformSpecific {}
diff --git a/winit/src/settings/windows.rs b/winit/src/settings/windows.rs
new file mode 100644
index 00000000..76b8d067
--- /dev/null
+++ b/winit/src/settings/windows.rs
@@ -0,0 +1,9 @@
+#![cfg(target_os = "windows")]
+//! Platform specific settings for Windows.
+
+/// The platform specific window settings of an application.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+pub struct PlatformSpecific {
+ /// Parent Window
+ pub parent: Option<winapi::shared::windef::HWND>,
+}
diff --git a/winit/src/size.rs b/winit/src/size.rs
new file mode 100644
index 00000000..7e3056d4
--- /dev/null
+++ b/winit/src/size.rs
@@ -0,0 +1,30 @@
+pub struct Size {
+ physical: winit::dpi::PhysicalSize<u32>,
+ logical: winit::dpi::LogicalSize<f64>,
+ scale_factor: f64,
+}
+
+impl Size {
+ pub fn new(
+ physical: winit::dpi::PhysicalSize<u32>,
+ scale_factor: f64,
+ ) -> Size {
+ Size {
+ logical: physical.to_logical(scale_factor),
+ physical,
+ scale_factor,
+ }
+ }
+
+ pub fn physical(&self) -> winit::dpi::PhysicalSize<u32> {
+ self.physical
+ }
+
+ pub fn logical(&self) -> winit::dpi::LogicalSize<f64> {
+ self.logical
+ }
+
+ pub fn scale_factor(&self) -> f64 {
+ self.scale_factor
+ }
+}