mirror of
https://github.com/danbulant/appit
synced 2026-06-17 13:21:20 +00:00
winit 0.30
This commit is contained in:
parent
657493a81d
commit
6048148efd
6 changed files with 581 additions and 467 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
|
@ -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
|
||||
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.
|
||||
- `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
|
||||
|
||||
- All `&Appplication` bounds now are `?Sized`, enabling `&dyn Application`
|
||||
parameters.
|
||||
|
||||
### Added
|
||||
|
||||
- `AsApplication` now provides `as_application_mut`.
|
||||
- `WindowBeahvior::pan_gesture` is a new event provided by `winit`.
|
||||
|
||||
## v0.2.0 (2023-12-27)
|
||||
|
||||
### Breaking Changes
|
||||
|
|
|
|||
618
Cargo.lock
generated
618
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -20,4 +20,4 @@ rwh_05 = ["winit/rwh_05"]
|
|||
|
||||
|
||||
[dependencies]
|
||||
winit = { version = "0.29.3", default-features = false }
|
||||
winit = { version = "0.30.0", default-features = false }
|
||||
|
|
|
|||
212
src/lib.rs
212
src/lib.rs
|
|
@ -11,13 +11,12 @@ use std::collections::HashMap;
|
|||
use std::process::exit;
|
||||
use std::sync::{mpsc, Arc, Mutex, PoisonError};
|
||||
|
||||
use private::{OpenedWindow, WindowSpawner};
|
||||
pub use window::{RunningWindow, Window, WindowAttributes, WindowBehavior, WindowBuilder};
|
||||
pub use winit;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::error::{EventLoopError, OsError};
|
||||
use winit::event::Event;
|
||||
use winit::event_loop::{
|
||||
ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget,
|
||||
};
|
||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop, EventLoopProxy};
|
||||
use winit::window::WindowId;
|
||||
|
||||
use crate::private::{EventLoopMessage, WindowEvent, WindowMessage};
|
||||
|
|
@ -30,6 +29,16 @@ where
|
|||
event_loop: EventLoop<EventLoopMessage<AppMessage>>,
|
||||
message_callback: BoxedEventCallback<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<
|
||||
|
|
@ -65,7 +74,7 @@ where
|
|||
event_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response
|
||||
+ 'static,
|
||||
) -> Self {
|
||||
let event_loop = EventLoopBuilder::with_user_event()
|
||||
let event_loop = EventLoop::with_user_event()
|
||||
.build()
|
||||
.expect("should be able to create an EventLoop");
|
||||
let proxy = event_loop.create_proxy();
|
||||
|
|
@ -76,6 +85,7 @@ where
|
|||
windows: Windows::default(),
|
||||
},
|
||||
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
|
||||
/// [`EventLoop::run`] for more information.
|
||||
pub fn run(mut self) -> Result<(), EventLoopError> {
|
||||
self.event_loop.run(move |event, target| {
|
||||
target.set_control_flow(ControlFlow::Wait);
|
||||
match event {
|
||||
Event::WindowEvent { window_id, event } => {
|
||||
let event = WindowEvent::from(event);
|
||||
self.running
|
||||
.windows
|
||||
.send(window_id, WindowMessage::Event(event));
|
||||
}
|
||||
Event::UserEvent(message) => 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,
|
||||
} => {
|
||||
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 => {}
|
||||
}
|
||||
pub fn run(self) -> Result<(), EventLoopError> {
|
||||
let Self {
|
||||
event_loop,
|
||||
message_callback,
|
||||
running,
|
||||
pending_windows,
|
||||
} = self;
|
||||
event_loop.run_app(&mut RunningApp::<AppMessage> {
|
||||
message_callback,
|
||||
running,
|
||||
pending_windows,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
pub struct App<AppMessage>
|
||||
where
|
||||
|
|
@ -180,6 +234,11 @@ pub trait AsApplication<AppMessage> {
|
|||
fn as_application(&self) -> &dyn Application<AppMessage>
|
||||
where
|
||||
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
|
||||
|
|
@ -193,6 +252,13 @@ where
|
|||
{
|
||||
self
|
||||
}
|
||||
|
||||
fn as_application_mut(&mut self) -> &mut dyn Application<AppMessage>
|
||||
where
|
||||
AppMessage: Message,
|
||||
{
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A message with an associated response type.
|
||||
|
|
@ -226,14 +292,17 @@ where
|
|||
AppMessage: Message,
|
||||
{
|
||||
fn open(
|
||||
&self,
|
||||
&mut self,
|
||||
window: WindowAttributes,
|
||||
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
|
||||
) -> Result<Option<Arc<winit::window::Window>>, OsError> {
|
||||
self.running
|
||||
.windows
|
||||
.open(&self.event_loop, window, sender)
|
||||
.map(Some)
|
||||
spawner: WindowSpawner,
|
||||
) -> Result<Option<OpenedWindow>, OsError> {
|
||||
self.pending_windows.push(PendingWindow {
|
||||
window,
|
||||
sender,
|
||||
spawner,
|
||||
});
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -262,10 +331,11 @@ where
|
|||
AppMessage: Message,
|
||||
{
|
||||
fn open(
|
||||
&self,
|
||||
&mut self,
|
||||
attrs: WindowAttributes,
|
||||
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);
|
||||
if self
|
||||
.proxy
|
||||
|
|
@ -273,6 +343,7 @@ where
|
|||
attrs,
|
||||
sender,
|
||||
open_sender,
|
||||
spawner,
|
||||
})
|
||||
.is_err()
|
||||
{
|
||||
|
|
@ -305,24 +376,21 @@ impl<Message> Clone for Windows<Message> {
|
|||
}
|
||||
|
||||
impl<Message> Windows<Message> {
|
||||
/// Gets an instance of the winit window for the given window id, if it is
|
||||
/// still open.
|
||||
/// Gets an instance of the winit window for the given window id, if it has
|
||||
/// been opened and is still open.
|
||||
pub fn get(&self, id: WindowId) -> Option<Arc<winit::window::Window>> {
|
||||
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)]
|
||||
fn open<AppMessage>(
|
||||
fn open(
|
||||
&self,
|
||||
target: &EventLoopWindowTarget<EventLoopMessage<AppMessage>>,
|
||||
target: &ActiveEventLoop,
|
||||
attrs: WindowAttributes,
|
||||
sender: Arc<mpsc::SyncSender<WindowMessage<Message>>>,
|
||||
) -> Result<Arc<winit::window::Window>, OsError>
|
||||
where
|
||||
AppMessage: crate::Message<Window = Message>,
|
||||
{
|
||||
let mut builder = winit::window::WindowBuilder::new()
|
||||
) -> Result<OpenedWindow, OsError> {
|
||||
let mut builder = winit::window::WindowAttributes::default()
|
||||
.with_active(attrs.active)
|
||||
.with_resizable(attrs.resizable)
|
||||
.with_enabled_buttons(attrs.enabled_buttons)
|
||||
|
|
@ -370,10 +438,12 @@ impl<Message> Windows<Message> {
|
|||
if let Some(resize_increments) = attrs.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);
|
||||
windows.insert(
|
||||
winit.id(),
|
||||
id,
|
||||
OpenWindow {
|
||||
winit: winit.clone(),
|
||||
sender,
|
||||
|
|
@ -406,6 +476,6 @@ impl<Message> Windows<Message> {
|
|||
}
|
||||
|
||||
struct OpenWindow<User> {
|
||||
winit: Arc<winit::window::Window>,
|
||||
winit: OpenedWindow,
|
||||
sender: Arc<mpsc::SyncSender<WindowMessage<User>>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::sync::{mpsc, Arc, Mutex, PoisonError};
|
||||
|
||||
use winit::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use winit::error::OsError;
|
||||
|
|
@ -13,15 +13,30 @@ use winit::window::{ActivationToken, Theme, WindowId};
|
|||
use crate::window::WindowAttributes;
|
||||
use crate::Message;
|
||||
|
||||
pub type WindowSpawner = Box<dyn FnOnce(OpenedWindow) + Send + 'static>;
|
||||
|
||||
pub trait ApplicationSealed<AppMessage>
|
||||
where
|
||||
AppMessage: Message,
|
||||
{
|
||||
fn open(
|
||||
&self,
|
||||
&mut self,
|
||||
window: WindowAttributes,
|
||||
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>
|
||||
|
|
@ -31,7 +46,8 @@ where
|
|||
OpenWindow {
|
||||
attrs: WindowAttributes,
|
||||
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),
|
||||
WindowPanic(WindowId),
|
||||
|
|
@ -219,15 +235,20 @@ pub enum WindowEvent {
|
|||
/// - **iOS / Android / Web / Wayland / Windows:** Unsupported.
|
||||
Occluded(bool),
|
||||
|
||||
TouchpadMagnify {
|
||||
PinchGesture {
|
||||
device_id: DeviceId,
|
||||
delta: f64,
|
||||
phase: TouchPhase,
|
||||
},
|
||||
SmartMagnify {
|
||||
PanGesture {
|
||||
device_id: DeviceId,
|
||||
delta: PhysicalPosition<f32>,
|
||||
phase: TouchPhase,
|
||||
},
|
||||
DoubleTapGesture {
|
||||
device_id: DeviceId,
|
||||
},
|
||||
TouchpadRotate {
|
||||
RotationGesture {
|
||||
device_id: DeviceId,
|
||||
delta: f32,
|
||||
phase: TouchPhase,
|
||||
|
|
@ -329,23 +350,30 @@ impl From<winit::event::WindowEvent> for WindowEvent {
|
|||
},
|
||||
winit::event::WindowEvent::ThemeChanged(theme) => Self::ThemeChanged(theme),
|
||||
winit::event::WindowEvent::Occluded(occluded) => Self::Occluded(occluded),
|
||||
winit::event::WindowEvent::TouchpadMagnify {
|
||||
winit::event::WindowEvent::PinchGesture {
|
||||
device_id,
|
||||
delta,
|
||||
phase,
|
||||
} => Self::TouchpadMagnify {
|
||||
} => Self::PinchGesture {
|
||||
device_id,
|
||||
delta,
|
||||
phase,
|
||||
},
|
||||
winit::event::WindowEvent::SmartMagnify { device_id } => {
|
||||
Self::SmartMagnify { device_id }
|
||||
winit::event::WindowEvent::PanGesture { device_id, delta, phase } => {
|
||||
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,
|
||||
delta,
|
||||
phase,
|
||||
} => Self::TouchpadRotate {
|
||||
} => Self::RotationGesture {
|
||||
device_id,
|
||||
delta,
|
||||
phase,
|
||||
|
|
|
|||
148
src/window.rs
148
src/window.rs
|
|
@ -2,7 +2,7 @@ use std::collections::HashSet;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use std::panic::AssertUnwindSafe;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{mpsc, Arc, Weak};
|
||||
use std::sync::{mpsc, Arc, PoisonError, Weak};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ use winit::event::{
|
|||
use winit::keyboard::PhysicalKey;
|
||||
use winit::window::{Fullscreen, Icon, Theme, WindowButtons, WindowId, WindowLevel};
|
||||
|
||||
use crate::private::{self, WindowEvent};
|
||||
use crate::private::{self, OpenedWindow, WindowEvent, WindowSpawner};
|
||||
use crate::{
|
||||
App, Application, AsApplication, EventLoopMessage, Message, PendingApp, WindowMessage, Windows,
|
||||
};
|
||||
|
|
@ -23,15 +23,20 @@ use crate::{
|
|||
/// A weak reference to a running window.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Window<Message> {
|
||||
id: WindowId,
|
||||
opened: OpenedWindow,
|
||||
sender: Weak<mpsc::SyncSender<WindowMessage<Message>>>,
|
||||
}
|
||||
|
||||
impl<Message> Window<Message> {
|
||||
/// Returns the winit id of the window.
|
||||
#[must_use]
|
||||
pub const fn id(&self) -> WindowId {
|
||||
self.id
|
||||
pub fn id(&self) -> Option<WindowId> {
|
||||
self.opened
|
||||
.0
|
||||
.lock()
|
||||
.map_or_else(PoisonError::into_inner, |g| g)
|
||||
.as_ref()
|
||||
.map(|w| w.id())
|
||||
}
|
||||
|
||||
/// Sends a message to the window.
|
||||
|
|
@ -68,7 +73,7 @@ where
|
|||
AppMessage: Message,
|
||||
Application: ?Sized,
|
||||
{
|
||||
owner: &'a Application,
|
||||
owner: &'a mut Application,
|
||||
context: Behavior::Context,
|
||||
attributes: WindowAttributes,
|
||||
}
|
||||
|
|
@ -156,7 +161,7 @@ pub struct WindowAttributes {
|
|||
impl Default for WindowAttributes {
|
||||
fn default() -> Self {
|
||||
let defaults = winit::window::WindowAttributes::default();
|
||||
let fullscreen = defaults.fullscreen().cloned();
|
||||
let fullscreen = defaults.fullscreen.clone();
|
||||
Self {
|
||||
inner_size: defaults.inner_size,
|
||||
min_inner_size: defaults.min_inner_size,
|
||||
|
|
@ -187,7 +192,7 @@ where
|
|||
Application: crate::AsApplication<AppMessage> + ?Sized,
|
||||
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 {
|
||||
owner,
|
||||
context,
|
||||
|
|
@ -212,37 +217,45 @@ where
|
|||
// by always using try_send.
|
||||
let (sender, receiver) = mpsc::sync_channel(65536);
|
||||
let sender = Arc::new(sender);
|
||||
let Some(winit) = self
|
||||
.owner
|
||||
.as_application()
|
||||
.open(self.attributes, sender.clone())?
|
||||
let app = self.owner.as_application().app();
|
||||
let Some(winit) = self.owner.as_application_mut().open(
|
||||
self.attributes,
|
||||
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 {
|
||||
return Ok(None);
|
||||
};
|
||||
let window = Window {
|
||||
id: winit.id(),
|
||||
opened: winit.clone(),
|
||||
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))
|
||||
}
|
||||
|
|
@ -257,6 +270,7 @@ where
|
|||
AppMessage: Message,
|
||||
{
|
||||
window: Arc<winit::window::Window>,
|
||||
opened: OpenedWindow,
|
||||
next_redraw_target: Option<RedrawTarget>,
|
||||
messages: SyncArcChannel<WindowMessage<AppMessage::Window>>,
|
||||
responses: SyncChannel<AppMessage::Response>,
|
||||
|
|
@ -288,7 +302,7 @@ where
|
|||
#[must_use]
|
||||
pub fn handle(&self) -> Window<AppMessage::Window> {
|
||||
Window {
|
||||
id: self.window.id(),
|
||||
opened: self.opened.clone(),
|
||||
sender: Arc::downgrade(&self.messages.0),
|
||||
}
|
||||
}
|
||||
|
|
@ -625,24 +639,31 @@ where
|
|||
WindowEvent::Touch(touch) => {
|
||||
behavior.touch(self, touch);
|
||||
}
|
||||
WindowEvent::TouchpadMagnify {
|
||||
WindowEvent::PinchGesture {
|
||||
device_id,
|
||||
delta,
|
||||
phase,
|
||||
} => {
|
||||
behavior.touchpad_magnify(self, device_id, delta, phase);
|
||||
behavior.pinch_gesture(self, device_id, delta, phase);
|
||||
}
|
||||
WindowEvent::SmartMagnify { device_id } => {
|
||||
behavior.smart_magnify(self, device_id);
|
||||
WindowEvent::PanGesture {
|
||||
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,
|
||||
delta,
|
||||
phase,
|
||||
} => {
|
||||
behavior.touchpad_rotate(self, device_id, delta, phase);
|
||||
}
|
||||
WindowEvent::ActivationTokenDone { .. } => todo!(),
|
||||
WindowEvent::ActivationTokenDone { .. } => {}
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -707,10 +728,11 @@ where
|
|||
AppMessage: Message,
|
||||
{
|
||||
fn open(
|
||||
&self,
|
||||
&mut self,
|
||||
attrs: WindowAttributes,
|
||||
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);
|
||||
if self
|
||||
.app
|
||||
|
|
@ -719,6 +741,7 @@ where
|
|||
attrs,
|
||||
sender,
|
||||
open_sender,
|
||||
spawner,
|
||||
})
|
||||
.is_ok()
|
||||
{
|
||||
|
|
@ -774,7 +797,7 @@ where
|
|||
type Context: Send;
|
||||
/// Returns a new window builder for this behavior. When the window is
|
||||
/// 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
|
||||
App: AsApplication<AppMessage> + ?Sized,
|
||||
Self::Context: Default,
|
||||
|
|
@ -785,7 +808,7 @@ where
|
|||
/// Returns a new window builder for this behavior. When the window is
|
||||
/// initialized, the provided context will be passed.
|
||||
fn build_with<App>(
|
||||
app: &App,
|
||||
app: &mut App,
|
||||
context: Self::Context,
|
||||
) -> WindowBuilder<'_, Self, App, AppMessage>
|
||||
where
|
||||
|
|
@ -815,8 +838,8 @@ where
|
|||
where
|
||||
Self::Context: Default,
|
||||
{
|
||||
let app = PendingApp::new_with_event_callback(app_callback);
|
||||
Self::open(&app).expect("error opening initial window");
|
||||
let mut app = PendingApp::new_with_event_callback(app_callback);
|
||||
Self::open(&mut app).expect("error opening initial window");
|
||||
app.run()
|
||||
}
|
||||
|
||||
|
|
@ -838,8 +861,8 @@ where
|
|||
app_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response
|
||||
+ 'static,
|
||||
) -> Result<(), EventLoopError> {
|
||||
let app = PendingApp::new_with_event_callback(app_callback);
|
||||
Self::open_with(&app, context).expect("error opening initial window");
|
||||
let mut app = PendingApp::new_with_event_callback(app_callback);
|
||||
Self::open_with(&mut app, context).expect("error opening initial window");
|
||||
app.run()
|
||||
}
|
||||
|
||||
|
|
@ -853,7 +876,7 @@ where
|
|||
///
|
||||
/// The only errors this funciton can return arise from
|
||||
/// [`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
|
||||
App: AsApplication<AppMessage> + ?Sized,
|
||||
Self::Context: Default,
|
||||
|
|
@ -872,7 +895,7 @@ where
|
|||
/// The only errors this funciton can return arise from
|
||||
/// [`winit::window::WindowBuilder::build`].
|
||||
fn open_with<App>(
|
||||
app: &App,
|
||||
app: &mut App,
|
||||
context: Self::Context,
|
||||
) -> Result<Option<Window<AppMessage::Window>>, OsError>
|
||||
where
|
||||
|
|
@ -1025,9 +1048,9 @@ where
|
|||
#[allow(unused_variables)]
|
||||
fn touch(&mut self, window: &mut RunningWindow<AppMessage>, touch: Touch) {}
|
||||
|
||||
/// A touchpad-originated magnification gesture.
|
||||
/// A magnification gesture.
|
||||
#[allow(unused_variables)]
|
||||
fn touchpad_magnify(
|
||||
fn pinch_gesture(
|
||||
&mut self,
|
||||
window: &mut RunningWindow<AppMessage>,
|
||||
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.
|
||||
#[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.
|
||||
#[allow(unused_variables)]
|
||||
|
|
@ -1066,8 +1100,8 @@ pub trait Run: WindowBehavior<()> {
|
|||
where
|
||||
Self::Context: Default,
|
||||
{
|
||||
let app = PendingApp::new();
|
||||
Self::open(&app).expect("error opening initial window");
|
||||
let mut app = PendingApp::new();
|
||||
Self::open(&mut app).expect("error opening initial window");
|
||||
app.run()
|
||||
}
|
||||
|
||||
|
|
@ -1076,8 +1110,8 @@ pub trait Run: WindowBehavior<()> {
|
|||
/// This function is shorthand for creating a [`PendingApp`], opening this
|
||||
/// window inside of it, and running the pending app.
|
||||
fn run_with(context: Self::Context) -> Result<(), EventLoopError> {
|
||||
let app = PendingApp::new();
|
||||
Self::open_with(&app, context).expect("error opening initial window");
|
||||
let mut app = PendingApp::new();
|
||||
Self::open_with(&mut app, context).expect("error opening initial window");
|
||||
app.run()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue