winit 0.30

This commit is contained in:
Jonathan Johnson 2024-05-01 11:29:26 -07:00
parent 657493a81d
commit 6048148efd
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
6 changed files with 581 additions and 467 deletions

View file

@ -13,12 +13,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
This crate will maintain feature flags that allow picking whatever versions This crate will maintain feature flags that allow picking whatever versions
winit is exposing. As of writing this note, the choices are `rwh_05` and winit is exposing. As of writing this note, the choices are `rwh_05` and
`rwh_06`. `rwh_05` was the feature that was activated in v0.2.0. `rwh_06`. `rwh_05` was the feature that was activated in v0.2.0.
- `winit` has been updated to 0.30.0.
- `Window::id` now returns `Option<WindowId>`, as a window may be opened before
the event loop has been started.
- `WindowBehavior::build`, `WindowBehavior::build_with`, `WindowBehavior::open`,
and `WindowBehavior::open_with` now require exclusive references to the
application.
- These gesture events have been renamed to match `winit`'s updated nomenclature:
- `WindowBehavior::touchpad_magnify` -> `WindowBehavior::pinch_gesture`
- `WindowBehavior::smart_magnify` -> `WindowBehavior::double_tap_gesture`
### Changed ### Changed
- All `&Appplication` bounds now are `?Sized`, enabling `&dyn Application` - All `&Appplication` bounds now are `?Sized`, enabling `&dyn Application`
parameters. parameters.
### Added
- `AsApplication` now provides `as_application_mut`.
- `WindowBeahvior::pan_gesture` is a new event provided by `winit`.
## v0.2.0 (2023-12-27) ## v0.2.0 (2023-12-27)
### Breaking Changes ### Breaking Changes

618
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -20,4 +20,4 @@ rwh_05 = ["winit/rwh_05"]
[dependencies] [dependencies]
winit = { version = "0.29.3", default-features = false } winit = { version = "0.30.0", default-features = false }

View file

