Skip to content

Commit

Permalink
quick & dirty close panic fix using dynamic dispatch
Browse files Browse the repository at this point in the history
  • Loading branch information
Friz64 committed Apr 15, 2024
1 parent 62f2a73 commit 0561754
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 12 deletions.
17 changes: 14 additions & 3 deletions crates/bevy_render/src/view/window/mod.rs
Expand Up @@ -12,7 +12,8 @@ use bevy_ecs::{entity::EntityHashMap, prelude::*};
use bevy_utils::warn_once;
use bevy_utils::{default, tracing::debug, HashSet};
use bevy_window::{
CompositeAlphaMode, PresentMode, PrimaryWindow, RawHandleWrapper, Window, WindowClosed,
CompositeAlphaMode, InnerWindowReference, PresentMode, PrimaryWindow, RawHandleWrapper, Window,
WindowClosed,
};
use std::{
ops::{Deref, DerefMut},
Expand Down Expand Up @@ -60,6 +61,7 @@ impl Plugin for WindowRenderPlugin {
}

pub struct ExtractedWindow {
_inner_ref: InnerWindowReference,
/// An entity that contains the components in [`Window`].
pub entity: Entity,
pub handle: RawHandleWrapper,
Expand Down Expand Up @@ -116,11 +118,19 @@ fn extract_windows(
mut extracted_windows: ResMut<ExtractedWindows>,
screenshot_manager: Extract<Res<ScreenshotManager>>,
mut closed: Extract<EventReader<WindowClosed>>,
windows: Extract<Query<(Entity, &Window, &RawHandleWrapper, Option<&PrimaryWindow>)>>,
windows: Extract<
Query<(
Entity,
&Window,
&RawHandleWrapper,
&InnerWindowReference,
Option<&PrimaryWindow>,
)>,
>,
mut removed: Extract<RemovedComponents<RawHandleWrapper>>,
mut window_surfaces: ResMut<WindowSurfaces>,
) {
for (entity, window, handle, primary) in windows.iter() {
for (entity, window, handle, inner_ref, primary) in windows.iter() {
if primary.is_some() {
extracted_windows.primary = Some(entity);
}
Expand All @@ -131,6 +141,7 @@ fn extract_windows(
);

let extracted_window = extracted_windows.entry(entity).or_insert(ExtractedWindow {
_inner_ref: inner_ref.clone(),
entity,
handle: handle.clone(),
physical_width: new_width,
Expand Down
12 changes: 12 additions & 0 deletions crates/bevy_window/src/window.rs
Expand Up @@ -11,6 +11,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
use bevy_utils::tracing::warn;

use crate::CursorIcon;
use std::{any::Any, sync::Arc};

/// Marker [`Component`] for the window considered the primary window.
///
Expand Down Expand Up @@ -88,6 +89,17 @@ impl NormalizedWindowRef {
}
}

pub type InnerWindow = Arc<dyn Any + Send + Sync>;

#[derive(Debug, Clone, Component)]
pub struct InnerWindowReference(#[allow(dead_code)] InnerWindow);

impl InnerWindowReference {
pub fn new(inner_window: InnerWindow) -> InnerWindowReference {
InnerWindowReference(inner_window)
}
}

/// The defining [`Component`] for window entities,
/// storing information about how it should appear and behave.
///
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_winit/src/lib.rs
Expand Up @@ -397,6 +397,7 @@ fn handle_winit_event(
let (_, winit_windows, _, _) = event_writer_system_state.get_mut(app.world_mut());
if visible && runner_state.active != ActiveState::WillSuspend {
for window in winit_windows.windows.values() {
let window = window.downcast_ref::<winit::window::Window>().unwrap();
window.request_redraw();
}
} else {
Expand Down Expand Up @@ -447,6 +448,9 @@ fn handle_winit_event(
// the engine.
if let Some(adapter) = access_kit_adapters.get(&window) {
if let Some(winit_window) = winit_windows.get_window(window) {
let winit_window = winit_window
.downcast_ref::<winit::window::Window>()
.unwrap();
adapter.process_event(winit_window, &event);
}
}
Expand Down
17 changes: 13 additions & 4 deletions crates/bevy_winit/src/system.rs
Expand Up @@ -8,7 +8,8 @@ use bevy_ecs::{
};
use bevy_utils::tracing::{error, info, warn};
use bevy_window::{
RawHandleWrapper, Window, WindowClosed, WindowCreated, WindowMode, WindowResized,
InnerWindowReference, RawHandleWrapper, Window, WindowClosed, WindowCreated, WindowMode,
WindowResized,
};

use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
Expand Down Expand Up @@ -57,7 +58,7 @@ pub fn create_windows<F: QueryFilter + 'static>(
entity
);

let winit_window = winit_windows.create_window(
let inner_winit_window = winit_windows.create_window(
event_loop,
entity,
&window,
Expand All @@ -66,6 +67,10 @@ pub fn create_windows<F: QueryFilter + 'static>(
&accessibility_requested,
);

let winit_window = inner_winit_window
.downcast_ref::<winit::window::Window>()
.unwrap();

if let Some(theme) = winit_window.theme() {
window.window_theme = Some(convert_winit_theme(theme));
}
Expand All @@ -81,7 +86,8 @@ pub fn create_windows<F: QueryFilter + 'static>(
})
.insert(CachedWindow {
window: window.clone(),
});
})
.insert(InnerWindowReference::new(inner_winit_window.clone()));

#[cfg(target_arch = "wasm32")]
{
Expand Down Expand Up @@ -135,7 +141,10 @@ pub(crate) fn changed_windows(
mut window_resized: EventWriter<WindowResized>,
) {
for (entity, mut window, mut cache) in &mut changed_windows {
let Some(winit_window) = winit_windows.get_window(entity) else {
let Some(winit_window) = winit_windows
.get_window(entity)
.and_then(|w| w.downcast_ref::<winit::window::Window>())
else {
continue;
};

Expand Down
12 changes: 7 additions & 5 deletions crates/bevy_winit/src/winit_windows.rs
Expand Up @@ -14,13 +14,15 @@ use crate::{
accessibility::{prepare_accessibility_for_window, AccessKitAdapters, WinitActionHandlers},
converters::{convert_enabled_buttons, convert_window_level, convert_window_theme},
};
use bevy_window::InnerWindow;
use std::sync::Arc;

/// A resource mapping window entities to their `winit`-backend [`Window`](winit::window::Window)
/// states.
#[derive(Debug, Default)]
pub struct WinitWindows {
/// Stores [`winit`] windows by window identifier.
pub windows: HashMap<winit::window::WindowId, winit::window::Window>,
pub windows: HashMap<winit::window::WindowId, InnerWindow>,
/// Maps entities to `winit` window identifiers.
pub entity_to_winit: EntityHashMap<winit::window::WindowId>,
/// Maps `winit` window identifiers to entities.
Expand All @@ -41,7 +43,7 @@ impl WinitWindows {
adapters: &mut AccessKitAdapters,
handlers: &mut WinitActionHandlers,
accessibility_requested: &AccessibilityRequested,
) -> &winit::window::Window {
) -> &InnerWindow {
let mut winit_window_builder = winit::window::WindowBuilder::new();

// Due to a UIA limitation, winit windows need to be invisible for the
Expand Down Expand Up @@ -240,12 +242,12 @@ impl WinitWindows {

self.windows
.entry(winit_window.id())
.insert(winit_window)
.insert(Arc::new(winit_window))
.into_mut()
}

/// Get the winit window that is associated with our entity.
pub fn get_window(&self, entity: Entity) -> Option<&winit::window::Window> {
pub fn get_window(&self, entity: Entity) -> Option<&InnerWindow> {
self.entity_to_winit
.get(&entity)
.and_then(|winit_id| self.windows.get(winit_id))
Expand All @@ -261,7 +263,7 @@ impl WinitWindows {
/// Remove a window from winit.
///
/// This should mostly just be called when the window is closing.
pub fn remove_window(&mut self, entity: Entity) -> Option<winit::window::Window> {
pub fn remove_window(&mut self, entity: Entity) -> Option<InnerWindow> {
let winit_id = self.entity_to_winit.remove(&entity)?;
self.winit_to_entity.remove(&winit_id);
self.windows.remove(&winit_id)
Expand Down

0 comments on commit 0561754

Please sign in to comment.