summaryrefslogtreecommitdiffstats
path: root/winit/src/program.rs
diff options
context:
space:
mode:
Diffstat (limited to 'winit/src/program.rs')
-rw-r--r--winit/src/program.rs199
1 files changed, 142 insertions, 57 deletions
diff --git a/winit/src/program.rs b/winit/src/program.rs
index d55aedf1..52d8eb5f 100644
--- a/winit/src/program.rs
+++ b/winit/src/program.rs
@@ -202,12 +202,25 @@ where
};
let (program, task) = runtime.enter(|| P::new(flags));
+ let is_daemon = window_settings.is_none();
- if let Some(stream) = task.into_stream() {
+ let task = if let Some(window_settings) = window_settings {
+ let mut task = Some(task);
+
+ let (_id, open) = runtime::window::open(window_settings);
+
+ open.then(move |_| task.take().unwrap_or(Task::none()))
+ } else {
+ task
+ };
+
+ if let Some(stream) = runtime::task::into_stream(task) {
runtime.run(stream);
}
- runtime.track(program.subscription().map(Action::Output).into_recipes());
+ runtime.track(subscription::into_recipes(
+ program.subscription().map(Action::Output),
+ ));
let (boot_sender, boot_receiver) = oneshot::channel();
let (event_sender, event_receiver) = mpsc::unbounded();
@@ -221,6 +234,7 @@ where
boot_receiver,
event_receiver,
control_sender,
+ is_daemon,
));
let context = task::Context::from_waker(task::noop_waker_ref());
@@ -229,7 +243,7 @@ where
instance: std::pin::Pin<Box<F>>,
context: task::Context<'static>,
id: Option<String>,
- boot: Option<BootConfig<Message, C>>,
+ boot: Option<BootConfig<C>>,
sender: mpsc::UnboundedSender<Event<Action<Message>>>,
receiver: mpsc::UnboundedReceiver<Control>,
error: Option<Error>,
@@ -240,11 +254,9 @@ where
queued_events: Vec<Event<Action<Message>>>,
}
- struct BootConfig<Message: 'static, C> {
- proxy: Proxy<Message>,
+ struct BootConfig<C> {
sender: oneshot::Sender<Boot<C>>,
fonts: Vec<Cow<'static, [u8]>>,
- window_settings: Option<window::Settings>,
graphics_settings: graphics::Settings,
}
@@ -253,10 +265,8 @@ where
context,
id: settings.id,
boot: Some(BootConfig {
- proxy,
sender: boot_sender,
fonts: settings.fonts,
- window_settings,
graphics_settings,
}),
sender: event_sender,
@@ -278,10 +288,8 @@ where
{
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
let Some(BootConfig {
- mut proxy,
sender,
fonts,
- window_settings,
graphics_settings,
}) = self.boot.take()
else {
@@ -299,8 +307,6 @@ where
}
};
- let clipboard = Clipboard::connect(&window);
-
let finish_boot = async move {
let mut compositor =
C::new(graphics_settings, window.clone()).await?;
@@ -310,27 +316,10 @@ where
}
sender
- .send(Boot {
- compositor,
- clipboard,
- window: window.id(),
- is_daemon: window_settings.is_none(),
- })
+ .send(Boot { compositor })
.ok()
.expect("Send boot event");
- if let Some(window_settings) = window_settings {
- let (sender, _receiver) = oneshot::channel();
-
- proxy.send_action(Action::Window(
- runtime::window::Action::Open(
- window::Id::unique(),
- window_settings,
- sender,
- ),
- ));
- }
-
Ok::<_, graphics::Error>(())
};
@@ -420,6 +409,23 @@ where
);
}
+ fn received_url(
+ &mut self,
+ event_loop: &winit::event_loop::ActiveEventLoop,
+ url: String,
+ ) {
+ self.process_event(
+ event_loop,
+ Event::EventLoopAwakened(
+ winit::event::Event::PlatformSpecific(
+ winit::event::PlatformSpecific::MacOS(
+ winit::event::MacOS::ReceivedUrl(url),
+ ),
+ ),
+ ),
+ );
+ }
+
fn about_to_wait(
&mut self,
event_loop: &winit::event_loop::ActiveEventLoop,
@@ -488,10 +494,13 @@ where
settings,
title,
monitor,
+ on_open,
} => {
let exit_on_close_request =
settings.exit_on_close_request;
+ let visible = settings.visible;
+
#[cfg(target_arch = "wasm32")]
let target =
settings.platform_specific.target.clone();
@@ -505,7 +514,8 @@ where
.or(event_loop
.primary_monitor()),
self.id.clone(),
- ),
+ )
+ .with_visible(false),
)
.expect("Create window");
@@ -561,6 +571,8 @@ where
id,
window,
exit_on_close_request,
+ make_visible: visible,
+ on_open,
},
);
}
@@ -600,20 +612,21 @@ where
struct Boot<C> {
compositor: C,
- clipboard: Clipboard,
- window: winit::window::WindowId,
- is_daemon: bool,
}
+#[derive(Debug)]
enum Event<Message: 'static> {
WindowCreated {
id: window::Id,
window: winit::window::Window,
exit_on_close_request: bool,
+ make_visible: bool,
+ on_open: oneshot::Sender<window::Id>,
},
EventLoopAwakened(winit::event::Event<Message>),
}
+#[derive(Debug)]
enum Control {
ChangeFlow(winit::event_loop::ControlFlow),
Exit,
@@ -622,6 +635,7 @@ enum Control {
settings: window::Settings,
title: String,
monitor: Option<winit::monitor::MonitorHandle>,
+ on_open: oneshot::Sender<window::Id>,
},
}
@@ -630,9 +644,10 @@ async fn run_instance<P, C>(
mut runtime: Runtime<P::Executor, Proxy<P::Message>, Action<P::Message>>,
mut proxy: Proxy<P::Message>,
mut debug: Debug,
- mut boot: oneshot::Receiver<Boot<C>>,
+ boot: oneshot::Receiver<Boot<C>>,
mut event_receiver: mpsc::UnboundedReceiver<Event<Action<P::Message>>>,
mut control_sender: mpsc::UnboundedSender<Control>,
+ is_daemon: bool,
) where
P: Program + 'static,
C: Compositor<Renderer = P::Renderer> + 'static,
@@ -641,14 +656,10 @@ async fn run_instance<P, C>(
use winit::event;
use winit::event_loop::ControlFlow;
- let Boot {
- mut compositor,
- mut clipboard,
- window: boot_window,
- is_daemon,
- } = boot.try_recv().ok().flatten().expect("Receive boot");
+ let Boot { mut compositor } = boot.await.expect("Receive boot");
let mut window_manager = WindowManager::new();
+ let mut is_window_opening = !is_daemon;
let mut events = Vec::new();
let mut messages = Vec::new();
@@ -656,15 +667,29 @@ async fn run_instance<P, C>(
let mut ui_caches = FxHashMap::default();
let mut user_interfaces = ManuallyDrop::new(FxHashMap::default());
+ let mut clipboard = Clipboard::unconnected();
debug.startup_finished();
- 'main: while let Some(event) = event_receiver.next().await {
+ loop {
+ // Empty the queue if possible
+ let event = if let Ok(event) = event_receiver.try_next() {
+ event
+ } else {
+ event_receiver.next().await
+ };
+
+ let Some(event) = event else {
+ break;
+ };
+
match event {
Event::WindowCreated {
id,
window,
exit_on_close_request,
+ make_visible,
+ on_open,
} => {
let window = window_manager.insert(
id,
@@ -689,6 +714,10 @@ async fn run_instance<P, C>(
);
let _ = ui_caches.insert(id, user_interface::Cache::default());
+ if make_visible {
+ window.raw.set_visible(true);
+ }
+
events.push((
id,
core::Event::Window(window::Event::Opened {
@@ -696,6 +725,13 @@ async fn run_instance<P, C>(
size: window.size(),
}),
));
+
+ if clipboard.window_id().is_none() {
+ clipboard = Clipboard::connect(window.raw.clone());
+ }
+
+ let _ = on_open.send(id);
+ is_window_opening = false;
}
Event::EventLoopAwakened(event) => {
match event {
@@ -725,6 +761,7 @@ async fn run_instance<P, C>(
action,
&program,
&mut compositor,
+ &mut events,
&mut messages,
&mut clipboard,
&mut control_sender,
@@ -732,6 +769,7 @@ async fn run_instance<P, C>(
&mut user_interfaces,
&mut window_manager,
&mut ui_caches,
+ &mut is_window_opening,
);
actions += 1;
}
@@ -916,10 +954,14 @@ async fn run_instance<P, C>(
window_event,
winit::event::WindowEvent::Destroyed
)
- && window_id != boot_window
+ && !is_window_opening
&& window_manager.is_empty()
{
- break 'main;
+ control_sender
+ .start_send(Control::Exit)
+ .expect("Send control action");
+
+ continue;
}
let Some((id, window)) =
@@ -933,14 +975,22 @@ async fn run_instance<P, C>(
winit::event::WindowEvent::CloseRequested
) && window.exit_on_close_request
{
- let _ = window_manager.remove(id);
- let _ = user_interfaces.remove(&id);
- let _ = ui_caches.remove(&id);
-
- events.push((
- id,
- core::Event::Window(window::Event::Closed),
- ));
+ run_action(
+ Action::Window(runtime::window::Action::Close(
+ id,
+ )),
+ &program,
+ &mut compositor,
+ &mut events,
+ &mut messages,
+ &mut clipboard,
+ &mut control_sender,
+ &mut debug,
+ &mut user_interfaces,
+ &mut window_manager,
+ &mut ui_caches,
+ &mut is_window_opening,
+ );
} else {
window.state.update(
&window.raw,
@@ -1114,19 +1164,20 @@ fn update<P: Program, E: Executor>(
let task = runtime.enter(|| program.update(message));
debug.update_finished();
- if let Some(stream) = task.into_stream() {
+ if let Some(stream) = runtime::task::into_stream(task) {
runtime.run(stream);
}
}
let subscription = program.subscription();
- runtime.track(subscription.map(Action::Output).into_recipes());
+ runtime.track(subscription::into_recipes(subscription.map(Action::Output)));
}
fn run_action<P, C>(
action: Action<P::Message>,
program: &P,
compositor: &mut C,
+ events: &mut Vec<(window::Id, core::Event)>,
messages: &mut Vec<P::Message>,
clipboard: &mut Clipboard,
control_sender: &mut mpsc::UnboundedSender<Control>,
@@ -1137,6 +1188,7 @@ fn run_action<P, C>(
>,
window_manager: &mut WindowManager<P, C>,
ui_caches: &mut FxHashMap<window::Id, user_interface::Cache>,
+ is_window_opening: &mut bool,
) where
P: Program,
C: Compositor<Renderer = P::Renderer> + 'static,
@@ -1168,14 +1220,30 @@ fn run_action<P, C>(
settings,
title: program.title(id),
monitor,
+ on_open: channel,
})
.expect("Send control action");
- let _ = channel.send(id);
+ *is_window_opening = true;
}
window::Action::Close(id) => {
- let _ = window_manager.remove(id);
let _ = ui_caches.remove(&id);
+ let _ = interfaces.remove(&id);
+
+ if let Some(window) = window_manager.remove(id) {
+ if clipboard.window_id() == Some(window.raw.id()) {
+ *clipboard = window_manager
+ .first()
+ .map(|window| window.raw.clone())
+ .map(Clipboard::connect)
+ .unwrap_or_else(Clipboard::unconnected);
+ }
+
+ events.push((
+ id,
+ core::Event::Window(core::window::Event::Closed),
+ ));
+ }
}
window::Action::GetOldest(channel) => {
let id =
@@ -1235,7 +1303,7 @@ fn run_action<P, C>(
}
}
window::Action::GetPosition(id, channel) => {
- if let Some(window) = window_manager.get_mut(id) {
+ if let Some(window) = window_manager.get(id) {
let position = window
.raw
.inner_position()
@@ -1250,6 +1318,13 @@ fn run_action<P, C>(
let _ = channel.send(position);
}
}
+ window::Action::GetScaleFactor(id, channel) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ let scale_factor = window.raw.scale_factor();
+
+ let _ = channel.send(scale_factor as f32);
+ }
+ }
window::Action::Move(id, position) => {
if let Some(window) = window_manager.get_mut(id) {
window.raw.set_outer_position(
@@ -1360,6 +1435,16 @@ fn run_action<P, C>(
));
}
}
+ window::Action::EnableMousePassthrough(id) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ let _ = window.raw.set_cursor_hittest(false);
+ }
+ }
+ window::Action::DisableMousePassthrough(id) => {
+ if let Some(window) = window_manager.get_mut(id) {
+ let _ = window.raw.set_cursor_hittest(true);
+ }
+ }
},
Action::System(action) => match action {
system::Action::QueryInformation(_channel) => {