Merge pull request #1389 from iced-rs/refactor-window-mode
Replace `window::Mode` with window commands
This commit is contained in:
commit
da7e859840
15 changed files with 148 additions and 99 deletions
|
|
@ -54,13 +54,17 @@ where
|
|||
runtime.enter(|| A::new(flags))
|
||||
};
|
||||
|
||||
let should_be_visible = settings.window.visible;
|
||||
|
||||
let context = {
|
||||
let builder = settings.window.into_builder(
|
||||
&application.title(),
|
||||
application.mode(),
|
||||
event_loop.primary_monitor(),
|
||||
settings.id,
|
||||
);
|
||||
let builder = settings
|
||||
.window
|
||||
.into_builder(
|
||||
&application.title(),
|
||||
event_loop.primary_monitor(),
|
||||
settings.id,
|
||||
)
|
||||
.with_visible(false);
|
||||
|
||||
log::info!("Window builder: {:#?}", builder);
|
||||
|
||||
|
|
@ -135,6 +139,7 @@ where
|
|||
receiver,
|
||||
context,
|
||||
init_command,
|
||||
should_be_visible,
|
||||
settings.exit_on_close_request,
|
||||
));
|
||||
|
||||
|
|
@ -187,6 +192,7 @@ async fn run_instance<A, E, C>(
|
|||
mut receiver: mpsc::UnboundedReceiver<glutin::event::Event<'_, A::Message>>,
|
||||
mut context: glutin::ContextWrapper<glutin::PossiblyCurrent, Window>,
|
||||
init_command: Command<A::Message>,
|
||||
should_be_visible: bool,
|
||||
exit_on_close_request: bool,
|
||||
) where
|
||||
A: Application + 'static,
|
||||
|
|
@ -200,6 +206,7 @@ async fn run_instance<A, E, C>(
|
|||
let mut clipboard = Clipboard::connect(context.window());
|
||||
let mut cache = user_interface::Cache::default();
|
||||
let mut state = application::State::new(&application, context.window());
|
||||
let mut visible = false;
|
||||
let mut viewport_version = state.viewport_version();
|
||||
|
||||
application::run_command(
|
||||
|
|
@ -399,6 +406,12 @@ async fn run_instance<A, E, C>(
|
|||
|
||||
debug.render_finished();
|
||||
|
||||
if !visible && should_be_visible {
|
||||
context.window().set_visible(true);
|
||||
|
||||
visible = true;
|
||||
}
|
||||
|
||||
// TODO: Handle animations!
|
||||
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pub enum Action<T> {
|
|||
Clipboard(clipboard::Action<T>),
|
||||
|
||||
/// Run a window action.
|
||||
Window(window::Action),
|
||||
Window(window::Action<T>),
|
||||
|
||||
/// Run a system action.
|
||||
System(system::Action<T>),
|
||||
|
|
@ -46,7 +46,7 @@ impl<T> Action<T> {
|
|||
match self {
|
||||
Self::Future(future) => Action::Future(Box::pin(future.map(f))),
|
||||
Self::Clipboard(action) => Action::Clipboard(action.map(f)),
|
||||
Self::Window(window) => Action::Window(window),
|
||||
Self::Window(window) => Action::Window(window.map(f)),
|
||||
Self::System(system) => Action::System(system.map(f)),
|
||||
Self::Widget(widget) => Action::Widget(widget.map(f)),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
//! Build window-based GUI applications.
|
||||
mod action;
|
||||
mod event;
|
||||
mod mode;
|
||||
|
||||
pub use action::Action;
|
||||
pub use event::Event;
|
||||
pub use mode::Mode;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
use crate::window::Mode;
|
||||
|
||||
use iced_futures::MaybeSend;
|
||||
use std::fmt;
|
||||
|
||||
/// An operation to be performed on some window.
|
||||
#[derive(Debug)]
|
||||
pub enum Action {
|
||||
pub enum Action<T> {
|
||||
/// Resize the window.
|
||||
Resize {
|
||||
/// The new logical width of the window
|
||||
|
|
@ -15,4 +19,43 @@ pub enum Action {
|
|||
/// The new logical y location of the window
|
||||
y: i32,
|
||||
},
|
||||
/// Set the [`Mode`] of the window.
|
||||
SetMode(Mode),
|
||||
/// Fetch the current [`Mode`] of the window.
|
||||
FetchMode(Box<dyn FnOnce(Mode) -> T + 'static>),
|
||||
}
|
||||
|
||||
impl<T> Action<T> {
|
||||
/// Maps the output of a window [`Action`] using the provided closure.
|
||||
pub fn map<A>(
|
||||
self,
|
||||
f: impl Fn(T) -> A + 'static + MaybeSend + Sync,
|
||||
) -> Action<A>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
match self {
|
||||
Self::Resize { width, height } => Action::Resize { width, height },
|
||||
Self::Move { x, y } => Action::Move { x, y },
|
||||
Self::SetMode(mode) => Action::SetMode(mode),
|
||||
Self::FetchMode(o) => Action::FetchMode(Box::new(move |s| f(o(s)))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Action<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Resize { width, height } => write!(
|
||||
f,
|
||||
"Action::Resize {{ widget: {}, height: {} }}",
|
||||
width, height
|
||||
),
|
||||
Self::Move { x, y } => {
|
||||
write!(f, "Action::Move {{ x: {}, y: {} }}", x, y)
|
||||
}
|
||||
Self::SetMode(mode) => write!(f, "Action::SetMode({:?})", mode),
|
||||
Self::FetchMode(_) => write!(f, "Action::FetchMode"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//! Build interactive cross-platform applications.
|
||||
use crate::window;
|
||||
use crate::{Command, Element, Executor, Settings, Subscription};
|
||||
|
||||
pub use iced_native::application::{Appearance, StyleSheet};
|
||||
|
|
@ -169,18 +168,6 @@ pub trait Application: Sized {
|
|||
Subscription::none()
|
||||
}
|
||||
|
||||
/// Returns the current [`Application`] mode.
|
||||
///
|
||||
/// The runtime will automatically transition your application if a new mode
|
||||
/// is returned.
|
||||
///
|
||||
/// Currently, the mode only has an effect in native platforms.
|
||||
///
|
||||
/// By default, an application will run in windowed mode.
|
||||
fn mode(&self) -> window::Mode {
|
||||
window::Mode::Windowed
|
||||
}
|
||||
|
||||
/// Returns the scale factor of the [`Application`].
|
||||
///
|
||||
/// It can be used to dynamically control the size of the UI at runtime
|
||||
|
|
@ -277,14 +264,6 @@ where
|
|||
self.0.style()
|
||||
}
|
||||
|
||||
fn mode(&self) -> iced_winit::Mode {
|
||||
match self.0.mode() {
|
||||
window::Mode::Windowed => iced_winit::Mode::Windowed,
|
||||
window::Mode::Fullscreen => iced_winit::Mode::Fullscreen,
|
||||
window::Mode::Hidden => iced_winit::Mode::Hidden,
|
||||
}
|
||||
}
|
||||
|
||||
fn subscription(&self) -> Subscription<Self::Message> {
|
||||
self.0.subscription()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
//! Configure the window of your application in native platforms.
|
||||
mod mode;
|
||||
mod position;
|
||||
mod settings;
|
||||
|
||||
pub mod icon;
|
||||
|
||||
pub use icon::Icon;
|
||||
pub use mode::Mode;
|
||||
pub use position::Position;
|
||||
pub use settings::Settings;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ pub struct Settings {
|
|||
/// 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,
|
||||
|
||||
|
|
@ -38,6 +41,7 @@ impl Default for Settings {
|
|||
position: Position::default(),
|
||||
min_size: None,
|
||||
max_size: None,
|
||||
visible: true,
|
||||
resizable: true,
|
||||
decorations: true,
|
||||
transparent: false,
|
||||
|
|
@ -54,6 +58,7 @@ impl From<Settings> for iced_winit::settings::Window {
|
|||
position: iced_winit::Position::from(settings.position),
|
||||
min_size: settings.min_size,
|
||||
max_size: settings.max_size,
|
||||
visible: settings.visible,
|
||||
resizable: settings.resizable,
|
||||
decorations: settings.decorations,
|
||||
transparent: settings.transparent,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::mouse;
|
|||
use crate::renderer;
|
||||
use crate::widget::operation;
|
||||
use crate::{
|
||||
Command, Debug, Error, Executor, Mode, Proxy, Runtime, Settings, Size,
|
||||
Command, Debug, Error, Executor, Proxy, Runtime, Settings, Size,
|
||||
Subscription,
|
||||
};
|
||||
|
||||
|
|
@ -81,16 +81,6 @@ where
|
|||
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 scale factor of the [`Application`].
|
||||
///
|
||||
/// It can be used to dynamically control the size of the UI at runtime
|
||||
|
|
@ -147,12 +137,15 @@ where
|
|||
runtime.enter(|| A::new(flags))
|
||||
};
|
||||
|
||||
let builder = settings.window.into_builder(
|
||||
&application.title(),
|
||||
application.mode(),
|
||||
event_loop.primary_monitor(),
|
||||
settings.id,
|
||||
);
|
||||
let should_be_visible = settings.window.visible;
|
||||
let builder = settings
|
||||
.window
|
||||
.into_builder(
|
||||
&application.title(),
|
||||
event_loop.primary_monitor(),
|
||||
settings.id,
|
||||
)
|
||||
.with_visible(false);
|
||||
|
||||
log::info!("Window builder: {:#?}", builder);
|
||||
|
||||
|
|
@ -189,6 +182,7 @@ where
|
|||
receiver,
|
||||
init_command,
|
||||
window,
|
||||
should_be_visible,
|
||||
settings.exit_on_close_request,
|
||||
));
|
||||
|
||||
|
|
@ -239,6 +233,7 @@ async fn run_instance<A, E, C>(
|
|||
mut receiver: mpsc::UnboundedReceiver<winit::event::Event<'_, A::Message>>,
|
||||
init_command: Command<A::Message>,
|
||||
window: winit::window::Window,
|
||||
should_be_visible: bool,
|
||||
exit_on_close_request: bool,
|
||||
) where
|
||||
A: Application + 'static,
|
||||
|
|
@ -252,6 +247,7 @@ async fn run_instance<A, E, C>(
|
|||
let mut clipboard = Clipboard::connect(&window);
|
||||
let mut cache = user_interface::Cache::default();
|
||||
let mut surface = compositor.create_surface(&window);
|
||||
let mut visible = false;
|
||||
|
||||
let mut state = State::new(&application, &window);
|
||||
let mut viewport_version = state.viewport_version();
|
||||
|
|
@ -383,6 +379,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,
|
||||
|
|
@ -450,6 +447,12 @@ async fn run_instance<A, E, C>(
|
|||
Ok(()) => {
|
||||
debug.render_finished();
|
||||
|
||||
if !visible && should_be_visible {
|
||||
window.set_visible(true);
|
||||
|
||||
visible = true;
|
||||
}
|
||||
|
||||
// TODO: Handle animations!
|
||||
// Maybe we can use `ControlFlow::WaitUntil` for this.
|
||||
}
|
||||
|
|
@ -637,6 +640,20 @@ pub fn run_command<A, E>(
|
|||
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 = conversion::mode(window.fullscreen());
|
||||
|
||||
proxy
|
||||
.send_event(tag(mode))
|
||||
.expect("Send message to event loop");
|
||||
}
|
||||
},
|
||||
command::Action::System(action) => match action {
|
||||
system::Action::QueryInformation(_tag) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
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};
|
||||
|
|
@ -13,7 +13,6 @@ where
|
|||
<A::Renderer as crate::Renderer>::Theme: application::StyleSheet,
|
||||
{
|
||||
title: String,
|
||||
mode: Mode,
|
||||
scale_factor: f64,
|
||||
viewport: Viewport,
|
||||
viewport_version: usize,
|
||||
|
|
@ -31,7 +30,6 @@ where
|
|||
/// 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 scale_factor = application.scale_factor();
|
||||
let theme = application.theme();
|
||||
let appearance = theme.appearance(application.style());
|
||||
|
|
@ -47,7 +45,6 @@ where
|
|||
|
||||
Self {
|
||||
title,
|
||||
mode,
|
||||
scale_factor,
|
||||
viewport,
|
||||
viewport_version: 0,
|
||||
|
|
@ -193,20 +190,6 @@ where
|
|||
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 scale factor
|
||||
let new_scale_factor = application.scale_factor();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ 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,26 +182,36 @@ 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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,14 +45,12 @@ pub mod window;
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -65,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,
|
||||
|
||||
|
|
@ -89,7 +92,6 @@ impl Window {
|
|||
pub fn into_builder(
|
||||
self,
|
||||
title: &str,
|
||||
mode: Mode,
|
||||
primary_monitor: Option<MonitorHandle>,
|
||||
_id: Option<String>,
|
||||
) -> WindowBuilder {
|
||||
|
|
@ -104,8 +106,7 @@ impl Window {
|
|||
.with_decorations(self.decorations)
|
||||
.with_transparent(self.transparent)
|
||||
.with_window_icon(self.icon)
|
||||
.with_always_on_top(self.always_on_top)
|
||||
.with_visible(conversion::visible(mode));
|
||||
.with_always_on_top(self.always_on_top);
|
||||
|
||||
if let Some(position) = conversion::position(
|
||||
primary_monitor.as_ref(),
|
||||
|
|
@ -166,9 +167,6 @@ impl Window {
|
|||
);
|
||||
}
|
||||
|
||||
window_builder = window_builder
|
||||
.with_fullscreen(conversion::fullscreen(primary_monitor, mode));
|
||||
|
||||
window_builder
|
||||
}
|
||||
}
|
||||
|
|
@ -180,6 +178,7 @@ impl Default for Window {
|
|||
position: Position::default(),
|
||||
min_size: None,
|
||||
max_size: None,
|
||||
visible: true,
|
||||
resizable: true,
|
||||
decorations: true,
|
||||
transparent: false,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue