Refactor event loop <-> instance communication in multi_window
This commit is contained in:
parent
3b39ba7029
commit
d34bc4e4a2
1 changed files with 469 additions and 436 deletions
|
|
@ -8,7 +8,7 @@ use crate::conversion;
|
||||||
use crate::core::widget::operation;
|
use crate::core::widget::operation;
|
||||||
use crate::core::{self, mouse, renderer, window, Size};
|
use crate::core::{self, mouse, renderer, window, Size};
|
||||||
use crate::futures::futures::channel::mpsc;
|
use crate::futures::futures::channel::mpsc;
|
||||||
use crate::futures::futures::{task, Future, FutureExt, StreamExt};
|
use crate::futures::futures::{task, Future, StreamExt};
|
||||||
use crate::futures::{Executor, Runtime, Subscription};
|
use crate::futures::{Executor, Runtime, Subscription};
|
||||||
use crate::graphics::{compositor, Compositor};
|
use crate::graphics::{compositor, Compositor};
|
||||||
use crate::multi_window::windows::Windows;
|
use crate::multi_window::windows::Windows;
|
||||||
|
|
@ -21,23 +21,24 @@ use crate::{Clipboard, Error, Proxy, Settings};
|
||||||
|
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use winit::monitor::MonitorHandle;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
enum Event<Message: 'static> {
|
||||||
enum Event<Message> {
|
|
||||||
Application(Message),
|
|
||||||
NewWindow {
|
|
||||||
id: window::Id,
|
|
||||||
settings: window::Settings,
|
|
||||||
title: String,
|
|
||||||
monitor: Option<MonitorHandle>,
|
|
||||||
},
|
|
||||||
CloseWindow(window::Id),
|
|
||||||
WindowCreated {
|
WindowCreated {
|
||||||
id: window::Id,
|
id: window::Id,
|
||||||
window: winit::window::Window,
|
window: winit::window::Window,
|
||||||
exit_on_close_request: bool,
|
exit_on_close_request: bool,
|
||||||
},
|
},
|
||||||
|
EventLoopAwakened(winit::event::Event<'static, Message>),
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Control {
|
||||||
|
ChangeFlow(winit::event_loop::ControlFlow),
|
||||||
|
CreateWindow {
|
||||||
|
id: window::Id,
|
||||||
|
settings: window::Settings,
|
||||||
|
title: String,
|
||||||
|
monitor: Option<winit::monitor::MonitorHandle>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An interactive, native, cross-platform, multi-windowed application.
|
/// An interactive, native, cross-platform, multi-windowed application.
|
||||||
|
|
@ -243,13 +244,31 @@ where
|
||||||
event: winit::event::WindowEvent::Resized(*new_inner_size),
|
event: winit::event::WindowEvent::Resized(*new_inner_size),
|
||||||
window_id,
|
window_id,
|
||||||
}),
|
}),
|
||||||
winit::event::Event::UserEvent(Event::NewWindow {
|
_ => event.to_static(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(event) = event {
|
||||||
|
event_sender
|
||||||
|
.start_send(Event::EventLoopAwakened(event))
|
||||||
|
.expect("Send event");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let poll = instance.as_mut().poll(&mut context);
|
||||||
|
|
||||||
|
match poll {
|
||||||
|
task::Poll::Pending => match control_receiver.try_next() {
|
||||||
|
Ok(Some(control)) => match control {
|
||||||
|
Control::ChangeFlow(flow) => {
|
||||||
|
*control_flow = flow;
|
||||||
|
}
|
||||||
|
Control::CreateWindow {
|
||||||
id,
|
id,
|
||||||
settings,
|
settings,
|
||||||
title,
|
title,
|
||||||
monitor,
|
monitor,
|
||||||
}) => {
|
} => {
|
||||||
let exit_on_close_request = settings.exit_on_close_request;
|
let exit_on_close_request =
|
||||||
|
settings.exit_on_close_request;
|
||||||
|
|
||||||
let window = conversion::window_settings(
|
let window = conversion::window_settings(
|
||||||
settings, &title, monitor, None,
|
settings, &title, monitor, None,
|
||||||
|
|
@ -257,44 +276,37 @@ where
|
||||||
.build(window_target)
|
.build(window_target)
|
||||||
.expect("Failed to build window");
|
.expect("Failed to build window");
|
||||||
|
|
||||||
Some(winit::event::Event::UserEvent(Event::WindowCreated {
|
event_sender
|
||||||
|
.start_send(Event::WindowCreated {
|
||||||
id,
|
id,
|
||||||
window,
|
window,
|
||||||
exit_on_close_request,
|
exit_on_close_request,
|
||||||
}))
|
})
|
||||||
}
|
.expect("Send event");
|
||||||
_ => event.to_static(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(event) = event {
|
|
||||||
event_sender.start_send(event).expect("Send event");
|
|
||||||
|
|
||||||
let poll = instance.as_mut().poll(&mut context);
|
|
||||||
|
|
||||||
match poll {
|
|
||||||
task::Poll::Pending => {
|
|
||||||
if let Ok(Some(flow)) = control_receiver.try_next() {
|
|
||||||
*control_flow = flow;
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
task::Poll::Ready(_) => {
|
task::Poll::Ready(_) => {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_instance<A, E, C>(
|
async fn run_instance<A, E, C>(
|
||||||
mut application: A,
|
mut application: A,
|
||||||
mut compositor: C,
|
mut compositor: C,
|
||||||
mut runtime: Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
mut runtime: Runtime<E, Proxy<A::Message>, A::Message>,
|
||||||
mut proxy: winit::event_loop::EventLoopProxy<Event<A::Message>>,
|
mut proxy: winit::event_loop::EventLoopProxy<A::Message>,
|
||||||
mut debug: Debug,
|
mut debug: Debug,
|
||||||
mut event_receiver: mpsc::UnboundedReceiver<
|
mut event_receiver: mpsc::UnboundedReceiver<Event<A::Message>>,
|
||||||
winit::event::Event<'_, Event<A::Message>>,
|
mut control_sender: mpsc::UnboundedSender<Control>,
|
||||||
>,
|
|
||||||
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
|
|
||||||
init_command: Command<A::Message>,
|
init_command: Command<A::Message>,
|
||||||
mut windows: Windows<A, C>,
|
mut windows: Windows<A, C>,
|
||||||
should_main_window_be_visible: bool,
|
should_main_window_be_visible: bool,
|
||||||
|
|
@ -327,18 +339,14 @@ async fn run_instance<A, E, C>(
|
||||||
init_command,
|
init_command,
|
||||||
&mut runtime,
|
&mut runtime,
|
||||||
&mut clipboard,
|
&mut clipboard,
|
||||||
|
&mut control_sender,
|
||||||
&mut proxy,
|
&mut proxy,
|
||||||
&mut debug,
|
&mut debug,
|
||||||
&mut windows,
|
&mut windows,
|
||||||
&mut ui_caches,
|
&mut ui_caches,
|
||||||
);
|
);
|
||||||
|
|
||||||
runtime.track(
|
runtime.track(application.subscription().into_recipes());
|
||||||
application
|
|
||||||
.subscription()
|
|
||||||
.map(Event::Application)
|
|
||||||
.into_recipes(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut mouse_interaction = mouse::Interaction::default();
|
let mut mouse_interaction = mouse::Interaction::default();
|
||||||
|
|
||||||
|
|
@ -360,6 +368,46 @@ async fn run_instance<A, E, C>(
|
||||||
debug.startup_finished();
|
debug.startup_finished();
|
||||||
|
|
||||||
'main: while let Some(event) = event_receiver.next().await {
|
'main: while let Some(event) = event_receiver.next().await {
|
||||||
|
match event {
|
||||||
|
Event::WindowCreated {
|
||||||
|
id,
|
||||||
|
window,
|
||||||
|
exit_on_close_request,
|
||||||
|
} => {
|
||||||
|
let bounds = logical_bounds_of(&window);
|
||||||
|
|
||||||
|
let (inner_size, i) = windows.add(
|
||||||
|
&application,
|
||||||
|
&mut compositor,
|
||||||
|
id,
|
||||||
|
window,
|
||||||
|
exit_on_close_request,
|
||||||
|
);
|
||||||
|
|
||||||
|
user_interfaces.push(build_user_interface(
|
||||||
|
&application,
|
||||||
|
user_interface::Cache::default(),
|
||||||
|
&mut windows.renderers[i],
|
||||||
|
inner_size,
|
||||||
|
&mut debug,
|
||||||
|
id,
|
||||||
|
));
|
||||||
|
ui_caches.push(user_interface::Cache::default());
|
||||||
|
|
||||||
|
if let Some(bounds) = bounds {
|
||||||
|
events.push((
|
||||||
|
Some(id),
|
||||||
|
core::Event::Window(
|
||||||
|
id,
|
||||||
|
window::Event::Created {
|
||||||
|
position: bounds.0,
|
||||||
|
size: bounds.1,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::EventLoopAwakened(event) => {
|
||||||
match event {
|
match event {
|
||||||
event::Event::NewEvents(start_cause) => {
|
event::Event::NewEvents(start_cause) => {
|
||||||
redraw_pending = matches!(
|
redraw_pending = matches!(
|
||||||
|
|
@ -377,7 +425,9 @@ async fn run_instance<A, E, C>(
|
||||||
let mut window_events = vec![];
|
let mut window_events = vec![];
|
||||||
|
|
||||||
events.retain(|(window_id, event)| {
|
events.retain(|(window_id, event)| {
|
||||||
if *window_id == Some(*id) || window_id.is_none() {
|
if *window_id == Some(*id)
|
||||||
|
|| window_id.is_none()
|
||||||
|
{
|
||||||
window_events.push(event.clone());
|
window_events.push(event.clone());
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -392,7 +442,8 @@ async fn run_instance<A, E, C>(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (ui_state, statuses) = user_interfaces[i].update(
|
let (ui_state, statuses) = user_interfaces[i]
|
||||||
|
.update(
|
||||||
&window_events,
|
&window_events,
|
||||||
windows.states[i].cursor(),
|
windows.states[i].cursor(),
|
||||||
&mut windows.renderers[i],
|
&mut windows.renderers[i],
|
||||||
|
|
@ -401,12 +452,15 @@ async fn run_instance<A, E, C>(
|
||||||
);
|
);
|
||||||
|
|
||||||
if !uis_stale {
|
if !uis_stale {
|
||||||
uis_stale =
|
uis_stale = matches!(
|
||||||
matches!(ui_state, user_interface::State::Outdated);
|
ui_state,
|
||||||
|
user_interface::State::Outdated
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (event, status) in
|
for (event, status) in window_events
|
||||||
window_events.into_iter().zip(statuses.into_iter())
|
.into_iter()
|
||||||
|
.zip(statuses.into_iter())
|
||||||
{
|
{
|
||||||
runtime.broadcast(event, status);
|
runtime.broadcast(event, status);
|
||||||
}
|
}
|
||||||
|
|
@ -416,8 +470,9 @@ async fn run_instance<A, E, C>(
|
||||||
|
|
||||||
// TODO mw application update returns which window IDs to update
|
// TODO mw application update returns which window IDs to update
|
||||||
if !messages.is_empty() || uis_stale {
|
if !messages.is_empty() || uis_stale {
|
||||||
let mut cached_interfaces: Vec<user_interface::Cache> =
|
let mut cached_interfaces: Vec<
|
||||||
ManuallyDrop::into_inner(user_interfaces)
|
user_interface::Cache,
|
||||||
|
> = ManuallyDrop::into_inner(user_interfaces)
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(UserInterface::into_cache)
|
.map(UserInterface::into_cache)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
@ -428,6 +483,7 @@ async fn run_instance<A, E, C>(
|
||||||
&mut compositor,
|
&mut compositor,
|
||||||
&mut runtime,
|
&mut runtime,
|
||||||
&mut clipboard,
|
&mut clipboard,
|
||||||
|
&mut control_sender,
|
||||||
&mut proxy,
|
&mut proxy,
|
||||||
&mut debug,
|
&mut debug,
|
||||||
&mut messages,
|
&mut messages,
|
||||||
|
|
@ -446,7 +502,8 @@ async fn run_instance<A, E, C>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// rebuild UIs with the synchronized states
|
// rebuild UIs with the synchronized states
|
||||||
user_interfaces = ManuallyDrop::new(build_user_interfaces(
|
user_interfaces =
|
||||||
|
ManuallyDrop::new(build_user_interfaces(
|
||||||
&application,
|
&application,
|
||||||
&mut debug,
|
&mut debug,
|
||||||
&mut windows,
|
&mut windows,
|
||||||
|
|
@ -509,7 +566,8 @@ async fn run_instance<A, E, C>(
|
||||||
core::event::Status::Ignored,
|
core::event::Status::Ignored,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = control_sender.start_send(match ui_state {
|
let _ = control_sender.start_send(
|
||||||
|
Control::ChangeFlow(match ui_state {
|
||||||
user_interface::State::Updated {
|
user_interface::State::Updated {
|
||||||
redraw_request: Some(redraw_request),
|
redraw_request: Some(redraw_request),
|
||||||
} => match redraw_request {
|
} => match redraw_request {
|
||||||
|
|
@ -521,16 +579,19 @@ async fn run_instance<A, E, C>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => ControlFlow::Wait,
|
_ => ControlFlow::Wait,
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw_pending = false;
|
redraw_pending = false;
|
||||||
|
|
||||||
debug.draw_finished();
|
debug.draw_finished();
|
||||||
}
|
}
|
||||||
event::Event::PlatformSpecific(event::PlatformSpecific::MacOS(
|
event::Event::PlatformSpecific(
|
||||||
|
event::PlatformSpecific::MacOS(
|
||||||
event::MacOS::ReceivedUrl(url),
|
event::MacOS::ReceivedUrl(url),
|
||||||
)) => {
|
),
|
||||||
|
) => {
|
||||||
use crate::core::event;
|
use crate::core::event;
|
||||||
|
|
||||||
events.push((
|
events.push((
|
||||||
|
|
@ -542,71 +603,23 @@ async fn run_instance<A, E, C>(
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
event::Event::UserEvent(event) => match event {
|
event::Event::UserEvent(message) => {
|
||||||
Event::Application(message) => {
|
|
||||||
messages.push(message);
|
messages.push(message);
|
||||||
}
|
}
|
||||||
Event::WindowCreated {
|
|
||||||
id,
|
|
||||||
window,
|
|
||||||
exit_on_close_request,
|
|
||||||
} => {
|
|
||||||
let bounds = logical_bounds_of(&window);
|
|
||||||
|
|
||||||
let (inner_size, i) = windows.add(
|
|
||||||
&application,
|
|
||||||
&mut compositor,
|
|
||||||
id,
|
|
||||||
window,
|
|
||||||
exit_on_close_request,
|
|
||||||
);
|
|
||||||
|
|
||||||
user_interfaces.push(build_user_interface(
|
|
||||||
&application,
|
|
||||||
user_interface::Cache::default(),
|
|
||||||
&mut windows.renderers[i],
|
|
||||||
inner_size,
|
|
||||||
&mut debug,
|
|
||||||
id,
|
|
||||||
));
|
|
||||||
ui_caches.push(user_interface::Cache::default());
|
|
||||||
|
|
||||||
if let Some(bounds) = bounds {
|
|
||||||
events.push((
|
|
||||||
Some(id),
|
|
||||||
core::Event::Window(
|
|
||||||
id,
|
|
||||||
window::Event::Created {
|
|
||||||
position: bounds.0,
|
|
||||||
size: bounds.1,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::CloseWindow(id) => {
|
|
||||||
let i = windows.delete(id);
|
|
||||||
let _ = user_interfaces.remove(i);
|
|
||||||
let _ = ui_caches.remove(i);
|
|
||||||
|
|
||||||
if windows.is_empty() {
|
|
||||||
break 'main;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::NewWindow { .. } => unreachable!(),
|
|
||||||
},
|
|
||||||
event::Event::RedrawRequested(id) => {
|
event::Event::RedrawRequested(id) => {
|
||||||
let i = windows.index_from_raw(id);
|
let i = windows.index_from_raw(id);
|
||||||
let state = &windows.states[i];
|
let state = &windows.states[i];
|
||||||
let physical_size = state.physical_size();
|
let physical_size = state.physical_size();
|
||||||
|
|
||||||
if physical_size.width == 0 || physical_size.height == 0 {
|
if physical_size.width == 0 || physical_size.height == 0
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.render_started();
|
debug.render_started();
|
||||||
let current_viewport_version = state.viewport_version();
|
let current_viewport_version = state.viewport_version();
|
||||||
let window_viewport_version = windows.viewport_versions[i];
|
let window_viewport_version =
|
||||||
|
windows.viewport_versions[i];
|
||||||
|
|
||||||
if window_viewport_version != current_viewport_version {
|
if window_viewport_version != current_viewport_version {
|
||||||
let logical_size = state.logical_size();
|
let logical_size = state.logical_size();
|
||||||
|
|
@ -622,7 +635,8 @@ async fn run_instance<A, E, C>(
|
||||||
debug.layout_finished();
|
debug.layout_finished();
|
||||||
|
|
||||||
debug.draw_started();
|
debug.draw_started();
|
||||||
let new_mouse_interaction = user_interfaces[i].draw(
|
let new_mouse_interaction = user_interfaces[i]
|
||||||
|
.draw(
|
||||||
renderer,
|
renderer,
|
||||||
state.theme(),
|
state.theme(),
|
||||||
&renderer::Style {
|
&renderer::Style {
|
||||||
|
|
@ -648,7 +662,8 @@ async fn run_instance<A, E, C>(
|
||||||
physical_size.height,
|
physical_size.height,
|
||||||
);
|
);
|
||||||
|
|
||||||
windows.viewport_versions[i] = current_viewport_version;
|
windows.viewport_versions[i] =
|
||||||
|
current_viewport_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
match compositor.present(
|
match compositor.present(
|
||||||
|
|
@ -687,8 +702,10 @@ async fn run_instance<A, E, C>(
|
||||||
event: window_event,
|
event: window_event,
|
||||||
window_id,
|
window_id,
|
||||||
} => {
|
} => {
|
||||||
let window_index =
|
let window_index = windows
|
||||||
windows.raw.iter().position(|w| w.id() == window_id);
|
.raw
|
||||||
|
.iter()
|
||||||
|
.position(|w| w.id() == window_id);
|
||||||
|
|
||||||
match window_index {
|
match window_index {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
|
|
@ -711,14 +728,20 @@ async fn run_instance<A, E, C>(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let state = &mut windows.states[i];
|
let state = &mut windows.states[i];
|
||||||
state.update(raw, &window_event, &mut debug);
|
state.update(
|
||||||
|
raw,
|
||||||
|
&window_event,
|
||||||
|
&mut debug,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(event) = conversion::window_event(
|
if let Some(event) =
|
||||||
|
conversion::window_event(
|
||||||
id,
|
id,
|
||||||
&window_event,
|
&window_event,
|
||||||
state.scale_factor(),
|
state.scale_factor(),
|
||||||
state.modifiers(),
|
state.modifiers(),
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
events.push((Some(id), event));
|
events.push((Some(id), event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -732,7 +755,8 @@ async fn run_instance<A, E, C>(
|
||||||
window_event,
|
window_event,
|
||||||
winit::event::WindowEvent::Destroyed
|
winit::event::WindowEvent::Destroyed
|
||||||
) {
|
) {
|
||||||
let id = windows.get_pending_destroy(window_id);
|
let id =
|
||||||
|
windows.get_pending_destroy(window_id);
|
||||||
|
|
||||||
events.push((
|
events.push((
|
||||||
None,
|
None,
|
||||||
|
|
@ -748,6 +772,8 @@ async fn run_instance<A, E, C>(
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let _ = ManuallyDrop::into_inner(user_interfaces);
|
let _ = ManuallyDrop::into_inner(user_interfaces);
|
||||||
}
|
}
|
||||||
|
|
@ -780,9 +806,10 @@ where
|
||||||
fn update<A: Application, C, E: Executor>(
|
fn update<A: Application, C, E: Executor>(
|
||||||
application: &mut A,
|
application: &mut A,
|
||||||
compositor: &mut C,
|
compositor: &mut C,
|
||||||
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
runtime: &mut Runtime<E, Proxy<A::Message>, A::Message>,
|
||||||
clipboard: &mut Clipboard,
|
clipboard: &mut Clipboard,
|
||||||
proxy: &mut winit::event_loop::EventLoopProxy<Event<A::Message>>,
|
control_sender: &mut mpsc::UnboundedSender<Control>,
|
||||||
|
proxy: &mut winit::event_loop::EventLoopProxy<A::Message>,
|
||||||
debug: &mut Debug,
|
debug: &mut Debug,
|
||||||
messages: &mut Vec<A::Message>,
|
messages: &mut Vec<A::Message>,
|
||||||
windows: &mut Windows<A, C>,
|
windows: &mut Windows<A, C>,
|
||||||
|
|
@ -804,6 +831,7 @@ fn update<A: Application, C, E: Executor>(
|
||||||
command,
|
command,
|
||||||
runtime,
|
runtime,
|
||||||
clipboard,
|
clipboard,
|
||||||
|
control_sender,
|
||||||
proxy,
|
proxy,
|
||||||
debug,
|
debug,
|
||||||
windows,
|
windows,
|
||||||
|
|
@ -811,7 +839,7 @@ fn update<A: Application, C, E: Executor>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let subscription = application.subscription().map(Event::Application);
|
let subscription = application.subscription();
|
||||||
runtime.track(subscription.into_recipes());
|
runtime.track(subscription.into_recipes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -820,9 +848,10 @@ fn run_command<A, C, E>(
|
||||||
application: &A,
|
application: &A,
|
||||||
compositor: &mut C,
|
compositor: &mut C,
|
||||||
command: Command<A::Message>,
|
command: Command<A::Message>,
|
||||||
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
runtime: &mut Runtime<E, Proxy<A::Message>, A::Message>,
|
||||||
clipboard: &mut Clipboard,
|
clipboard: &mut Clipboard,
|
||||||
proxy: &mut winit::event_loop::EventLoopProxy<Event<A::Message>>,
|
control_sender: &mut mpsc::UnboundedSender<Control>,
|
||||||
|
proxy: &mut winit::event_loop::EventLoopProxy<A::Message>,
|
||||||
debug: &mut Debug,
|
debug: &mut Debug,
|
||||||
windows: &mut Windows<A, C>,
|
windows: &mut Windows<A, C>,
|
||||||
ui_caches: &mut Vec<user_interface::Cache>,
|
ui_caches: &mut Vec<user_interface::Cache>,
|
||||||
|
|
@ -839,17 +868,17 @@ fn run_command<A, C, E>(
|
||||||
for action in command.actions() {
|
for action in command.actions() {
|
||||||
match action {
|
match action {
|
||||||
command::Action::Future(future) => {
|
command::Action::Future(future) => {
|
||||||
runtime.spawn(Box::pin(future.map(Event::Application)));
|
runtime.spawn(Box::pin(future));
|
||||||
}
|
}
|
||||||
command::Action::Stream(stream) => {
|
command::Action::Stream(stream) => {
|
||||||
runtime.run(Box::pin(stream.map(Event::Application)));
|
runtime.run(Box::pin(stream));
|
||||||
}
|
}
|
||||||
command::Action::Clipboard(action) => match action {
|
command::Action::Clipboard(action) => match action {
|
||||||
clipboard::Action::Read(tag) => {
|
clipboard::Action::Read(tag) => {
|
||||||
let message = tag(clipboard.read());
|
let message = tag(clipboard.read());
|
||||||
|
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(message))
|
.send_event(message)
|
||||||
.expect("Send message to event loop");
|
.expect("Send message to event loop");
|
||||||
}
|
}
|
||||||
clipboard::Action::Write(contents) => {
|
clipboard::Action::Write(contents) => {
|
||||||
|
|
@ -860,19 +889,28 @@ fn run_command<A, C, E>(
|
||||||
window::Action::Spawn { settings } => {
|
window::Action::Spawn { settings } => {
|
||||||
let monitor = windows.last_monitor();
|
let monitor = windows.last_monitor();
|
||||||
|
|
||||||
proxy
|
control_sender
|
||||||
.send_event(Event::NewWindow {
|
.start_send(Control::CreateWindow {
|
||||||
id,
|
id,
|
||||||
settings,
|
settings,
|
||||||
title: application.title(id),
|
title: application.title(id),
|
||||||
monitor,
|
monitor,
|
||||||
})
|
})
|
||||||
.expect("Send message to event loop");
|
.expect("Send control action");
|
||||||
}
|
}
|
||||||
window::Action::Close => {
|
window::Action::Close => {
|
||||||
proxy
|
use winit::event_loop::ControlFlow;
|
||||||
.send_event(Event::CloseWindow(id))
|
|
||||||
.expect("Send message to event loop");
|
let i = windows.delete(id);
|
||||||
|
let _ = ui_caches.remove(i);
|
||||||
|
|
||||||
|
if windows.is_empty() {
|
||||||
|
control_sender
|
||||||
|
.start_send(Control::ChangeFlow(
|
||||||
|
ControlFlow::ExitWithCode(0),
|
||||||
|
))
|
||||||
|
.expect("Send control action");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
window::Action::Drag => {
|
window::Action::Drag => {
|
||||||
let _ = windows.with_raw(id).drag_window();
|
let _ = windows.with_raw(id).drag_window();
|
||||||
|
|
@ -890,10 +928,10 @@ fn run_command<A, C, E>(
|
||||||
let size = window.inner_size();
|
let size = window.inner_size();
|
||||||
|
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(callback(Size::new(
|
.send_event(callback(Size::new(
|
||||||
size.width,
|
size.width,
|
||||||
size.height,
|
size.height,
|
||||||
))))
|
)))
|
||||||
.expect("Send message to event loop");
|
.expect("Send message to event loop");
|
||||||
}
|
}
|
||||||
window::Action::Maximize(maximized) => {
|
window::Action::Maximize(maximized) => {
|
||||||
|
|
@ -929,7 +967,7 @@ fn run_command<A, C, E>(
|
||||||
};
|
};
|
||||||
|
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(tag(mode)))
|
.send_event(tag(mode))
|
||||||
.expect("Event loop doesn't exist.");
|
.expect("Event loop doesn't exist.");
|
||||||
}
|
}
|
||||||
window::Action::ToggleMaximize => {
|
window::Action::ToggleMaximize => {
|
||||||
|
|
@ -955,10 +993,7 @@ fn run_command<A, C, E>(
|
||||||
}
|
}
|
||||||
window::Action::FetchId(tag) => {
|
window::Action::FetchId(tag) => {
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(tag(windows
|
.send_event(tag(windows.with_raw(id).id().into()))
|
||||||
.with_raw(id)
|
|
||||||
.id()
|
|
||||||
.into())))
|
|
||||||
.expect("Event loop doesn't exist.");
|
.expect("Event loop doesn't exist.");
|
||||||
}
|
}
|
||||||
window::Action::Screenshot(tag) => {
|
window::Action::Screenshot(tag) => {
|
||||||
|
|
@ -976,11 +1011,9 @@ fn run_command<A, C, E>(
|
||||||
);
|
);
|
||||||
|
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(tag(
|
.send_event(tag(window::Screenshot::new(
|
||||||
window::Screenshot::new(
|
|
||||||
bytes,
|
bytes,
|
||||||
state.physical_size(),
|
state.physical_size(),
|
||||||
),
|
|
||||||
)))
|
)))
|
||||||
.expect("Event loop doesn't exist.");
|
.expect("Event loop doesn't exist.");
|
||||||
}
|
}
|
||||||
|
|
@ -999,7 +1032,7 @@ fn run_command<A, C, E>(
|
||||||
let message = _tag(information);
|
let message = _tag(information);
|
||||||
|
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(message))
|
.send_event(message)
|
||||||
.expect("Event loop doesn't exist.");
|
.expect("Event loop doesn't exist.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1025,7 +1058,7 @@ fn run_command<A, C, E>(
|
||||||
operation::Outcome::None => {}
|
operation::Outcome::None => {}
|
||||||
operation::Outcome::Some(message) => {
|
operation::Outcome::Some(message) => {
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(message))
|
.send_event(message)
|
||||||
.expect("Event loop doesn't exist.");
|
.expect("Event loop doesn't exist.");
|
||||||
|
|
||||||
// operation completed, don't need to try to operate on rest of UIs
|
// operation completed, don't need to try to operate on rest of UIs
|
||||||
|
|
@ -1051,7 +1084,7 @@ fn run_command<A, C, E>(
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(tagger(Ok(()))))
|
.send_event(tagger(Ok(())))
|
||||||
.expect("Send message to event loop");
|
.expect("Send message to event loop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue