Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bevy_winit(emit raw winit events) #15884

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extern crate alloc;
use bevy_derive::Deref;
use bevy_window::{RawHandleWrapperHolder, WindowEvent};
use core::marker::PhantomData;
use winit::event_loop::EventLoop;
use winit::{event_loop::EventLoop, window::WindowId};

use bevy_a11y::AccessibilityRequested;
use bevy_app::{App, Last, Plugin};
Expand Down Expand Up @@ -117,6 +117,7 @@ impl<T: Event> Plugin for WinitPlugin<T> {
app.init_non_send_resource::<WinitWindows>()
.init_resource::<WinitMonitors>()
.init_resource::<WinitSettings>()
.add_event::<RawWinitWindowEvent>()
.set_runner(winit_runner::<T>)
.add_systems(
Last,
Expand Down Expand Up @@ -149,6 +150,21 @@ impl<T: Event> Plugin for WinitPlugin<T> {
#[derive(Debug, Default, Clone, Copy, Event)]
pub struct WakeUp;

/// The original window event as produced by winit. This is meant as an escape
/// hatch for power users that wish add custom winit integrations.
/// If you want to process events for your app or game, you should instead use
/// bevy::window::WindowEvent, or one of its sub-events.
///
/// When you receive this event it has already been handled by Bevy's main loop.
/// Sending these events will NOT cause them to be processed by Bevy.
#[derive(Debug, Clone, Event)]
pub struct RawWinitWindowEvent {
/// The window for which the event was fired.
pub window_id: WindowId,
/// The raw winit window event.
pub event: winit::event::WindowEvent,
}

/// A wrapper type around [`winit::event_loop::EventLoopProxy`] with the specific
/// [`winit::event::Event::UserEvent`] used in the [`WinitPlugin`].
///
Expand Down
31 changes: 22 additions & 9 deletions crates/bevy_winit/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ use crate::{
accessibility::AccessKitAdapters,
converters, create_windows,
system::{create_monitors, CachedWindow},
AppSendEvent, CreateMonitorParams, CreateWindowParams, EventLoopProxyWrapper, UpdateMode,
WinitSettings, WinitWindows,
AppSendEvent, CreateMonitorParams, CreateWindowParams, EventLoopProxyWrapper,
RawWinitWindowEvent, UpdateMode, WinitSettings, WinitWindows,
};

/// Persistent state that is used to run the [`App`] according to the current
Expand Down Expand Up @@ -80,6 +80,8 @@ struct WinitAppRunnerState<T: Event> {
previous_lifecycle: AppLifecycle,
/// Bevy window events to send
bevy_window_events: Vec<bevy_window::WindowEvent>,
/// Raw Winit window events to send
raw_winit_events: Vec<RawWinitWindowEvent>,
_marker: PhantomData<T>,

event_writer_system_state: SystemState<(
Expand Down Expand Up @@ -121,6 +123,7 @@ impl<T: Event> WinitAppRunnerState<T> {
// 3 seems to be enough, 5 is a safe margin
startup_forced_updates: 5,
bevy_window_events: Vec::new(),
raw_winit_events: Vec::new(),
_marker: PhantomData,
event_writer_system_state,
}
Expand Down Expand Up @@ -250,6 +253,12 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
return;
};

// Store a copy of the event to send to an EventWriter later.
self.raw_winit_events.push(RawWinitWindowEvent {
window_id,
event: event.clone(),
});

// Allow AccessKit to respond to `WindowEvent`s before they reach
// the engine.
if let Some(adapter) = access_kit_adapters.get_mut(&window) {
Expand Down Expand Up @@ -687,14 +696,16 @@ impl<T: Event> WinitAppRunnerState<T> {
}

fn forward_bevy_events(&mut self) {
let raw_winit_events = self.raw_winit_events.drain(..).collect::<Vec<_>>();
let buffered_events = self.bevy_window_events.drain(..).collect::<Vec<_>>();
let world = self.world_mut();

if buffered_events.is_empty() {
return;
if !raw_winit_events.is_empty() {
world
.resource_mut::<Events<RawWinitWindowEvent>>()
.send_batch(raw_winit_events);
}

let world = self.world_mut();

for winit_event in buffered_events.iter() {
match winit_event.clone() {
BevyWindowEvent::AppLifecycle(e) => {
Expand Down Expand Up @@ -781,9 +792,11 @@ impl<T: Event> WinitAppRunnerState<T> {
}
}

world
.resource_mut::<Events<BevyWindowEvent>>()
.send_batch(buffered_events);
if !buffered_events.is_empty() {
world
.resource_mut::<Events<BevyWindowEvent>>()
.send_batch(buffered_events);
}
}

#[cfg(feature = "custom_cursor")]
Expand Down
Loading