diff options
Diffstat (limited to 'winit/src')
-rw-r--r-- | winit/src/application.rs | 256 | ||||
-rw-r--r-- | winit/src/application/state.rs | 82 | ||||
-rw-r--r-- | winit/src/conversion.rs | 48 | ||||
-rw-r--r-- | winit/src/error.rs | 12 | ||||
-rw-r--r-- | winit/src/lib.rs | 27 | ||||
-rw-r--r-- | winit/src/mode.rs | 12 | ||||
-rw-r--r-- | winit/src/settings.rs | 18 | ||||
-rw-r--r-- | winit/src/settings/windows.rs | 2 | ||||
-rw-r--r-- | winit/src/system.rs | 41 | ||||
-rw-r--r-- | winit/src/window.rs | 16 |
10 files changed, 355 insertions, 159 deletions
diff --git a/winit/src/application.rs b/winit/src/application.rs index ed077507..0496aea9 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -6,17 +6,22 @@ pub use state::State; use crate::clipboard::{self, Clipboard}; use crate::conversion; use crate::mouse; +use crate::renderer; +use crate::widget::operation; use crate::{ - Color, Command, Debug, Error, Executor, Mode, Proxy, Runtime, Settings, - Size, Subscription, + Command, Debug, Error, Executor, Proxy, Runtime, Settings, Size, + Subscription, }; use iced_futures::futures; use iced_futures::futures::channel::mpsc; +use iced_graphics::compositor; use iced_graphics::window; use iced_native::program::Program; use iced_native::user_interface::{self, UserInterface}; +pub use iced_native::application::{Appearance, StyleSheet}; + use std::mem::ManuallyDrop; /// An interactive, native cross-platform application. @@ -30,7 +35,10 @@ use std::mem::ManuallyDrop; /// /// When using an [`Application`] with the `debug` feature enabled, a debug view /// can be toggled by pressing `F12`. -pub trait Application: Program { +pub trait Application: Program +where + <Self::Renderer as crate::Renderer>::Theme: StyleSheet, +{ /// The data needed to initialize your [`Application`]. type Flags; @@ -50,6 +58,16 @@ pub trait Application: Program { /// title of your application when necessary. fn title(&self) -> String; + /// Returns the current [`Theme`] of the [`Application`]. + fn theme(&self) -> <Self::Renderer as crate::Renderer>::Theme; + + /// Returns the [`Style`] variation of the [`Theme`]. + fn style( + &self, + ) -> <<Self::Renderer as crate::Renderer>::Theme as StyleSheet>::Style { + Default::default() + } + /// Returns the event `Subscription` for the current state of the /// application. /// @@ -63,23 +81,6 @@ pub trait Application: Program { Subscription::none() } - /// 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. - fn mode(&self) -> Mode { - Mode::Windowed - } - - /// Returns the background [`Color`] of the [`Application`]. - /// - /// By default, it returns [`Color::WHITE`]. - fn background_color(&self) -> Color { - Color::WHITE - } - /// Returns the scale factor of the [`Application`]. /// /// It can be used to dynamically control the size of the UI at runtime @@ -111,18 +112,19 @@ where A: Application + 'static, E: Executor + 'static, C: window::Compositor<Renderer = A::Renderer> + 'static, + <A::Renderer as crate::Renderer>::Theme: StyleSheet, { use futures::task; use futures::Future; - use winit::event_loop::EventLoop; + use winit::event_loop::EventLoopBuilder; let mut debug = Debug::new(); debug.startup_started(); - let event_loop = EventLoop::with_user_event(); - let mut proxy = event_loop.create_proxy(); + let event_loop = EventLoopBuilder::with_user_event().build(); + let proxy = event_loop.create_proxy(); - let mut runtime = { + let runtime = { let proxy = Proxy::new(event_loop.create_proxy()); let executor = E::new().map_err(Error::ExecutorCreationFailed)?; @@ -135,16 +137,15 @@ where runtime.enter(|| A::new(flags)) }; - let subscription = application.subscription(); + let builder = settings.window.into_builder( + &application.title(), + event_loop.primary_monitor(), + settings.id, + ); - let window = settings - .window - .into_builder( - &application.title(), - application.mode(), - event_loop.primary_monitor(), - settings.id, - ) + log::info!("Window builder: {:#?}", builder); + + let window = builder .build(&event_loop) .map_err(Error::WindowCreationFailed)?; @@ -163,17 +164,6 @@ where .expect("Append canvas to HTML body"); } - let mut clipboard = Clipboard::connect(&window); - - run_command( - init_command, - &mut runtime, - &mut clipboard, - &mut proxy, - &window, - ); - runtime.track(subscription); - let (compositor, renderer) = C::new(compositor_settings, Some(&window))?; let (mut sender, receiver) = mpsc::unbounded(); @@ -183,10 +173,10 @@ where compositor, renderer, runtime, - clipboard, proxy, debug, receiver, + init_command, window, settings.exit_on_close_request, )); @@ -196,7 +186,7 @@ where platform::run(event_loop, move |event, _, control_flow| { use winit::event_loop::ControlFlow; - if let ControlFlow::Exit = control_flow { + if let ControlFlow::ExitWithCode(_) = control_flow { return; } @@ -233,20 +223,23 @@ async fn run_instance<A, E, C>( mut compositor: C, mut renderer: A::Renderer, mut runtime: Runtime<E, Proxy<A::Message>, A::Message>, - mut clipboard: Clipboard, mut proxy: winit::event_loop::EventLoopProxy<A::Message>, mut debug: Debug, mut receiver: mpsc::UnboundedReceiver<winit::event::Event<'_, A::Message>>, + init_command: Command<A::Message>, window: winit::window::Window, exit_on_close_request: bool, ) where A: Application + 'static, E: Executor + 'static, C: window::Compositor<Renderer = A::Renderer> + 'static, + <A::Renderer as crate::Renderer>::Theme: StyleSheet, { use iced_futures::futures::stream::StreamExt; use winit::event; + let mut clipboard = Clipboard::connect(&window); + let mut cache = user_interface::Cache::default(); let mut surface = compositor.create_surface(&window); let mut state = State::new(&application, &window); @@ -260,9 +253,24 @@ async fn run_instance<A, E, C>( physical_size.height, ); + run_command( + &application, + &mut cache, + &state, + &mut renderer, + init_command, + &mut runtime, + &mut clipboard, + &mut proxy, + &mut debug, + &window, + || compositor.fetch_information(), + ); + runtime.track(application.subscription()); + let mut user_interface = ManuallyDrop::new(build_user_interface( - &mut application, - user_interface::Cache::default(), + &application, + cache, &mut renderer, state.logical_size(), &mut debug, @@ -303,18 +311,22 @@ async fn run_instance<A, E, C>( user_interface::State::Outdated, ) { - let cache = + let mut cache = ManuallyDrop::into_inner(user_interface).into_cache(); // Update application update( &mut application, + &mut cache, + &state, + &mut renderer, &mut runtime, &mut clipboard, &mut proxy, &mut debug, &mut messages, &window, + || compositor.fetch_information(), ); // Update window @@ -323,7 +335,7 @@ async fn run_instance<A, E, C>( let should_exit = application.should_exit(); user_interface = ManuallyDrop::new(build_user_interface( - &mut application, + &application, cache, &mut renderer, state.logical_size(), @@ -336,8 +348,14 @@ async fn run_instance<A, E, C>( } debug.draw_started(); - let new_mouse_interaction = - user_interface.draw(&mut renderer, state.cursor_position()); + let new_mouse_interaction = user_interface.draw( + &mut renderer, + state.theme(), + &renderer::Style { + text_color: state.text_color(), + }, + state.cursor_position(), + ); debug.draw_finished(); if new_mouse_interaction != mouse_interaction { @@ -354,6 +372,7 @@ async fn run_instance<A, E, C>( event::MacOS::ReceivedUrl(url), )) => { use iced_native::event; + events.push(iced_native::Event::PlatformSpecific( event::PlatformSpecific::MacOS(event::MacOS::ReceivedUrl( url, @@ -384,8 +403,14 @@ async fn run_instance<A, E, C>( debug.layout_finished(); debug.draw_started(); - let new_mouse_interaction = user_interface - .draw(&mut renderer, state.cursor_position()); + let new_mouse_interaction = user_interface.draw( + &mut renderer, + state.theme(), + &renderer::Style { + text_color: state.text_color(), + }, + state.cursor_position(), + ); if new_mouse_interaction != mouse_interaction { window.set_cursor_icon(conversion::mouse_interaction( @@ -420,7 +445,7 @@ async fn run_instance<A, E, C>( } Err(error) => match error { // This is an unrecoverable error. - window::SurfaceError::OutOfMemory => { + compositor::SurfaceError::OutOfMemory => { panic!("{:?}", error); } _ => { @@ -487,12 +512,15 @@ pub fn requests_exit( /// Builds a [`UserInterface`] for the provided [`Application`], logging /// [`struct@Debug`] information accordingly. pub fn build_user_interface<'a, A: Application>( - application: &'a mut A, + application: &'a A, cache: user_interface::Cache, renderer: &mut A::Renderer, size: Size, debug: &mut Debug, -) -> UserInterface<'a, A::Message, A::Renderer> { +) -> UserInterface<'a, A::Message, A::Renderer> +where + <A::Renderer as crate::Renderer>::Theme: StyleSheet, +{ debug.view_started(); let view = application.view(); debug.view_finished(); @@ -508,13 +536,19 @@ pub fn build_user_interface<'a, A: Application>( /// resulting [`Command`], and tracking its [`Subscription`]. pub fn update<A: Application, E: Executor>( application: &mut A, + cache: &mut user_interface::Cache, + state: &State<A>, + renderer: &mut A::Renderer, runtime: &mut Runtime<E, Proxy<A::Message>, A::Message>, clipboard: &mut Clipboard, proxy: &mut winit::event_loop::EventLoopProxy<A::Message>, debug: &mut Debug, messages: &mut Vec<A::Message>, window: &winit::window::Window, -) { + graphics_info: impl FnOnce() -> compositor::Information + Copy, +) where + <A::Renderer as crate::Renderer>::Theme: StyleSheet, +{ for message in messages.drain(..) { debug.log_message(&message); @@ -522,7 +556,19 @@ pub fn update<A: Application, E: Executor>( let command = runtime.enter(|| application.update(message)); debug.update_finished(); - run_command(command, runtime, clipboard, proxy, window); + run_command( + application, + cache, + state, + renderer, + command, + runtime, + clipboard, + proxy, + debug, + window, + graphics_info, + ); } let subscription = application.subscription(); @@ -530,14 +576,25 @@ pub fn update<A: Application, E: Executor>( } /// Runs the actions of a [`Command`]. -pub fn run_command<Message: 'static + std::fmt::Debug + Send, E: Executor>( - command: Command<Message>, - runtime: &mut Runtime<E, Proxy<Message>, Message>, +pub fn run_command<A, E>( + application: &A, + cache: &mut user_interface::Cache, + state: &State<A>, + renderer: &mut A::Renderer, + command: Command<A::Message>, + runtime: &mut Runtime<E, Proxy<A::Message>, A::Message>, clipboard: &mut Clipboard, - proxy: &mut winit::event_loop::EventLoopProxy<Message>, + proxy: &mut winit::event_loop::EventLoopProxy<A::Message>, + debug: &mut Debug, window: &winit::window::Window, -) { + _graphics_info: impl FnOnce() -> compositor::Information + Copy, +) where + A: Application, + E: Executor, + <A::Renderer as crate::Renderer>::Theme: StyleSheet, +{ use iced_native::command; + use iced_native::system; use iced_native::window; for action in command.actions() { @@ -570,7 +627,76 @@ pub fn run_command<Message: 'static + std::fmt::Debug + Send, E: Executor>( y, }); } + window::Action::SetMode(mode) => { + window.set_visible(conversion::visible(mode)); + window.set_fullscreen(conversion::fullscreen( + window.primary_monitor(), + mode, + )); + } + window::Action::FetchMode(tag) => { + let mode = if window.is_visible().unwrap_or(true) { + conversion::mode(window.fullscreen()) + } else { + window::Mode::Hidden + }; + + proxy + .send_event(tag(mode)) + .expect("Send message to event loop"); + } + }, + command::Action::System(action) => match action { + system::Action::QueryInformation(_tag) => { + #[cfg(feature = "system")] + { + let graphics_info = _graphics_info(); + let proxy = proxy.clone(); + + let _ = std::thread::spawn(move || { + let information = + crate::system::information(graphics_info); + + let message = _tag(information); + + proxy + .send_event(message) + .expect("Send message to event loop") + }); + } + } }, + command::Action::Widget(action) => { + let mut current_cache = std::mem::take(cache); + let mut current_operation = Some(action.into_operation()); + + let mut user_interface = build_user_interface( + application, + current_cache, + renderer, + state.logical_size(), + debug, + ); + + while let Some(mut operation) = current_operation.take() { + user_interface.operate(renderer, operation.as_mut()); + + match operation.finish() { + operation::Outcome::None => {} + operation::Outcome::Some(message) => { + proxy + .send_event(message) + .expect("Send message to event loop"); + } + operation::Outcome::Chain(next) => { + current_operation = Some(next); + } + } + } + + current_cache = user_interface.into_cache(); + *cache = current_cache; + } } } } diff --git a/winit/src/application/state.rs b/winit/src/application/state.rs index b54d3aed..9c539548 100644 --- a/winit/src/application/state.rs +++ b/winit/src/application/state.rs @@ -1,31 +1,38 @@ +use crate::application::{self, StyleSheet as _}; use crate::conversion; -use crate::{Application, Color, Debug, Mode, Point, Size, Viewport}; +use crate::{Application, Color, Debug, Point, Size, Viewport}; use std::marker::PhantomData; use winit::event::{Touch, WindowEvent}; use winit::window::Window; /// The state of a windowed [`Application`]. -#[derive(Debug, Clone)] -pub struct State<A: Application> { +#[allow(missing_debug_implementations)] +pub struct State<A: Application> +where + <A::Renderer as crate::Renderer>::Theme: application::StyleSheet, +{ title: String, - mode: Mode, - background_color: Color, scale_factor: f64, viewport: Viewport, viewport_version: usize, cursor_position: winit::dpi::PhysicalPosition<f64>, modifiers: winit::event::ModifiersState, + theme: <A::Renderer as crate::Renderer>::Theme, + appearance: application::Appearance, application: PhantomData<A>, } -impl<A: Application> State<A> { +impl<A: Application> State<A> +where + <A::Renderer as crate::Renderer>::Theme: application::StyleSheet, +{ /// Creates a new [`State`] for the provided [`Application`] and window. pub fn new(application: &A, window: &Window) -> Self { let title = application.title(); - let mode = application.mode(); - let background_color = application.background_color(); let scale_factor = application.scale_factor(); + let theme = application.theme(); + let appearance = theme.appearance(application.style()); let viewport = { let physical_size = window.inner_size(); @@ -38,23 +45,18 @@ impl<A: Application> State<A> { Self { title, - mode, - background_color, scale_factor, viewport, viewport_version: 0, // TODO: Encode cursor availability in the type-system cursor_position: winit::dpi::PhysicalPosition::new(-1.0, -1.0), modifiers: winit::event::ModifiersState::default(), + theme, + appearance, application: PhantomData, } } - /// Returns the current background [`Color`] of the [`State`]. - pub fn background_color(&self) -> Color { - self.background_color - } - /// Returns the current [`Viewport`] of the [`State`]. pub fn viewport(&self) -> &Viewport { &self.viewport @@ -95,6 +97,21 @@ impl<A: Application> State<A> { self.modifiers } + /// Returns the current theme of the [`State`]. + pub fn theme(&self) -> &<A::Renderer as crate::Renderer>::Theme { + &self.theme + } + + /// Returns the current background [`Color`] of the [`State`]. + pub fn background_color(&self) -> Color { + self.appearance.background_color + } + + /// Returns the current text [`Color`] of the [`State`]. + pub fn text_color(&self) -> Color { + self.appearance.text_color + } + /// Processes the provided window event and updates the [`State`] /// accordingly. pub fn update( @@ -173,35 +190,26 @@ impl<A: Application> State<A> { self.title = new_title; } - // Update window mode - let new_mode = application.mode(); - - if self.mode != new_mode { - window.set_fullscreen(conversion::fullscreen( - window.current_monitor(), - new_mode, - )); - - window.set_visible(conversion::visible(new_mode)); - - self.mode = new_mode; - } - - // Update background color - self.background_color = application.background_color(); - - // Update scale factor + // Update scale factor and size let new_scale_factor = application.scale_factor(); + let new_size = window.inner_size(); + let current_size = self.viewport.physical_size(); - if self.scale_factor != new_scale_factor { - let size = window.inner_size(); - + if self.scale_factor != new_scale_factor + || (current_size.width, current_size.height) + != (new_size.width, new_size.height) + { self.viewport = Viewport::with_physical_size( - Size::new(size.width, size.height), + Size::new(new_size.width, new_size.height), window.scale_factor() * new_scale_factor, ); + self.viewport_version = self.viewport_version.wrapping_add(1); self.scale_factor = new_scale_factor; } + + // Update theme and appearance + self.theme = application.theme(); + self.appearance = self.theme.appearance(application.style()); } } diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index b00a095d..ba5b0002 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -1,12 +1,12 @@ //! Convert [`winit`] types into [`iced_native`] types, and viceversa. //! //! [`winit`]: https://github.com/rust-windowing/winit -//! [`iced_native`]: https://github.com/hecrj/iced/tree/master/native +//! [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native use crate::keyboard; use crate::mouse; use crate::touch; use crate::window; -use crate::{Event, Mode, Point, Position}; +use crate::{Event, Point, Position}; /// Converts a winit window event into an iced event. pub fn window_event( @@ -182,33 +182,43 @@ pub fn position( } } -/// Converts a [`Mode`] to a [`winit`] fullscreen mode. +/// Converts a [`window::Mode`] to a [`winit`] fullscreen mode. /// /// [`winit`]: https://github.com/rust-windowing/winit pub fn fullscreen( monitor: Option<winit::monitor::MonitorHandle>, - mode: Mode, + mode: window::Mode, ) -> Option<winit::window::Fullscreen> { match mode { - Mode::Windowed | Mode::Hidden => None, - Mode::Fullscreen => { + window::Mode::Windowed | window::Mode::Hidden => None, + window::Mode::Fullscreen => { Some(winit::window::Fullscreen::Borderless(monitor)) } } } -/// Converts a [`Mode`] to a visibility flag. -pub fn visible(mode: Mode) -> bool { +/// Converts a [`window::Mode`] to a visibility flag. +pub fn visible(mode: window::Mode) -> bool { match mode { - Mode::Windowed | Mode::Fullscreen => true, - Mode::Hidden => false, + window::Mode::Windowed | window::Mode::Fullscreen => true, + window::Mode::Hidden => false, + } +} + +/// Converts a [`winit`] fullscreen mode to a [`window::Mode`]. +/// +/// [`winit`]: https://github.com/rust-windowing/winit +pub fn mode(mode: Option<winit::window::Fullscreen>) -> window::Mode { + match mode { + None => window::Mode::Windowed, + Some(_) => window::Mode::Fullscreen, } } /// 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 +/// [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native pub fn mouse_interaction( interaction: mouse::Interaction, ) -> winit::window::CursorIcon { @@ -232,7 +242,7 @@ pub fn mouse_interaction( /// 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 +/// [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native pub fn mouse_button(mouse_button: winit::event::MouseButton) -> mouse::Button { match mouse_button { winit::event::MouseButton::Left => mouse::Button::Left, @@ -248,7 +258,7 @@ pub fn mouse_button(mouse_button: winit::event::MouseButton) -> mouse::Button { /// modifiers state. /// /// [`winit`]: https://github.com/rust-windowing/winit -/// [`iced_native`]: https://github.com/hecrj/iced/tree/master/native +/// [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native pub fn modifiers( modifiers: winit::event::ModifiersState, ) -> keyboard::Modifiers { @@ -275,7 +285,7 @@ pub fn cursor_position( /// Converts a `Touch` from [`winit`] to an [`iced_native`] touch event. /// /// [`winit`]: https://github.com/rust-windowing/winit -/// [`iced_native`]: https://github.com/hecrj/iced/tree/master/native +/// [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native pub fn touch_event( touch: winit::event::Touch, scale_factor: f64, @@ -306,7 +316,7 @@ pub fn touch_event( /// 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 +/// [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native pub fn key_code( virtual_keycode: winit::event::VirtualKeyCode, ) -> keyboard::KeyCode { @@ -485,10 +495,10 @@ pub fn key_code( // As defined in: http://www.unicode.org/faq/private_use.html pub(crate) fn is_private_use_character(c: char) -> bool { - match c { + matches!( + c, '\u{E000}'..='\u{F8FF}' | '\u{F0000}'..='\u{FFFFD}' - | '\u{100000}'..='\u{10FFFD}' => true, - _ => false, - } + | '\u{100000}'..='\u{10FFFD}' + ) } diff --git a/winit/src/error.rs b/winit/src/error.rs index 8e1d20e8..eaeafd51 100644 --- a/winit/src/error.rs +++ b/winit/src/error.rs @@ -11,17 +11,13 @@ pub enum Error { #[error("the application window could not be created")] WindowCreationFailed(winit::error::OsError), - /// A suitable graphics adapter or device could not be found. - #[error("a suitable graphics adapter or device could not be found")] - GraphicsAdapterNotFound, + /// The application graphics context could not be created. + #[error("the application graphics context could not be created")] + GraphicsCreationFailed(iced_graphics::Error), } impl From<iced_graphics::Error> for Error { fn from(error: iced_graphics::Error) -> Error { - match error { - iced_graphics::Error::AdapterNotFound => { - Error::GraphicsAdapterNotFound - } - } + Error::GraphicsCreationFailed(error) } } diff --git a/winit/src/lib.rs b/winit/src/lib.rs index b31adf6e..e32cc9af 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -1,6 +1,6 @@ //! A windowing shell for Iced, on top of [`winit`]. //! -//!  +//!  //! //! `iced_winit` offers some convenient abstractions on top of [`iced_native`] //! to quickstart development when using [`winit`]. @@ -11,17 +11,25 @@ //! Additionally, a [`conversion`] module is available for users that decide to //! implement a custom event loop. //! -//! [`iced_native`]: https://github.com/hecrj/iced/tree/master/native +//! [`iced_native`]: https://github.com/iced-rs/iced/tree/0.4/native //! [`winit`]: https://github.com/rust-windowing/winit //! [`conversion`]: crate::conversion #![doc( html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg" )] -#![deny(missing_docs)] -#![deny(missing_debug_implementations)] -#![deny(unused_results)] -#![forbid(unsafe_code)] -#![forbid(rust_2018_idioms)] +#![deny( + missing_debug_implementations, + missing_docs, + unused_results, + clippy::extra_unused_lifetimes, + clippy::from_over_into, + clippy::needless_borrow, + clippy::new_without_default, + clippy::useless_conversion +)] +#![forbid(rust_2018_idioms, unsafe_code)] +#![allow(clippy::inherent_to_string, clippy::type_complexity)] +#![cfg_attr(docsrs, feature(doc_cfg))] #[doc(no_inline)] pub use iced_native::*; @@ -33,15 +41,16 @@ pub mod conversion; pub mod settings; pub mod window; +#[cfg(feature = "system")] +pub mod system; + mod error; -mod mode; mod position; mod proxy; pub use application::Application; pub use clipboard::Clipboard; pub use error::Error; -pub use mode::Mode; pub use position::Position; pub use proxy::Proxy; pub use settings::Settings; diff --git a/winit/src/mode.rs b/winit/src/mode.rs deleted file mode 100644 index fdce8e23..00000000 --- a/winit/src/mode.rs +++ /dev/null @@ -1,12 +0,0 @@ -/// 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, - - /// The application is hidden - Hidden, -} diff --git a/winit/src/settings.rs b/winit/src/settings.rs index 9a93824a..6387454b 100644 --- a/winit/src/settings.rs +++ b/winit/src/settings.rs @@ -14,7 +14,7 @@ mod platform; pub use platform::PlatformSpecific; use crate::conversion; -use crate::{Mode, Position}; +use crate::Position; use winit::monitor::MonitorHandle; use winit::window::WindowBuilder; @@ -37,12 +37,16 @@ pub struct Settings<Flags> { /// Whether the [`Application`] should exit when the user requests the /// window to close (e.g. the user presses the close button). + /// + /// [`Application`]: crate::Application pub exit_on_close_request: bool, /// Whether the [`Application`] should try to build the context /// using OpenGL ES first then OpenGL. /// /// NOTE: Only works for the `glow` backend. + /// + /// [`Application`]: crate::Application pub try_opengles_first: bool, } @@ -61,6 +65,9 @@ pub struct Window { /// The maximum size of the window. pub max_size: Option<(u32, u32)>, + /// Whether the window should be visible or not. + pub visible: bool, + /// Whether the window should be resizable or not. pub resizable: bool, @@ -85,7 +92,6 @@ impl Window { pub fn into_builder( self, title: &str, - mode: Mode, primary_monitor: Option<MonitorHandle>, _id: Option<String>, ) -> WindowBuilder { @@ -101,7 +107,7 @@ impl Window { .with_transparent(self.transparent) .with_window_icon(self.icon) .with_always_on_top(self.always_on_top) - .with_visible(conversion::visible(mode)); + .with_visible(self.visible); if let Some(position) = conversion::position( primary_monitor.as_ref(), @@ -132,7 +138,7 @@ impl Window { use ::winit::platform::unix::WindowBuilderExtUnix; if let Some(id) = _id { - window_builder = window_builder.with_app_id(id); + window_builder = window_builder.with_name(id.clone(), id); } } @@ -162,9 +168,6 @@ impl Window { ); } - window_builder = window_builder - .with_fullscreen(conversion::fullscreen(primary_monitor, mode)); - window_builder } } @@ -176,6 +179,7 @@ impl Default for Window { position: Position::default(), min_size: None, max_size: None, + visible: true, resizable: true, decorations: true, transparent: false, diff --git a/winit/src/settings/windows.rs b/winit/src/settings/windows.rs index fc26acd7..9bef1eaf 100644 --- a/winit/src/settings/windows.rs +++ b/winit/src/settings/windows.rs @@ -5,7 +5,7 @@ #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct PlatformSpecific { /// Parent window - pub parent: Option<winapi::shared::windef::HWND>, + pub parent: Option<winit::platform::windows::HWND>, /// Drag and drop support pub drag_and_drop: bool, diff --git a/winit/src/system.rs b/winit/src/system.rs new file mode 100644 index 00000000..0303707e --- /dev/null +++ b/winit/src/system.rs @@ -0,0 +1,41 @@ +//! Access the native system. +use crate::command::{self, Command}; +pub use iced_native::system::*; + +use iced_graphics::compositor; + +/// Query for available system information. +pub fn fetch_information<Message>( + f: impl Fn(Information) -> Message + Send + 'static, +) -> Command<Message> { + Command::single(command::Action::System(Action::QueryInformation( + Box::new(f), + ))) +} + +pub(crate) fn information( + graphics_info: compositor::Information, +) -> Information { + use sysinfo::{ProcessExt, ProcessorExt, System, SystemExt}; + let mut system = System::new_all(); + system.refresh_all(); + + let cpu = system.global_processor_info(); + + let memory_used = sysinfo::get_current_pid() + .and_then(|pid| system.process(pid).ok_or("Process not found")) + .map(|process| process.memory()) + .ok(); + + Information { + system_name: system.name(), + system_kernel: system.kernel_version(), + system_version: system.long_os_version(), + cpu_brand: cpu.brand().into(), + cpu_cores: system.physical_core_count(), + memory_total: system.total_memory(), + memory_used, + graphics_adapter: graphics_info.adapter, + graphics_backend: graphics_info.backend, + } +} diff --git a/winit/src/window.rs b/winit/src/window.rs index f3207e68..265139f7 100644 --- a/winit/src/window.rs +++ b/winit/src/window.rs @@ -2,7 +2,7 @@ use crate::command::{self, Command}; use iced_native::window; -pub use window::Event; +pub use window::{Event, Mode}; /// Resizes the window to the given logical dimensions. pub fn resize<Message>(width: u32, height: u32) -> Command<Message> { @@ -16,3 +16,17 @@ pub fn resize<Message>(width: u32, height: u32) -> Command<Message> { pub fn move_to<Message>(x: i32, y: i32) -> Command<Message> { Command::single(command::Action::Window(window::Action::Move { x, y })) } + +/// Sets the [`Mode`] of the window. +pub fn set_mode<Message>(mode: Mode) -> Command<Message> { + Command::single(command::Action::Window(window::Action::SetMode(mode))) +} + +/// Fetches the current [`Mode`] of the window. +pub fn fetch_mode<Message>( + f: impl FnOnce(Mode) -> Message + 'static, +) -> Command<Message> { + Command::single(command::Action::Window(window::Action::FetchMode( + Box::new(f), + ))) +} |