@ -11,13 +11,12 @@ use std::collections::HashMap;
use std::process::exit; use std::process::exit;
use std::sync::{mpsc, Arc, Mutex, PoisonError}; use std::sync::{mpsc, Arc, Mutex, PoisonError};
use private::{OpenedWindow, WindowSpawner};
pub use window::{RunningWindow, Window, WindowAttributes, WindowBehavior, WindowBuilder}; pub use window::{RunningWindow, Window, WindowAttributes, WindowBehavior, WindowBuilder};
pub use winit; pub use winit;
use winit::application::ApplicationHandler;
use winit::error::{EventLoopError, OsError}; use winit::error::{EventLoopError, OsError};
use winit::event::Event; use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop, EventLoopProxy};
use winit::event_loop::{
ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget,
};
use winit::window::WindowId; use winit::window::WindowId;
use crate::private::{EventLoopMessage, WindowEvent, WindowMessage}; use crate::private::{EventLoopMessage, WindowEvent, WindowMessage};
@ -30,6 +29,16 @@ where
event_loop: EventLoop<EventLoopMessage<AppMessage>>, event_loop: EventLoop<EventLoopMessage<AppMessage>>,
message_callback: BoxedEventCallback<AppMessage>, message_callback: BoxedEventCallback<AppMessage>,
running: App<AppMessage>, running: App<AppMessage>,
pending_windows: Vec<PendingWindow<AppMessage>>,
}
struct PendingWindow<AppMessage>
where
AppMessage: Message,
{
window: WindowAttributes,
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
spawner: WindowSpawner,
} }
type BoxedEventCallback<AppMessage> = Box< type BoxedEventCallback<AppMessage> = Box<
@ -65,7 +74,7 @@ where
event_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response event_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response
+ 'static, + 'static,
) -> Self { ) -> Self {
let event_loop = EventLoopBuilder::with_user_event() let event_loop = EventLoop::with_user_event()
.build() .build()
.expect("should be able to create an EventLoop"); .expect("should be able to create an EventLoop");
let proxy = event_loop.create_proxy(); let proxy = event_loop.create_proxy();
@ -76,6 +85,7 @@ where
windows: Windows::default(), windows: Windows::default(),
}, },
message_callback: Box::new(event_callback), message_callback: Box::new(event_callback),
pending_windows: Vec::new(),
} }
} }
@ -87,55 +97,99 @@ where
/// ///
/// Returns an [`EventLoopError`] upon the loop exiting due to an error. See /// Returns an [`EventLoopError`] upon the loop exiting due to an error. See
/// [`EventLoop::run`] for more information. /// [`EventLoop::run`] for more information.
pub fn run(mut self) -> Result<(), EventLoopError> { pub fn run(self) -> Result<(), EventLoopError> {
self.event_loop.run(move |event, target| { let Self {
target.set_control_flow(ControlFlow::Wait); event_loop,
match event { message_callback,
Event::WindowEvent { window_id, event } => { running,
let event = WindowEvent::from(event); pending_windows,
self.running } = self;
.windows event_loop.run_app(&mut RunningApp::<AppMessage> {
.send(window_id, WindowMessage::Event(event)); message_callback,
} running,
Event::UserEvent(message) => match message { pending_windows,
EventLoopMessage::CloseWindow(window_id) => {
if self.running.windows.close(window_id) {
exit(0)
}
}
EventLoopMessage::WindowPanic(window_id) => {
if self.running.windows.close(window_id) {
exit(1)
}
}
EventLoopMessage::OpenWindow {
attrs,
sender,
open_sender,
} => {
let result = self.running.windows.open(target, attrs, sender);
let _result = open_sender.send(result);
}
EventLoopMessage::User {
message,
response_sender,
} => {
let _result = response_sender
.send((self.message_callback)(message, &self.running.windows));
}
},
Event::NewEvents(_)
| Event::MemoryWarning
| Event::DeviceEvent { .. }
| Event::Suspended
| Event::Resumed
| Event::LoopExiting
| Event::AboutToWait => {}
}
}) })
} }
} }
struct RunningApp<AppMessage>
where
AppMessage: Message,
{
message_callback: BoxedEventCallback<AppMessage>,
running: App<AppMessage>,
pending_windows: Vec<PendingWindow<AppMessage>>,
}
impl<AppMessage> ApplicationHandler<EventLoopMessage<AppMessage>> for RunningApp<AppMessage>
where
AppMessage: Message,
{
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
event_loop.set_control_flow(ControlFlow::Wait);
for PendingWindow {
window,
sender,
spawner,
} in self.pending_windows.drain(..)
{
// TODO how to handle open failure errors for pending windows?
let window = self
.running
.windows
.open(event_loop, window, sender)
.expect("error spawning initial window");
spawner(window);
}
}
fn window_event(
&mut self,
_event_loop: &ActiveEventLoop,
window_id: WindowId,
event: winit::event::WindowEvent,
) {
let event = WindowEvent::from(event);
self.running
.windows
.send(window_id, WindowMessage::Event(event));
}
fn user_event(&mut self, event_loop: &ActiveEventLoop, message: EventLoopMessage<AppMessage>) {
match message {
EventLoopMessage::CloseWindow(window_id) => {
if self.running.windows.close(window_id) {
exit(0)
}
}
EventLoopMessage::WindowPanic(window_id) => {
if self.running.windows.close(window_id) {
exit(1)
}
}
EventLoopMessage::OpenWindow {
attrs,
sender,
open_sender,
spawner,
} => {
let result = self.running.windows.open(event_loop, attrs, sender);
if let Ok(open) = &result {
spawner(open.clone());
}
let _result = open_sender.send(result);
}
EventLoopMessage::User {
message,
response_sender,
} => {
let _result =
response_sender.send((self.message_callback)(message, &self.running.windows));
}
}
}
}
/// A reference to a multi-window application. /// A reference to a multi-window application.
pub struct App<AppMessage> pub struct App<AppMessage>
where where
@ -180,6 +234,11 @@ pub trait AsApplication<AppMessage> {
fn as_application(&self) -> &dyn Application<AppMessage> fn as_application(&self) -> &dyn Application<AppMessage>
where where
AppMessage: Message; AppMessage: Message;
/// Returns this type's application.
fn as_application_mut(&mut self) -> &mut dyn Application<AppMessage>
where
AppMessage: Message;
} }
impl<T, AppMessage> AsApplication<AppMessage> for T impl<T, AppMessage> AsApplication<AppMessage> for T
@ -193,6 +252,13 @@ where
{ {
self self
} }
fn as_application_mut(&mut self) -> &mut dyn Application<AppMessage>
where
AppMessage: Message,
{
self
}
} }
/// A message with an associated response type. /// A message with an associated response type.
@ -226,14 +292,17 @@ where
AppMessage: Message, AppMessage: Message,
{ {
fn open( fn open(
&self, &mut self,
window: WindowAttributes, window: WindowAttributes,
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError> { spawner: WindowSpawner,
self.running ) -> Result<Option<OpenedWindow>, OsError> {
.windows self.pending_windows.push(PendingWindow {
.open(&self.event_loop, window, sender) window,
.map(Some) sender,
spawner,
});
Ok(None)
} }
} }
@ -262,10 +331,11 @@ where
AppMessage: Message, AppMessage: Message,
{ {
fn open( fn open(
&self, &mut self,
attrs: WindowAttributes, attrs: WindowAttributes,
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError> { spawner: WindowSpawner,
) -> Result<Option<OpenedWindow>, OsError> {
let (open_sender, open_receiver) = mpsc::sync_channel(1); let (open_sender, open_receiver) = mpsc::sync_channel(1);
if self if self
.proxy .proxy
@ -273,6 +343,7 @@ where
attrs, attrs,
sender, sender,
open_sender, open_sender,
spawner,
}) })
.is_err() .is_err()
{ {
@ -305,24 +376,21 @@ impl<Message> Clone for Windows<Message> {
} }
impl<Message> Windows<Message> { impl<Message> Windows<Message> {
/// Gets an instance of the winit window for the given window id, if it is /// Gets an instance of the winit window for the given window id, if it has
/// still open. /// been opened and is still open.
pub fn get(&self, id: WindowId) -> Option<Arc<winit::window::Window>> { pub fn get(&self, id: WindowId) -> Option<Arc<winit::window::Window>> {
let windows = self.data.lock().map_or_else(PoisonError::into_inner, |g| g); let windows = self.data.lock().map_or_else(PoisonError::into_inner, |g| g);
windows.get(&id).map(|w| w.winit.clone()) windows.get(&id).and_then(|w| w.winit.winit())
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn open<AppMessage>( fn open(
&self, &self,
target: &EventLoopWindowTarget<EventLoopMessage<AppMessage>>, target: &ActiveEventLoop,
attrs: WindowAttributes, attrs: WindowAttributes,
sender: Arc<mpsc::SyncSender<WindowMessage<Message>>>, sender: Arc<mpsc::SyncSender<WindowMessage<Message>>>,
) -> Result<Arc<winit::window::Window>, OsError> ) -> Result<OpenedWindow, OsError> {
where let mut builder = winit::window::WindowAttributes::default()
AppMessage: crate::Message<Window = Message>,
{
let mut builder = winit::window::WindowBuilder::new()
.with_active(attrs.active) .with_active(attrs.active)
.with_resizable(attrs.resizable) .with_resizable(attrs.resizable)
.with_enabled_buttons(attrs.enabled_buttons) .with_enabled_buttons(attrs.enabled_buttons)
@ -370,10 +438,12 @@ impl<Message> Windows<Message> {
if let Some(resize_increments) = attrs.resize_increments { if let Some(resize_increments) = attrs.resize_increments {
builder = builder.with_resize_increments(resize_increments); builder = builder.with_resize_increments(resize_increments);
} }
let winit = Arc::new(builder.build(target)?); let winit = Arc::new(target.create_window(builder)?);
let id = winit.id();
let winit = OpenedWindow(Arc::new(Mutex::new(Some(winit))));
let mut windows = self.data.lock().map_or_else(PoisonError::into_inner, |g| g); let mut windows = self.data.lock().map_or_else(PoisonError::into_inner, |g| g);
windows.insert( windows.insert(
winit.id(), id,
OpenWindow { OpenWindow {
winit: winit.clone(), winit: winit.clone(),
sender, sender,
@ -406,6 +476,6 @@ impl<Message> Windows<Message> {
} }
struct OpenWindow<User> { struct OpenWindow<User> {
winit: Arc<winit::window::Window>, winit: OpenedWindow,
sender: Arc<mpsc::SyncSender<WindowMessage<User>>>, sender: Arc<mpsc::SyncSender<WindowMessage<User>>>,
} }

View file

@ -1,5 +1,5 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc, Mutex, PoisonError};
use winit::dpi::{PhysicalPosition, PhysicalSize}; use winit::dpi::{PhysicalPosition, PhysicalSize};
use winit::error::OsError; use winit::error::OsError;
@ -13,15 +13,30 @@ use winit::window::{ActivationToken, Theme, WindowId};
use crate::window::WindowAttributes; use crate::window::WindowAttributes;
use crate::Message; use crate::Message;
pub type WindowSpawner = Box<dyn FnOnce(OpenedWindow) + Send + 'static>;
pub trait ApplicationSealed<AppMessage> pub trait ApplicationSealed<AppMessage>
where where
AppMessage: Message, AppMessage: Message,
{ {
fn open( fn open(
&self, &mut self,
window: WindowAttributes, window: WindowAttributes,
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError>; spawner: WindowSpawner,
) -> Result<Option<OpenedWindow>, OsError>;
}
#[derive(Clone, Debug)]
pub struct OpenedWindow(pub(crate) Arc<Mutex<Option<Arc<winit::window::Window>>>>);
impl OpenedWindow {
pub fn winit(&self) -> Option<Arc<winit::window::Window>> {
self.0
.lock()
.map_or_else(PoisonError::into_inner, |g| g)
.clone()
}
} }
pub enum EventLoopMessage<AppMessage> pub enum EventLoopMessage<AppMessage>
@ -31,7 +46,8 @@ where
OpenWindow { OpenWindow {
attrs: WindowAttributes, attrs: WindowAttributes,
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
open_sender: mpsc::SyncSender<Result<Arc<winit::window::Window>, OsError>>, open_sender: mpsc::SyncSender<Result<OpenedWindow, OsError>>,
spawner: WindowSpawner,
}, },
CloseWindow(WindowId), CloseWindow(WindowId),
WindowPanic(WindowId), WindowPanic(WindowId),
@ -219,15 +235,20 @@ pub enum WindowEvent {
/// - **iOS / Android / Web / Wayland / Windows:** Unsupported. /// - **iOS / Android / Web / Wayland / Windows:** Unsupported.
Occluded(bool), Occluded(bool),
TouchpadMagnify { PinchGesture {
device_id: DeviceId, device_id: DeviceId,
delta: f64, delta: f64,
phase: TouchPhase, phase: TouchPhase,
}, },
SmartMagnify { PanGesture {
device_id: DeviceId,
delta: PhysicalPosition<f32>,
phase: TouchPhase,
},
DoubleTapGesture {
device_id: DeviceId, device_id: DeviceId,
}, },
TouchpadRotate { RotationGesture {
device_id: DeviceId, device_id: DeviceId,
delta: f32, delta: f32,
phase: TouchPhase, phase: TouchPhase,
@ -329,23 +350,30 @@ impl From<winit::event::WindowEvent> for WindowEvent {
}, },
winit::event::WindowEvent::ThemeChanged(theme) => Self::ThemeChanged(theme), winit::event::WindowEvent::ThemeChanged(theme) => Self::ThemeChanged(theme),
winit::event::WindowEvent::Occluded(occluded) => Self::Occluded(occluded), winit::event::WindowEvent::Occluded(occluded) => Self::Occluded(occluded),
winit::event::WindowEvent::TouchpadMagnify { winit::event::WindowEvent::PinchGesture {
device_id, device_id,
delta, delta,
phase, phase,
} => Self::TouchpadMagnify { } => Self::PinchGesture {
device_id, device_id,
delta, delta,
phase, phase,
}, },
winit::event::WindowEvent::SmartMagnify { device_id } => { winit::event::WindowEvent::PanGesture { device_id, delta, phase } => {
Self::SmartMagnify { device_id } Self::PanGesture {
device_id,
delta,
phase,
}
} }
winit::event::WindowEvent::TouchpadRotate { winit::event::WindowEvent::DoubleTapGesture { device_id } => {
Self::DoubleTapGesture { device_id }
}
winit::event::WindowEvent::RotationGesture {
device_id, device_id,
delta, delta,
phase, phase,
} => Self::TouchpadRotate { } => Self::RotationGesture {
device_id, device_id,
delta, delta,
phase, phase,

View file

@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::panic::AssertUnwindSafe; use std::panic::AssertUnwindSafe;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{mpsc, Arc, Weak}; use std::sync::{mpsc, Arc, PoisonError, Weak};
use std::thread; use std::thread;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -15,7 +15,7 @@ use winit::event::{
use winit::keyboard::PhysicalKey; use winit::keyboard::PhysicalKey;
use winit::window::{Fullscreen, Icon, Theme, WindowButtons, WindowId, WindowLevel}; use winit::window::{Fullscreen, Icon, Theme, WindowButtons, WindowId, WindowLevel};
use crate::private::{self, WindowEvent}; use crate::private::{self, OpenedWindow, WindowEvent, WindowSpawner};
use crate::{ use crate::{
App, Application, AsApplication, EventLoopMessage, Message, PendingApp, WindowMessage, Windows, App, Application, AsApplication, EventLoopMessage, Message, PendingApp, WindowMessage, Windows,
}; };
@ -23,15 +23,20 @@ use crate::{
/// A weak reference to a running window. /// A weak reference to a running window.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Window<Message> { pub struct Window<Message> {
id: WindowId, opened: OpenedWindow,
sender: Weak<mpsc::SyncSender<WindowMessage<Message>>>, sender: Weak<mpsc::SyncSender<WindowMessage<Message>>>,
} }
impl<Message> Window<Message> { impl<Message> Window<Message> {
/// Returns the winit id of the window. /// Returns the winit id of the window.
#[must_use] #[must_use]
pub const fn id(&self) -> WindowId { pub fn id(&self) -> Option<WindowId> {
self.id self.opened
.0
.lock()
.map_or_else(PoisonError::into_inner, |g| g)
.as_ref()
.map(|w| w.id())
} }
/// Sends a message to the window. /// Sends a message to the window.
@ -68,7 +73,7 @@ where
AppMessage: Message, AppMessage: Message,
Application: ?Sized, Application: ?Sized,
{ {
owner: &'a Application, owner: &'a mut Application,
context: Behavior::Context, context: Behavior::Context,
attributes: WindowAttributes, attributes: WindowAttributes,
} }
@ -156,7 +161,7 @@ pub struct WindowAttributes {
impl Default for WindowAttributes { impl Default for WindowAttributes {
fn default() -> Self { fn default() -> Self {
let defaults = winit::window::WindowAttributes::default(); let defaults = winit::window::WindowAttributes::default();
let fullscreen = defaults.fullscreen().cloned(); let fullscreen = defaults.fullscreen.clone();
Self { Self {
inner_size: defaults.inner_size, inner_size: defaults.inner_size,
min_inner_size: defaults.min_inner_size, min_inner_size: defaults.min_inner_size,
@ -187,7 +192,7 @@ where
Application: crate::AsApplication<AppMessage> + ?Sized, Application: crate::AsApplication<AppMessage> + ?Sized,
AppMessage: Message, AppMessage: Message,
{ {
pub(crate) fn new(owner: &'a Application, context: Behavior::Context) -> Self { pub(crate) fn new(owner: &'a mut Application, context: Behavior::Context) -> Self {
Self { Self {
owner, owner,
context, context,
@ -212,37 +217,45 @@ where
// by always using try_send. // by always using try_send.
let (sender, receiver) = mpsc::sync_channel(65536); let (sender, receiver) = mpsc::sync_channel(65536);
let sender = Arc::new(sender); let sender = Arc::new(sender);
let Some(winit) = self let app = self.owner.as_application().app();
.owner let Some(winit) = self.owner.as_application_mut().open(
.as_application() self.attributes,
.open(self.attributes, sender.clone())? sender.clone(),
Box::new({
let sender = sender.clone();
move |opened| {
let winit = opened.winit().expect("just opened");
let running_window = RunningWindow {
messages: (sender, receiver),
responses: mpsc::sync_channel(1),
app,
occluded: winit.is_visible().unwrap_or(false),
focused: winit.has_focus(),
inner_size: winit.inner_size(),
position: winit.inner_position().unwrap_or_default(),
scale: winit.scale_factor(),
theme: winit.theme().unwrap_or(Theme::Dark),
window: winit,
opened,
next_redraw_target: None,
close: false,
modifiers: Modifiers::default(),
cursor_position: None,
mouse_buttons: HashSet::default(),
keys: HashSet::default(),
};
thread::spawn(move || running_window.run_with::<Behavior>(self.context));
}
}),
)?
else { else {
return Ok(None); return Ok(None);
}; };
let window = Window { let window = Window {
id: winit.id(), opened: winit.clone(),
sender: Arc::downgrade(&sender), sender: Arc::downgrade(&sender),
}; };
let running_window = RunningWindow {
messages: (sender, receiver),
responses: mpsc::sync_channel(1),
app: self.owner.as_application().app(),
occluded: winit.is_visible().unwrap_or(false),
focused: winit.has_focus(),
inner_size: winit.inner_size(),
position: winit.inner_position().unwrap_or_default(),
scale: winit.scale_factor(),
theme: winit.theme().unwrap_or(Theme::Dark),
window: winit,
next_redraw_target: None,
close: false,
modifiers: Modifiers::default(),
cursor_position: None,
mouse_buttons: HashSet::default(),
keys: HashSet::default(),
};
thread::spawn(move || running_window.run_with::<Behavior>(self.context));
Ok(Some(window)) Ok(Some(window))
} }
@ -257,6 +270,7 @@ where
AppMessage: Message, AppMessage: Message,
{ {
window: Arc<winit::window::Window>, window: Arc<winit::window::Window>,
opened: OpenedWindow,
next_redraw_target: Option<RedrawTarget>, next_redraw_target: Option<RedrawTarget>,
messages: SyncArcChannel<WindowMessage<AppMessage::Window>>, messages: SyncArcChannel<WindowMessage<AppMessage::Window>>,
responses: SyncChannel<AppMessage::Response>, responses: SyncChannel<AppMessage::Response>,
@ -288,7 +302,7 @@ where
#[must_use] #[must_use]
pub fn handle(&self) -> Window<AppMessage::Window> { pub fn handle(&self) -> Window<AppMessage::Window> {
Window { Window {
id: self.window.id(), opened: self.opened.clone(),
sender: Arc::downgrade(&self.messages.0), sender: Arc::downgrade(&self.messages.0),
} }
} }
@ -625,24 +639,31 @@ where
WindowEvent::Touch(touch) => { WindowEvent::Touch(touch) => {
behavior.touch(self, touch); behavior.touch(self, touch);
} }
WindowEvent::TouchpadMagnify { WindowEvent::PinchGesture {
device_id, device_id,
delta, delta,
phase, phase,
} => { } => {
behavior.touchpad_magnify(self, device_id, delta, phase); behavior.pinch_gesture(self, device_id, delta, phase);
} }
WindowEvent::SmartMagnify { device_id } => { WindowEvent::PanGesture {
behavior.smart_magnify(self, device_id); device_id,
delta,
phase,
} => {
behavior.pan_gesture(self, device_id, delta, phase);
} }
WindowEvent::TouchpadRotate { WindowEvent::DoubleTapGesture { device_id } => {
behavior.double_tap_gesture(self, device_id);
}
WindowEvent::RotationGesture {
device_id, device_id,
delta, delta,
phase, phase,
} => { } => {
behavior.touchpad_rotate(self, device_id, delta, phase); behavior.touchpad_rotate(self, device_id, delta, phase);
} }
WindowEvent::ActivationTokenDone { .. } => todo!(), WindowEvent::ActivationTokenDone { .. } => {}
}, },
} }
@ -707,10 +728,11 @@ where
AppMessage: Message, AppMessage: Message,
{ {
fn open( fn open(
&self, &mut self,
attrs: WindowAttributes, attrs: WindowAttributes,
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError> { spawner: WindowSpawner,
) -> Result<Option<OpenedWindow>, OsError> {
let (open_sender, open_receiver) = mpsc::sync_channel(1); let (open_sender, open_receiver) = mpsc::sync_channel(1);
if self if self
.app .app
@ -719,6 +741,7 @@ where
attrs, attrs,
sender, sender,
open_sender, open_sender,
spawner,
}) })
.is_ok() .is_ok()
{ {
@ -774,7 +797,7 @@ where
type Context: Send; type Context: Send;
/// Returns a new window builder for this behavior. When the window is /// Returns a new window builder for this behavior. When the window is
/// initialized, a default [`Context`](Self::Context) will be passed. /// initialized, a default [`Context`](Self::Context) will be passed.
fn build<App>(app: &App) -> WindowBuilder<'_, Self, App, AppMessage> fn build<App>(app: &mut App) -> WindowBuilder<'_, Self, App, AppMessage>
where where
App: AsApplication<AppMessage> + ?Sized, App: AsApplication<AppMessage> + ?Sized,
Self::Context: Default, Self::Context: Default,
@ -785,7 +808,7 @@ where
/// Returns a new window builder for this behavior. When the window is /// Returns a new window builder for this behavior. When the window is
/// initialized, the provided context will be passed. /// initialized, the provided context will be passed.
fn build_with<App>( fn build_with<App>(
app: &App, app: &mut App,
context: Self::Context, context: Self::Context,
) -> WindowBuilder<'_, Self, App, AppMessage> ) -> WindowBuilder<'_, Self, App, AppMessage>
where where
@ -815,8 +838,8 @@ where
where where
Self::Context: Default, Self::Context: Default,
{ {
let app = PendingApp::new_with_event_callback(app_callback); let mut app = PendingApp::new_with_event_callback(app_callback);
Self::open(&app).expect("error opening initial window"); Self::open(&mut app).expect("error opening initial window");
app.run() app.run()
} }
@ -838,8 +861,8 @@ where
app_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response app_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response
+ 'static, + 'static,
) -> Result<(), EventLoopError> { ) -> Result<(), EventLoopError> {
let app = PendingApp::new_with_event_callback(app_callback); let mut app = PendingApp::new_with_event_callback(app_callback);
Self::open_with(&app, context).expect("error opening initial window"); Self::open_with(&mut app, context).expect("error opening initial window");
app.run() app.run()
} }
@ -853,7 +876,7 @@ where
/// ///
/// The only errors this funciton can return arise from /// The only errors this funciton can return arise from
/// [`winit::window::WindowBuilder::build`]. /// [`winit::window::WindowBuilder::build`].
fn open<App>(app: &App) -> Result<Option<Window<AppMessage::Window>>, OsError> fn open<App>(app: &mut App) -> Result<Option<Window<AppMessage::Window>>, OsError>
where where
App: AsApplication<AppMessage> + ?Sized, App: AsApplication<AppMessage> + ?Sized,
Self::Context: Default, Self::Context: Default,
@ -872,7 +895,7 @@ where
/// The only errors this funciton can return arise from /// The only errors this funciton can return arise from
/// [`winit::window::WindowBuilder::build`]. /// [`winit::window::WindowBuilder::build`].
fn open_with<App>( fn open_with<App>(
app: &App, app: &mut App,
context: Self::Context, context: Self::Context,
) -> Result<Option<Window<AppMessage::Window>>, OsError> ) -> Result<Option<Window<AppMessage::Window>>, OsError>
where where
@ -1025,9 +1048,9 @@ where
#[allow(unused_variables)] #[allow(unused_variables)]
fn touch(&mut self, window: &mut RunningWindow<AppMessage>, touch: Touch) {} fn touch(&mut self, window: &mut RunningWindow<AppMessage>, touch: Touch) {}
/// A touchpad-originated magnification gesture. /// A magnification gesture.
#[allow(unused_variables)] #[allow(unused_variables)]
fn touchpad_magnify( fn pinch_gesture(
&mut self, &mut self,
window: &mut RunningWindow<AppMessage>, window: &mut RunningWindow<AppMessage>,
device_id: DeviceId, device_id: DeviceId,
@ -1036,9 +1059,20 @@ where
) { ) {
} }
/// A pan/scroll gesture.
#[allow(unused_variables)]
fn pan_gesture(
&mut self,
window: &mut RunningWindow<AppMessage>,
device_id: DeviceId,
delta: PhysicalPosition<f32>,
phase: TouchPhase,
) {
}
/// A request to smart-magnify the window. /// A request to smart-magnify the window.
#[allow(unused_variables)] #[allow(unused_variables)]
fn smart_magnify(&mut self, window: &mut RunningWindow<AppMessage>, device_id: DeviceId) {} fn double_tap_gesture(&mut self, window: &mut RunningWindow<AppMessage>, device_id: DeviceId) {}
/// A touchpad-originated rotation gesture. /// A touchpad-originated rotation gesture.
#[allow(unused_variables)] #[allow(unused_variables)]
@ -1066,8 +1100,8 @@ pub trait Run: WindowBehavior<()> {
where where
Self::Context: Default, Self::Context: Default,
{ {
let app = PendingApp::new(); let mut app = PendingApp::new();
Self::open(&app).expect("error opening initial window"); Self::open(&mut app).expect("error opening initial window");
app.run() app.run()
} }
@ -1076,8 +1110,8 @@ pub trait Run: WindowBehavior<()> {
/// This function is shorthand for creating a [`PendingApp`], opening this /// This function is shorthand for creating a [`PendingApp`], opening this
/// window inside of it, and running the pending app. /// window inside of it, and running the pending app.
fn run_with(context: Self::Context) -> Result<(), EventLoopError> { fn run_with(context: Self::Context) -> Result<(), EventLoopError> {
let app = PendingApp::new(); let mut app = PendingApp::new();
Self::open_with(&app, context).expect("error opening initial window"); Self::open_with(&mut app, context).expect("error opening initial window");
app.run() app.run()
} }
} }