Update winit to 0.29.4

This commit is contained in:
Héctor Ramón Jiménez 2023-12-15 13:15:44 +01:00
parent dd249a1d11
commit e819c2390b
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
19 changed files with 654 additions and 846 deletions

View file

@ -118,7 +118,10 @@ where
let mut debug = Debug::new();
debug.startup_started();
let event_loop = EventLoopBuilder::with_user_event().build();
let event_loop = EventLoopBuilder::with_user_event()
.build()
.expect("Create event loop");
let proxy = event_loop.create_proxy();
let runtime = {
@ -210,78 +213,64 @@ where
let mut context = task::Context::from_waker(task::noop_waker_ref());
platform::run(event_loop, move |event, window_target, control_flow| {
use winit::event_loop::ControlFlow;
if let ControlFlow::ExitWithCode(_) = control_flow {
let _ = event_loop.run(move |event, event_loop| {
if event_loop.exiting() {
return;
}
let event = match event {
winit::event::Event::WindowEvent {
event:
winit::event::WindowEvent::ScaleFactorChanged {
new_inner_size,
..
},
window_id,
} => Some(winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::Resized(*new_inner_size),
window_id,
}),
_ => event.to_static(),
};
event_sender
.start_send(Event::EventLoopAwakened(event))
.expect("Send event");
if let Some(event) = event {
event_sender
.start_send(Event::EventLoopAwakened(event))
.expect("Send event");
loop {
let poll = instance.as_mut().poll(&mut context);
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) => {
event_loop.set_control_flow(flow);
}
Control::CreateWindow {
id,
settings,
title,
monitor,
} => {
let exit_on_close_request =
settings.exit_on_close_request;
match poll {
task::Poll::Pending => match control_receiver.try_next() {
Ok(Some(control)) => match control {
Control::ChangeFlow(flow) => {
*control_flow = flow;
}
Control::CreateWindow {
id,
settings,
title,
monitor,
} => {
let exit_on_close_request =
settings.exit_on_close_request;
let window = conversion::window_settings(
settings, &title, monitor, None,
)
.build(event_loop)
.expect("Failed to build window");
let window = conversion::window_settings(
settings, &title, monitor, None,
)
.build(window_target)
.expect("Failed to build window");
event_sender
.start_send(Event::WindowCreated {
id,
window,
exit_on_close_request,
})
.expect("Send event");
}
},
_ => {
break;
event_sender
.start_send(Event::WindowCreated {
id,
window,
exit_on_close_request,
})
.expect("Send event");
}
Control::Exit => {
event_loop.exit();
}
},
task::Poll::Ready(_) => {
*control_flow = ControlFlow::Exit;
_ => {
break;
}
};
}
},
task::Poll::Ready(_) => {
event_loop.exit();
break;
}
};
}
})
});
Ok(())
}
enum Event<Message: 'static> {
@ -290,11 +279,12 @@ enum Event<Message: 'static> {
window: winit::window::Window,
exit_on_close_request: bool,
},
EventLoopAwakened(winit::event::Event<'static, Message>),
EventLoopAwakened(winit::event::Event<Message>),
}
enum Control {
ChangeFlow(winit::event_loop::ControlFlow),
Exit,
CreateWindow {
id: window::Id,
settings: window::Settings,
@ -427,184 +417,6 @@ async fn run_instance<A, E, C>(
| event::StartCause::ResumeTimeReached { .. }
);
}
event::Event::MainEventsCleared => {
debug.event_processing_started();
let mut uis_stale = false;
for (id, window) in window_manager.iter_mut() {
let mut window_events = vec![];
events.retain(|(window_id, event)| {
if *window_id == Some(id) || window_id.is_none()
{
window_events.push(event.clone());
false
} else {
true
}
});
if !redraw_pending
&& window_events.is_empty()
&& messages.is_empty()
{
continue;
}
let (ui_state, statuses) = user_interfaces
.get_mut(&id)
.expect("Get user interface")
.update(
&window_events,
window.state.cursor(),
&mut window.renderer,
&mut clipboard,
&mut messages,
);
if !uis_stale {
uis_stale = matches!(
ui_state,
user_interface::State::Outdated
);
}
for (event, status) in window_events
.into_iter()
.zip(statuses.into_iter())
{
runtime.broadcast(event, status);
}
}
debug.event_processing_finished();
// TODO mw application update returns which window IDs to update
if !messages.is_empty() || uis_stale {
let mut cached_interfaces: HashMap<
window::Id,
user_interface::Cache,
> = ManuallyDrop::into_inner(user_interfaces)
.drain()
.map(|(id, ui)| (id, ui.into_cache()))
.collect();
// Update application
update(
&mut application,
&mut compositor,
&mut runtime,
&mut clipboard,
&mut control_sender,
&mut proxy,
&mut debug,
&mut messages,
&mut window_manager,
&mut cached_interfaces,
);
// we must synchronize all window states with application state after an
// application update since we don't know what changed
for (id, window) in window_manager.iter_mut() {
window.state.synchronize(
&application,
id,
&window.raw,
);
}
// rebuild UIs with the synchronized states
user_interfaces =
ManuallyDrop::new(build_user_interfaces(
&application,
&mut debug,
&mut window_manager,
cached_interfaces,
));
}
debug.draw_started();
for (id, window) in window_manager.iter_mut() {
// TODO: Avoid redrawing all the time by forcing widgets to
// request redraws on state changes
//
// Then, we can use the `interface_state` here to decide if a redraw
// is needed right away, or simply wait until a specific time.
let redraw_event = core::Event::Window(
id,
window::Event::RedrawRequested(Instant::now()),
);
let cursor = window.state.cursor();
let ui = user_interfaces
.get_mut(&id)
.expect("Get user interface");
let (ui_state, _) = ui.update(
&[redraw_event.clone()],
cursor,
&mut window.renderer,
&mut clipboard,
&mut messages,
);
let new_mouse_interaction = {
let state = &window.state;
ui.draw(
&mut window.renderer,
state.theme(),
&renderer::Style {
text_color: state.text_color(),
},
cursor,
)
};
if new_mouse_interaction != window.mouse_interaction
{
window.raw.set_cursor_icon(
conversion::mouse_interaction(
new_mouse_interaction,
),
);
window.mouse_interaction =
new_mouse_interaction;
}
// TODO once widgets can request to be redrawn, we can avoid always requesting a
// redraw
window.raw.request_redraw();
runtime.broadcast(
redraw_event.clone(),
core::event::Status::Ignored,
);
let _ = control_sender.start_send(
Control::ChangeFlow(match ui_state {
user_interface::State::Updated {
redraw_request: Some(redraw_request),
} => match redraw_request {
window::RedrawRequest::NextFrame => {
ControlFlow::Poll
}
window::RedrawRequest::At(at) => {
ControlFlow::WaitUntil(at)
}
},
_ => ControlFlow::Wait,
}),
);
}
redraw_pending = false;
debug.draw_finished();
}
event::Event::PlatformSpecific(
event::PlatformSpecific::MacOS(
event::MacOS::ReceivedUrl(url),
@ -624,7 +436,11 @@ async fn run_instance<A, E, C>(
event::Event::UserEvent(message) => {
messages.push(message);
}
event::Event::RedrawRequested(id) => {
event::Event::WindowEvent {
window_id: id,
event: event::WindowEvent::RedrawRequested,
..
} => {
let Some((id, window)) =
window_manager.get_mut_alias(id)
else {
@ -775,6 +591,163 @@ async fn run_instance<A, E, C>(
}
}
}
debug.event_processing_started();
let mut uis_stale = false;
for (id, window) in window_manager.iter_mut() {
let mut window_events = vec![];
events.retain(|(window_id, event)| {
if *window_id == Some(id) || window_id.is_none() {
window_events.push(event.clone());
false
} else {
true
}
});
if !redraw_pending
&& window_events.is_empty()
&& messages.is_empty()
{
continue;
}
let (ui_state, statuses) = user_interfaces
.get_mut(&id)
.expect("Get user interface")
.update(
&window_events,
window.state.cursor(),
&mut window.renderer,
&mut clipboard,
&mut messages,
);
if !uis_stale {
uis_stale = matches!(ui_state, user_interface::State::Outdated);
}
for (event, status) in
window_events.into_iter().zip(statuses.into_iter())
{
runtime.broadcast(event, status);
}
}
debug.event_processing_finished();
// TODO mw application update returns which window IDs to update
if !messages.is_empty() || uis_stale {
let mut cached_interfaces: HashMap<
window::Id,
user_interface::Cache,
> = ManuallyDrop::into_inner(user_interfaces)
.drain()
.map(|(id, ui)| (id, ui.into_cache()))
.collect();
// Update application
update(
&mut application,
&mut compositor,
&mut runtime,
&mut clipboard,
&mut control_sender,
&mut proxy,
&mut debug,
&mut messages,
&mut window_manager,
&mut cached_interfaces,
);
// we must synchronize all window states with application state after an
// application update since we don't know what changed
for (id, window) in window_manager.iter_mut() {
window.state.synchronize(&application, id, &window.raw);
}
// rebuild UIs with the synchronized states
user_interfaces = ManuallyDrop::new(build_user_interfaces(
&application,
&mut debug,
&mut window_manager,
cached_interfaces,
));
}
debug.draw_started();
for (id, window) in window_manager.iter_mut() {
// TODO: Avoid redrawing all the time by forcing widgets to
// request redraws on state changes
//
// Then, we can use the `interface_state` here to decide if a redraw
// is needed right away, or simply wait until a specific time.
let redraw_event = core::Event::Window(
id,
window::Event::RedrawRequested(Instant::now()),
);
let cursor = window.state.cursor();
let ui = user_interfaces.get_mut(&id).expect("Get user interface");
let (ui_state, _) = ui.update(
&[redraw_event.clone()],
cursor,
&mut window.renderer,
&mut clipboard,
&mut messages,
);
let new_mouse_interaction = {
let state = &window.state;
ui.draw(
&mut window.renderer,
state.theme(),
&renderer::Style {
text_color: state.text_color(),
},
cursor,
)
};
if new_mouse_interaction != window.mouse_interaction {
window.raw.set_cursor_icon(conversion::mouse_interaction(
new_mouse_interaction,
));
window.mouse_interaction = new_mouse_interaction;
}
// TODO once widgets can request to be redrawn, we can avoid always requesting a
// redraw
window.raw.request_redraw();
runtime
.broadcast(redraw_event.clone(), core::event::Status::Ignored);
let _ = control_sender.start_send(Control::ChangeFlow(
match ui_state {
user_interface::State::Updated {
redraw_request: Some(redraw_request),
} => match redraw_request {
window::RedrawRequest::NextFrame => ControlFlow::Poll,
window::RedrawRequest::At(at) => {
ControlFlow::WaitUntil(at)
}
},
_ => ControlFlow::Wait,
},
));
}
redraw_pending = false;
debug.draw_finished();
}
let _ = ManuallyDrop::into_inner(user_interfaces);
@ -901,16 +874,12 @@ fn run_command<A, C, E>(
.expect("Send control action");
}
window::Action::Close(id) => {
use winit::event_loop::ControlFlow;
let _ = window_manager.remove(id);
let _ = ui_caches.remove(&id);
if window_manager.is_empty() {
control_sender
.start_send(Control::ChangeFlow(
ControlFlow::ExitWithCode(0),
))
.start_send(Control::Exit)
.expect("Send control action");
}
}
@ -921,10 +890,12 @@ fn run_command<A, C, E>(
}
window::Action::Resize(id, size) => {
if let Some(window) = window_manager.get_mut(id) {
window.raw.set_inner_size(winit::dpi::LogicalSize {
width: size.width,
height: size.height,
});
let _ = window.raw.request_inner_size(
winit::dpi::LogicalSize {
width: size.width,
height: size.height,
},
);
}
}
window::Action::FetchSize(id, callback) => {
@ -1153,60 +1124,20 @@ where
/// Returns true if the provided event should cause an [`Application`] to
/// exit.
pub fn user_force_quit(
event: &winit::event::WindowEvent<'_>,
_modifiers: winit::event::ModifiersState,
event: &winit::event::WindowEvent,
_modifiers: winit::keyboard::ModifiersState,
) -> bool {
match event {
#[cfg(target_os = "macos")]
winit::event::WindowEvent::KeyboardInput {
input:
winit::event::KeyboardInput {
virtual_keycode: Some(winit::event::VirtualKeyCode::Q),
event:
winit::event::KeyEvent {
logical_key: winit::keyboard::Key::Character(c),
state: winit::event::ElementState::Pressed,
..
},
..
} if _modifiers.logo() => true,
} if c == "q" && _modifiers.super_key() => true,
_ => false,
}
}
#[cfg(not(target_arch = "wasm32"))]
mod platform {
pub fn run<T, F>(
mut event_loop: winit::event_loop::EventLoop<T>,
event_handler: F,
) -> Result<(), super::Error>
where
F: 'static
+ FnMut(
winit::event::Event<'_, T>,
&winit::event_loop::EventLoopWindowTarget<T>,
&mut winit::event_loop::ControlFlow,
),
{
use winit::platform::run_return::EventLoopExtRunReturn;
let _ = event_loop.run_return(event_handler);
Ok(())
}
}
#[cfg(target_arch = "wasm32")]
mod platform {
pub fn run<T, F>(
event_loop: winit::event_loop::EventLoop<T>,
event_handler: F,
) -> !
where
F: 'static
+ FnMut(
winit::event::Event<'_, T>,
&winit::event_loop::EventLoopWindowTarget<T>,
&mut winit::event_loop::ControlFlow,
),
{
event_loop.run(event_handler)
}
}