1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 05:40:03 -04:00

Upgrade winit to 0.30.2 (#4849)

* Closes https://github.com/emilk/egui/issues/1918
* Closes https://github.com/emilk/egui/issues/4437
* Closes https://github.com/emilk/egui/issues/4709
* [x] I have followed the instructions in the PR template

Hiya,

I need new winit for a specific fix for a android_native_actvity. There
are already two PRs, but both don't seem to have a lot of movement, or
are entirely complete:

https://github.com/emilk/egui/pull/4466
Seems to have gone stale & is missing some bits.

https://github.com/emilk/egui/pull/4702
Also seems stale (if less so), and is missing a refactor to
run_on_demand. I also *think* the accesskit integration has a mistake
and can't be enabled. I've marked them as a co-author on this as I
started from this branch. (I think! Haven't done that on git before...).

Sorry for the wall of text but just dumping some details / thoughts
here:

- There's an issue with creating child windows in winit 0.30.1 and up on
macOS. The multiple_viewports, "create immediate viewport" example
crashes on anything later 0.30.1, with a stack overflow in unsafe code.
I've create [a winit
issue](https://github.com/rust-windowing/winit/issues/3800), it *might*
already be fixed in 0.31.0 but I can't test as 0.31 will likely require
another refactoring. For now I have just pinned things to 0.30.0 exatly.

- Winit has deprecated run_on_demand, instead requiring the
ApplicationHandler interface. In 0.31.0 run_on_demand is removed. I've
refactored both the integration and the WinitApp trait to follow this
pattern. I've left user_events a bit more opaque, as it seems 0.31.0 is
doing a rework of UserEvents too.

- I've used the new lazy init approach for access kit from this branch
https://github.com/mwcampbell/egui/tree/accesskit-new-lazy-init and
marked Matt as co-author, thanks Matt!

- There was very similair but not quite the same code for run_and_return
and run_and_exit. I've merged them, but looking at the github issues
graveyard it seems vey finnicky. I *hope* this is more robust than
before but it's a bit scary.

- when receiving new_events this also used to check the redraw timing
dictionary. That doesn't seem necesarry so left this out, but that is a
slight behaviour change?

- I have reeneabled serial_windows on macOS. I wondered whether it was
fixed after this PR and does seem to be! However, even before this PR it
seems to work, so maybe winit has sorted things out before that...
Windows also works fine now without the extra hack.

- I've done a very basic test of AccessKit on Windows and screen reader
seems ok but I'm really not knowleadgable enough to say whether it's all
good or not.

- I've tested cargo tests & all examples on Windows & macOS, and ran a
basic Android app. Still, testing native platforms is wel... hard so if
anyone can test linux / iOs / older mac versions / windows 10 would
probably be a good idea!

- For consistencys sake I've made all event like functions in WinitApp
return a `Result<EventResult>`. There's quite a bit of Ok-wrapping now,
maybe too annoying? Not sure.

Thank you for having a look!

# Tested on
* [x] macOS
* [x] Windows
* [x] Wayland (thanks [SiebenCorgie](https://github.com/SiebenCorgie))
* [x] X11 (thanks
[crumblingstatue](https://github.com/crumblingstatue)!,
[SiebenCorgie](https://github.com/SiebenCorgie))


# TODO
* [x] Fix "follow system theme" not working on initial startup (winit
issue, pinning to 0.30.2 for now).
* [x] Fix `request_repaint_after`

---------

Co-authored-by: mwcampbell <mattcampbell@pobox.com>
Co-authored-by: j-axa <josef.axa@gmail.com>
Co-authored-by: DataTriny <datatriny@gmail.com>
Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
Arthur Brussee
2024-07-31 07:43:16 +00:00
committed by GitHub
parent 37b1e1504d
commit 6f2f006885
25 changed files with 1313 additions and 1165 deletions

View File

@@ -31,7 +31,7 @@ pub(crate) use profiling_scopes::*;
use winit::{
dpi::{PhysicalPosition, PhysicalSize},
event::ElementState,
event_loop::EventLoopWindowTarget,
event_loop::ActiveEventLoop,
window::{CursorGrabMode, Window, WindowButtons, WindowLevel},
};
@@ -158,16 +158,15 @@ impl State {
}
#[cfg(feature = "accesskit")]
pub fn init_accesskit<T: From<accesskit_winit::ActionRequestEvent> + Send>(
pub fn init_accesskit<T: From<accesskit_winit::Event> + Send>(
&mut self,
window: &Window,
event_loop_proxy: winit::event_loop::EventLoopProxy<T>,
initial_tree_update_factory: impl 'static + FnOnce() -> accesskit::TreeUpdate + Send,
) {
crate::profile_function!();
self.accesskit = Some(accesskit_winit::Adapter::new(
self.accesskit = Some(accesskit_winit::Adapter::with_event_loop_proxy(
window,
initial_tree_update_factory,
event_loop_proxy,
));
}
@@ -263,7 +262,7 @@ impl State {
crate::profile_function!(short_window_event_description(event));
#[cfg(feature = "accesskit")]
if let Some(accesskit) = &self.accesskit {
if let Some(accesskit) = self.accesskit.as_mut() {
accesskit.process_event(window, event);
}
@@ -474,13 +473,14 @@ impl State {
// Things we completely ignore:
WindowEvent::ActivationTokenDone { .. }
| WindowEvent::AxisMotion { .. }
| WindowEvent::SmartMagnify { .. }
| WindowEvent::TouchpadRotate { .. } => EventResponse {
| WindowEvent::DoubleTapGesture { .. }
| WindowEvent::RotationGesture { .. }
| WindowEvent::PanGesture { .. } => EventResponse {
repaint: false,
consumed: false,
},
WindowEvent::TouchpadMagnify { delta, .. } => {
WindowEvent::PinchGesture { delta, .. } => {
// Positive delta values indicate magnification (zooming in).
// Negative delta values indicate shrinking (zooming out).
let zoom_factor = (*delta as f32).exp();
@@ -859,7 +859,7 @@ impl State {
}
#[cfg(feature = "accesskit")]
if let Some(accesskit) = self.accesskit.as_ref() {
if let Some(accesskit) = self.accesskit.as_mut() {
if let Some(update) = accesskit_update {
crate::profile_scope!("accesskit");
accesskit.update_if_active(|| update);
@@ -880,7 +880,7 @@ impl State {
if let Some(winit_cursor_icon) = translate_cursor(cursor_icon) {
window.set_cursor_visible(true);
window.set_cursor_icon(winit_cursor_icon);
window.set_cursor(winit_cursor_icon);
} else {
window.set_cursor_visible(false);
}
@@ -1510,28 +1510,25 @@ fn process_viewport_command(
///
/// # Errors
/// Possible causes of error include denied permission, incompatible system, and lack of memory.
pub fn create_window<T>(
pub fn create_window(
egui_ctx: &egui::Context,
event_loop: &EventLoopWindowTarget<T>,
event_loop: &ActiveEventLoop,
viewport_builder: &ViewportBuilder,
) -> Result<Window, winit::error::OsError> {
crate::profile_function!();
let window_builder =
create_winit_window_builder(egui_ctx, event_loop, viewport_builder.clone());
let window = {
crate::profile_scope!("WindowBuilder::build");
window_builder.build(event_loop)?
};
let window_attributes =
create_winit_window_attributes(egui_ctx, event_loop, viewport_builder.clone());
let window = event_loop.create_window(window_attributes)?;
apply_viewport_builder_to_window(egui_ctx, &window, viewport_builder);
Ok(window)
}
pub fn create_winit_window_builder<T>(
pub fn create_winit_window_attributes(
egui_ctx: &egui::Context,
event_loop: &EventLoopWindowTarget<T>,
event_loop: &ActiveEventLoop,
viewport_builder: ViewportBuilder,
) -> winit::window::WindowBuilder {
) -> winit::window::WindowAttributes {
crate::profile_function!();
// We set sizes and positions in egui:s own ui points, which depends on the egui
@@ -1590,7 +1587,7 @@ pub fn create_winit_window_builder<T>(
clamp_size_to_monitor_size: _, // Handled in `viewport_builder` in `epi_integration.rs`
} = viewport_builder;
let mut window_builder = winit::window::WindowBuilder::new()
let mut window_attributes = winit::window::WindowAttributes::default()
.with_title(title.unwrap_or_else(|| "egui window".to_owned()))
.with_transparent(transparent.unwrap_or(false))
.with_decorations(decorations.unwrap_or(true))
@@ -1621,28 +1618,28 @@ pub fn create_winit_window_builder<T>(
.with_active(active.unwrap_or(true));
if let Some(size) = inner_size {
window_builder = window_builder.with_inner_size(PhysicalSize::new(
window_attributes = window_attributes.with_inner_size(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
));
}
if let Some(size) = min_inner_size {
window_builder = window_builder.with_min_inner_size(PhysicalSize::new(
window_attributes = window_attributes.with_min_inner_size(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
));
}
if let Some(size) = max_inner_size {
window_builder = window_builder.with_max_inner_size(PhysicalSize::new(
window_attributes = window_attributes.with_max_inner_size(PhysicalSize::new(
pixels_per_point * size.x,
pixels_per_point * size.y,
));
}
if let Some(pos) = position {
window_builder = window_builder.with_position(PhysicalPosition::new(
window_attributes = window_attributes.with_position(PhysicalPosition::new(
pixels_per_point * pos.x,
pixels_per_point * pos.y,
));
@@ -1650,61 +1647,61 @@ pub fn create_winit_window_builder<T>(
if let Some(icon) = icon {
let winit_icon = to_winit_icon(&icon);
window_builder = window_builder.with_window_icon(winit_icon);
window_attributes = window_attributes.with_window_icon(winit_icon);
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
if let Some(app_id) = _app_id {
use winit::platform::wayland::WindowBuilderExtWayland as _;
window_builder = window_builder.with_name(app_id, "");
use winit::platform::wayland::WindowAttributesExtWayland as _;
window_attributes = window_attributes.with_name(app_id, "");
}
#[cfg(all(feature = "x11", target_os = "linux"))]
{
if let Some(window_type) = _window_type {
use winit::platform::x11::WindowBuilderExtX11 as _;
use winit::platform::x11::XWindowType;
window_builder = window_builder.with_x11_window_type(vec![match window_type {
egui::X11WindowType::Normal => XWindowType::Normal,
egui::X11WindowType::Utility => XWindowType::Utility,
egui::X11WindowType::Dock => XWindowType::Dock,
egui::X11WindowType::Desktop => XWindowType::Desktop,
egui::X11WindowType::Toolbar => XWindowType::Toolbar,
egui::X11WindowType::Menu => XWindowType::Menu,
egui::X11WindowType::Splash => XWindowType::Splash,
egui::X11WindowType::Dialog => XWindowType::Dialog,
egui::X11WindowType::DropdownMenu => XWindowType::DropdownMenu,
egui::X11WindowType::PopupMenu => XWindowType::PopupMenu,
egui::X11WindowType::Tooltip => XWindowType::Tooltip,
egui::X11WindowType::Notification => XWindowType::Notification,
egui::X11WindowType::Combo => XWindowType::Combo,
egui::X11WindowType::Dnd => XWindowType::Dnd,
use winit::platform::x11::WindowAttributesExtX11 as _;
use winit::platform::x11::WindowType;
window_attributes = window_attributes.with_x11_window_type(vec![match window_type {
egui::X11WindowType::Normal => WindowType::Normal,
egui::X11WindowType::Utility => WindowType::Utility,
egui::X11WindowType::Dock => WindowType::Dock,
egui::X11WindowType::Desktop => WindowType::Desktop,
egui::X11WindowType::Toolbar => WindowType::Toolbar,
egui::X11WindowType::Menu => WindowType::Menu,
egui::X11WindowType::Splash => WindowType::Splash,
egui::X11WindowType::Dialog => WindowType::Dialog,
egui::X11WindowType::DropdownMenu => WindowType::DropdownMenu,
egui::X11WindowType::PopupMenu => WindowType::PopupMenu,
egui::X11WindowType::Tooltip => WindowType::Tooltip,
egui::X11WindowType::Notification => WindowType::Notification,
egui::X11WindowType::Combo => WindowType::Combo,
egui::X11WindowType::Dnd => WindowType::Dnd,
}]);
}
}
#[cfg(target_os = "windows")]
{
use winit::platform::windows::WindowBuilderExtWindows as _;
use winit::platform::windows::WindowAttributesExtWindows as _;
if let Some(enable) = _drag_and_drop {
window_builder = window_builder.with_drag_and_drop(enable);
window_attributes = window_attributes.with_drag_and_drop(enable);
}
if let Some(show) = _taskbar {
window_builder = window_builder.with_skip_taskbar(!show);
window_attributes = window_attributes.with_skip_taskbar(!show);
}
}
#[cfg(target_os = "macos")]
{
use winit::platform::macos::WindowBuilderExtMacOS as _;
window_builder = window_builder
use winit::platform::macos::WindowAttributesExtMacOS as _;
window_attributes = window_attributes
.with_title_hidden(!_title_shown.unwrap_or(true))
.with_titlebar_buttons_hidden(!_titlebar_buttons_shown.unwrap_or(true))
.with_titlebar_transparent(!_titlebar_shown.unwrap_or(true))
.with_fullsize_content_view(_fullsize_content_view.unwrap_or(false));
}
window_builder
window_attributes
}
fn to_winit_icon(icon: &egui::IconData) -> Option<winit::window::Icon> {
@@ -1774,38 +1771,23 @@ pub fn apply_viewport_builder_to_window(
// ---------------------------------------------------------------------------
/// Short and fast description of an event.
/// Short and fast description of a device event.
/// Useful for logging and profiling.
pub fn short_generic_event_description<T>(event: &winit::event::Event<T>) -> &'static str {
use winit::event::{DeviceEvent, Event, StartCause};
pub fn short_device_event_description(event: &winit::event::DeviceEvent) -> &'static str {
use winit::event::DeviceEvent;
match event {
Event::AboutToWait => "Event::AboutToWait",
Event::LoopExiting => "Event::LoopExiting",
Event::Suspended => "Event::Suspended",
Event::Resumed => "Event::Resumed",
Event::MemoryWarning => "Event::MemoryWarning",
Event::UserEvent(_) => "UserEvent",
Event::DeviceEvent { event, .. } => match event {
DeviceEvent::Added { .. } => "DeviceEvent::Added",
DeviceEvent::Removed { .. } => "DeviceEvent::Removed",
DeviceEvent::MouseMotion { .. } => "DeviceEvent::MouseMotion",
DeviceEvent::MouseWheel { .. } => "DeviceEvent::MouseWheel",
DeviceEvent::Motion { .. } => "DeviceEvent::Motion",
DeviceEvent::Button { .. } => "DeviceEvent::Button",
DeviceEvent::Key { .. } => "DeviceEvent::Key",
},
Event::NewEvents(start_cause) => match start_cause {
StartCause::ResumeTimeReached { .. } => "NewEvents::ResumeTimeReached",
StartCause::WaitCancelled { .. } => "NewEvents::WaitCancelled",
StartCause::Poll => "NewEvents::Poll",
StartCause::Init => "NewEvents::Init",
},
Event::WindowEvent { event, .. } => short_window_event_description(event),
DeviceEvent::Added { .. } => "DeviceEvent::Added",
DeviceEvent::Removed { .. } => "DeviceEvent::Removed",
DeviceEvent::MouseMotion { .. } => "DeviceEvent::MouseMotion",
DeviceEvent::MouseWheel { .. } => "DeviceEvent::MouseWheel",
DeviceEvent::Motion { .. } => "DeviceEvent::Motion",
DeviceEvent::Button { .. } => "DeviceEvent::Button",
DeviceEvent::Key { .. } => "DeviceEvent::Key",
}
}
/// Short and fast description of an event.
/// Short and fast description of a window event.
/// Useful for logging and profiling.
pub fn short_window_event_description(event: &winit::event::WindowEvent) -> &'static str {
use winit::event::WindowEvent;
@@ -1828,16 +1810,17 @@ pub fn short_window_event_description(event: &winit::event::WindowEvent) -> &'st
WindowEvent::CursorLeft { .. } => "WindowEvent::CursorLeft",
WindowEvent::MouseWheel { .. } => "WindowEvent::MouseWheel",
WindowEvent::MouseInput { .. } => "WindowEvent::MouseInput",
WindowEvent::TouchpadMagnify { .. } => "WindowEvent::TouchpadMagnify",
WindowEvent::PinchGesture { .. } => "WindowEvent::PinchGesture",
WindowEvent::RedrawRequested { .. } => "WindowEvent::RedrawRequested",
WindowEvent::SmartMagnify { .. } => "WindowEvent::SmartMagnify",
WindowEvent::TouchpadRotate { .. } => "WindowEvent::TouchpadRotate",
WindowEvent::DoubleTapGesture { .. } => "WindowEvent::DoubleTapGesture",
WindowEvent::RotationGesture { .. } => "WindowEvent::RotationGesture",
WindowEvent::TouchpadPressure { .. } => "WindowEvent::TouchpadPressure",
WindowEvent::AxisMotion { .. } => "WindowEvent::AxisMotion",
WindowEvent::Touch { .. } => "WindowEvent::Touch",
WindowEvent::ScaleFactorChanged { .. } => "WindowEvent::ScaleFactorChanged",
WindowEvent::ThemeChanged { .. } => "WindowEvent::ThemeChanged",
WindowEvent::Occluded { .. } => "WindowEvent::Occluded",
WindowEvent::PanGesture { .. } => "WindowEvent::PanGesture",
}
}

View File

@@ -50,10 +50,10 @@ impl WindowSettings {
self.inner_size_points
}
pub fn initialize_viewport_builder<E>(
pub fn initialize_viewport_builder(
&self,
egui_zoom_factor: f32,
event_loop: &winit::event_loop::EventLoopWindowTarget<E>,
event_loop: &winit::event_loop::ActiveEventLoop,
mut viewport_builder: ViewportBuilder,
) -> ViewportBuilder {
crate::profile_function!();
@@ -110,10 +110,10 @@ impl WindowSettings {
}
}
pub fn clamp_position_to_monitors<E>(
pub fn clamp_position_to_monitors(
&mut self,
egui_zoom_factor: f32,
event_loop: &winit::event_loop::EventLoopWindowTarget<E>,
event_loop: &winit::event_loop::ActiveEventLoop,
) {
// If the app last ran on two monitors and only one is now connected, then
// the given position is invalid.
@@ -137,9 +137,9 @@ impl WindowSettings {
}
}
fn find_active_monitor<E>(
fn find_active_monitor(
egui_zoom_factor: f32,
event_loop: &winit::event_loop::EventLoopWindowTarget<E>,
event_loop: &winit::event_loop::ActiveEventLoop,
window_size_pts: egui::Vec2,
position_px: &egui::Pos2,
) -> Option<winit::monitor::MonitorHandle> {
@@ -172,9 +172,9 @@ fn find_active_monitor<E>(
Some(active_monitor)
}
fn clamp_pos_to_monitors<E>(
fn clamp_pos_to_monitors(
egui_zoom_factor: f32,
event_loop: &winit::event_loop::EventLoopWindowTarget<E>,
event_loop: &winit::event_loop::ActiveEventLoop,
window_size_pts: egui::Vec2,
position_px: &mut egui::Pos2,
) {