mirror of
https://github.com/danbulant/appit
synced 2026-07-03 10:00:37 +00:00
Added ability for windows to call the main loop
When I ran the new Kludgine on my mac last night, I was surprised to discover it didn't work. It turns out create_surface needs to be called on the main thread on Metal. This commit adds a way to provide a callback that can be remotely called through the EventLoopProxy. This allows Kludgine to send a CreateSurfaceRequest to the main event loop and receive a wgpu::Surface back.
This commit is contained in:
parent
8f49442f28
commit
13e0864bcd
3 changed files with 419 additions and 240 deletions
149
src/lib.rs
149
src/lib.rs
|
|
@ -15,30 +15,52 @@ use winit::error::OsError;
|
||||||
use winit::window::WindowId;
|
use winit::window::WindowId;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::sync::{mpsc, Arc, Mutex, PoisonError};
|
use std::sync::{mpsc, Arc, Mutex, PoisonError};
|
||||||
use winit::event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget};
|
use winit::event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget};
|
||||||
use winit::{event::Event, event_loop::EventLoop};
|
use winit::{event::Event, event_loop::EventLoop};
|
||||||
|
|
||||||
use crate::private::{AppMessage, WindowEvent, WindowMessage};
|
use crate::private::{EventLoopMessage, WindowEvent, WindowMessage};
|
||||||
use crate::window::WindowAttributes;
|
use crate::window::WindowAttributes;
|
||||||
|
|
||||||
/// An application that is not yet running.
|
/// An application that is not yet running.
|
||||||
pub struct PendingApp {
|
pub struct PendingApp<AppMessage>
|
||||||
event_loop: EventLoop<AppMessage>,
|
where
|
||||||
running: App,
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
event_loop: EventLoop<EventLoopMessage<AppMessage>>,
|
||||||
|
message_callback: BoxedEventCallback<AppMessage>,
|
||||||
|
running: App<AppMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PendingApp {
|
type BoxedEventCallback<AppMessage> =
|
||||||
|
Box<dyn FnMut(AppMessage, &Windows<AppMessage>) -> <AppMessage as Message>::Response>;
|
||||||
|
|
||||||
|
impl Default for PendingApp<()> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PendingApp {
|
impl PendingApp<()> {
|
||||||
/// Returns a new app with no windows. If no windows are opened before the
|
/// Returns a new app with no windows. If no windows are opened before the
|
||||||
/// app is run, the app will immediately close.
|
/// app is run, the app will immediately close.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
Self::new_with_event_callback(|_, _| {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> PendingApp<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
/// Returns a new app with no windows. If no windows are opened before the
|
||||||
|
/// app is run, the app will immediately close.
|
||||||
|
#[must_use]
|
||||||
|
pub fn new_with_event_callback(
|
||||||
|
event_callback: impl FnMut(AppMessage, &Windows<AppMessage>) -> AppMessage::Response + 'static,
|
||||||
|
) -> Self {
|
||||||
let event_loop = EventLoopBuilder::with_user_event().build();
|
let event_loop = EventLoopBuilder::with_user_event().build();
|
||||||
let proxy = event_loop.create_proxy();
|
let proxy = event_loop.create_proxy();
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -47,13 +69,14 @@ impl PendingApp {
|
||||||
proxy,
|
proxy,
|
||||||
windows: Windows::default(),
|
windows: Windows::default(),
|
||||||
},
|
},
|
||||||
|
message_callback: Box::new(event_callback),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Begins running the application. This function will never return.
|
/// Begins running the application. This function will never return.
|
||||||
///
|
///
|
||||||
/// Internally this runs the [`EventLoop`].
|
/// Internally this runs the [`EventLoop`].
|
||||||
pub fn run(self) -> ! {
|
pub fn run(mut self) -> ! {
|
||||||
self.event_loop.run(move |event, target, control_flow| {
|
self.event_loop.run(move |event, target, control_flow| {
|
||||||
*control_flow = ControlFlow::Wait;
|
*control_flow = ControlFlow::Wait;
|
||||||
match event {
|
match event {
|
||||||
|
|
@ -67,17 +90,17 @@ impl PendingApp {
|
||||||
self.running.windows.send(window_id, WindowMessage::Redraw);
|
self.running.windows.send(window_id, WindowMessage::Redraw);
|
||||||
}
|
}
|
||||||
Event::UserEvent(message) => match message {
|
Event::UserEvent(message) => match message {
|
||||||
AppMessage::CloseWindow(window_id) => {
|
EventLoopMessage::CloseWindow(window_id) => {
|
||||||
if self.running.windows.close(window_id) {
|
if self.running.windows.close(window_id) {
|
||||||
*control_flow = ControlFlow::ExitWithCode(0);
|
*control_flow = ControlFlow::ExitWithCode(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AppMessage::WindowPanic(window_id) => {
|
EventLoopMessage::WindowPanic(window_id) => {
|
||||||
if self.running.windows.close(window_id) {
|
if self.running.windows.close(window_id) {
|
||||||
*control_flow = ControlFlow::ExitWithCode(1);
|
*control_flow = ControlFlow::ExitWithCode(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AppMessage::OpenWindow {
|
EventLoopMessage::OpenWindow {
|
||||||
attrs,
|
attrs,
|
||||||
sender,
|
sender,
|
||||||
open_sender,
|
open_sender,
|
||||||
|
|
@ -85,6 +108,13 @@ impl PendingApp {
|
||||||
let result = self.running.windows.open(target, attrs, sender);
|
let result = self.running.windows.open(target, attrs, sender);
|
||||||
let _result = open_sender.send(result);
|
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::NewEvents(_)
|
||||||
| Event::DeviceEvent { .. }
|
| Event::DeviceEvent { .. }
|
||||||
|
|
@ -99,19 +129,64 @@ impl PendingApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A reference to a multi-window application.
|
/// A reference to a multi-window application.
|
||||||
#[derive(Clone)]
|
pub struct App<AppMessage>
|
||||||
pub struct App {
|
where
|
||||||
proxy: EventLoopProxy<AppMessage>,
|
AppMessage: Message,
|
||||||
windows: Windows,
|
{
|
||||||
|
proxy: EventLoopProxy<EventLoopMessage<AppMessage>>,
|
||||||
|
windows: Windows<AppMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> Clone for App<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
proxy: self.proxy.clone(),
|
||||||
|
windows: self.windows.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that has a handle to the application thread.
|
/// A type that has a handle to the application thread.
|
||||||
pub trait Application: private::ApplicationSealed {}
|
pub trait Application<AppMessage>: private::ApplicationSealed<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
/// Sends an app message to the main event loop to be handled by the
|
||||||
|
/// callback provided when the app was created.
|
||||||
|
///
|
||||||
|
/// This function will return None if the main event loop is no longer
|
||||||
|
/// running. Otherwise, this function will block until the result of the
|
||||||
|
/// callback has been received.
|
||||||
|
fn send(&mut self, message: AppMessage) -> Option<AppMessage::Response>;
|
||||||
|
}
|
||||||
|
|
||||||
impl Application for PendingApp {}
|
/// A message with an associated response type.
|
||||||
|
pub trait Message: Send + 'static {
|
||||||
|
/// The type returned when responding to this message.
|
||||||
|
type Response: Send;
|
||||||
|
}
|
||||||
|
|
||||||
impl private::ApplicationSealed for PendingApp {
|
impl Message for () {
|
||||||
fn app(&self) -> App {
|
type Response = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> Application<AppMessage> for PendingApp<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn send(&mut self, message: AppMessage) -> Option<<AppMessage as Message>::Response> {
|
||||||
|
Some((self.message_callback)(message, &self.running.windows))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> private::ApplicationSealed<AppMessage> for PendingApp<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn app(&self) -> App<AppMessage> {
|
||||||
self.running.clone()
|
self.running.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,13 +202,37 @@ impl private::ApplicationSealed for PendingApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
/// A collection of open windows.
|
||||||
struct Windows {
|
pub struct Windows<AppMessage> {
|
||||||
data: Arc<Mutex<HashMap<WindowId, OpenWindow>>>,
|
data: Arc<Mutex<HashMap<WindowId, OpenWindow>>>,
|
||||||
|
_message: PhantomData<AppMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Windows {
|
impl<AppMessage> Default for Windows<AppMessage> {
|
||||||
fn get(&self, id: WindowId) -> Option<Arc<winit::window::Window>> {
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
data: Arc::default(),
|
||||||
|
_message: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> Clone for Windows<AppMessage> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
data: self.data.clone(),
|
||||||
|
_message: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> Windows<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
/// Gets an instance of the winit window for the given window id, if it 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);
|
let windows = self.data.lock().map_or_else(PoisonError::into_inner, |g| g);
|
||||||
windows.get(&id).map(|w| w.winit.clone())
|
windows.get(&id).map(|w| w.winit.clone())
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +240,7 @@ impl Windows {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn open(
|
fn open(
|
||||||
&self,
|
&self,
|
||||||
target: &EventLoopWindowTarget<AppMessage>,
|
target: &EventLoopWindowTarget<EventLoopMessage<AppMessage>>,
|
||||||
attrs: WindowAttributes,
|
attrs: WindowAttributes,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage>,
|
||||||
) -> Result<Arc<winit::window::Window>, OsError> {
|
) -> Result<Arc<winit::window::Window>, OsError> {
|
||||||
|
|
@ -198,7 +297,7 @@ impl Windows {
|
||||||
Ok(winit)
|
Ok(winit)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send(&self, window: WindowId, message: WindowMessage) {
|
fn send(&self, window: WindowId, message: WindowMessage) {
|
||||||
let mut data = self.data.lock().map_or_else(PoisonError::into_inner, |g| g);
|
let mut data = self.data.lock().map_or_else(PoisonError::into_inner, |g| g);
|
||||||
if let Some(open_window) = data.get(&window) {
|
if let Some(open_window) = data.get(&window) {
|
||||||
match open_window.sender.try_send(message) {
|
match open_window.sender.try_send(message) {
|
||||||
|
|
@ -214,7 +313,7 @@ impl Windows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(&self, window: WindowId) -> bool {
|
fn close(&self, window: WindowId) -> bool {
|
||||||
let mut data = self.data.lock().map_or_else(PoisonError::into_inner, |g| g);
|
let mut data = self.data.lock().map_or_else(PoisonError::into_inner, |g| g);
|
||||||
data.remove(&window);
|
data.remove(&window);
|
||||||
data.is_empty()
|
data.is_empty()
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,13 @@ use winit::event::{
|
||||||
use winit::window::{Theme, WindowId};
|
use winit::window::{Theme, WindowId};
|
||||||
|
|
||||||
use crate::window::WindowAttributes;
|
use crate::window::WindowAttributes;
|
||||||
use crate::App;
|
use crate::{App, Message};
|
||||||
|
|
||||||
pub trait ApplicationSealed {
|
pub trait ApplicationSealed<AppMessage>
|
||||||
fn app(&self) -> App;
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn app(&self) -> App<AppMessage>;
|
||||||
fn open(
|
fn open(
|
||||||
&self,
|
&self,
|
||||||
window: WindowAttributes,
|
window: WindowAttributes,
|
||||||
|
|
@ -21,7 +24,10 @@ pub trait ApplicationSealed {
|
||||||
) -> Result<Option<Arc<winit::window::Window>>, OsError>;
|
) -> Result<Option<Arc<winit::window::Window>>, OsError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AppMessage {
|
pub enum EventLoopMessage<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
OpenWindow {
|
OpenWindow {
|
||||||
attrs: WindowAttributes,
|
attrs: WindowAttributes,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage>,
|
||||||
|
|
@ -29,6 +35,10 @@ pub enum AppMessage {
|
||||||
},
|
},
|
||||||
CloseWindow(WindowId),
|
CloseWindow(WindowId),
|
||||||
WindowPanic(WindowId),
|
WindowPanic(WindowId),
|
||||||
|
User {
|
||||||
|
message: AppMessage,
|
||||||
|
response_sender: mpsc::SyncSender<AppMessage::Response>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
||||||
492
src/window.rs
492
src/window.rs
|
|
@ -15,12 +15,11 @@ use winit::event::{
|
||||||
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, WindowEvent};
|
||||||
use crate::{App, AppMessage, Application, PendingApp, WindowMessage};
|
use crate::{App, Application, EventLoopMessage, Message, PendingApp, WindowMessage, Windows};
|
||||||
|
|
||||||
/// A weak reference to a running window.
|
/// A weak reference to a running window.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
app: App,
|
|
||||||
id: WindowId,
|
id: WindowId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,13 +29,6 @@ impl Window {
|
||||||
pub const fn id(&self) -> WindowId {
|
pub const fn id(&self) -> WindowId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a clone of the winit [`Window`](winit::window::Window) if the
|
|
||||||
/// window is still open.
|
|
||||||
#[must_use]
|
|
||||||
pub fn winit(&self) -> Option<Arc<winit::window::Window>> {
|
|
||||||
self.app.windows.get(self.id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A builder for a window.
|
/// A builder for a window.
|
||||||
|
|
@ -46,17 +38,20 @@ impl Window {
|
||||||
/// supports the cross-platform interface. Support for additional
|
/// supports the cross-platform interface. Support for additional
|
||||||
/// platform-specific settings may be possible as long as all types introduced
|
/// platform-specific settings may be possible as long as all types introduced
|
||||||
/// are `Send`.
|
/// are `Send`.
|
||||||
pub struct WindowBuilder<'a, Behavior, Application>
|
pub struct WindowBuilder<'a, Behavior, Application, AppMessage>
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
owner: &'a Application,
|
owner: &'a Application,
|
||||||
context: Behavior::Context,
|
context: Behavior::Context,
|
||||||
attributes: WindowAttributes,
|
attributes: WindowAttributes,
|
||||||
}
|
}
|
||||||
impl<'a, Behavior, Application> Deref for WindowBuilder<'a, Behavior, Application>
|
impl<'a, Behavior, Application, AppMessage> Deref
|
||||||
|
for WindowBuilder<'a, Behavior, Application, AppMessage>
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
type Target = WindowAttributes;
|
type Target = WindowAttributes;
|
||||||
|
|
||||||
|
|
@ -65,9 +60,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Behavior, Application> DerefMut for WindowBuilder<'a, Behavior, Application>
|
impl<'a, Behavior, Application, AppMessage> DerefMut
|
||||||
|
for WindowBuilder<'a, Behavior, Application, AppMessage>
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.attributes
|
&mut self.attributes
|
||||||
|
|
@ -124,10 +121,11 @@ impl Default for WindowAttributes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Behavior, Application> WindowBuilder<'a, Behavior, Application>
|
impl<'a, Behavior, Application, AppMessage> WindowBuilder<'a, Behavior, Application, AppMessage>
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
Application: crate::Application,
|
Application: crate::Application<AppMessage>,
|
||||||
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(owner: &'a Application, context: Behavior::Context) -> Self {
|
pub(crate) fn new(owner: &'a Application, context: Behavior::Context) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -156,12 +154,10 @@ where
|
||||||
let Some(winit) = self.owner.open(self.attributes, sender)? else {
|
let Some(winit) = self.owner.open(self.attributes, sender)? else {
|
||||||
return Ok(None)
|
return Ok(None)
|
||||||
};
|
};
|
||||||
let window = Window {
|
let window = Window { id: winit.id() };
|
||||||
id: winit.id(),
|
|
||||||
app: self.owner.app(),
|
|
||||||
};
|
|
||||||
let running_window = RunningWindow {
|
let running_window = RunningWindow {
|
||||||
messages: receiver,
|
messages: receiver,
|
||||||
|
responses: mpsc::sync_channel(1),
|
||||||
app: self.owner.app(),
|
app: self.owner.app(),
|
||||||
occluded: winit.is_visible().unwrap_or(false),
|
occluded: winit.is_visible().unwrap_or(false),
|
||||||
focused: winit.has_focus(),
|
focused: winit.has_focus(),
|
||||||
|
|
@ -185,11 +181,18 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A window that is running in its own thread.
|
/// A window that is running in its own thread.
|
||||||
pub struct RunningWindow {
|
pub struct RunningWindow<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
window: Arc<winit::window::Window>,
|
window: Arc<winit::window::Window>,
|
||||||
next_redraw_target: Option<RedrawTarget>,
|
next_redraw_target: Option<RedrawTarget>,
|
||||||
messages: mpsc::Receiver<WindowMessage>,
|
messages: mpsc::Receiver<WindowMessage>,
|
||||||
app: App,
|
responses: (
|
||||||
|
mpsc::SyncSender<AppMessage::Response>,
|
||||||
|
mpsc::Receiver<AppMessage::Response>,
|
||||||
|
),
|
||||||
|
app: App<AppMessage>,
|
||||||
inner_size: PhysicalSize<u32>,
|
inner_size: PhysicalSize<u32>,
|
||||||
location: PhysicalPosition<i32>,
|
location: PhysicalPosition<i32>,
|
||||||
cursor_location: Option<PhysicalPosition<f64>>,
|
cursor_location: Option<PhysicalPosition<f64>>,
|
||||||
|
|
@ -203,7 +206,10 @@ pub struct RunningWindow {
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunningWindow {
|
impl<AppMessage> RunningWindow<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
/// Returns a reference to the underlying window.
|
/// Returns a reference to the underlying window.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn winit(&self) -> &winit::window::Window {
|
pub fn winit(&self) -> &winit::window::Window {
|
||||||
|
|
@ -300,7 +306,7 @@ impl RunningWindow {
|
||||||
|
|
||||||
fn run_with<Behavior>(mut self, context: Behavior::Context)
|
fn run_with<Behavior>(mut self, context: Behavior::Context)
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
{
|
{
|
||||||
let proxy = self.app.proxy.clone();
|
let proxy = self.app.proxy.clone();
|
||||||
let window_id = self.window.id();
|
let window_id = self.window.id();
|
||||||
|
|
@ -318,16 +324,16 @@ impl RunningWindow {
|
||||||
|
|
||||||
//
|
//
|
||||||
if let Err(panic) = possible_panic {
|
if let Err(panic) = possible_panic {
|
||||||
let _result = proxy.send_event(AppMessage::WindowPanic(window_id));
|
let _result = proxy.send_event(EventLoopMessage::WindowPanic(window_id));
|
||||||
std::panic::resume_unwind(panic)
|
std::panic::resume_unwind(panic)
|
||||||
} else {
|
} else {
|
||||||
let _result = proxy.send_event(AppMessage::CloseWindow(window_id));
|
let _result = proxy.send_event(EventLoopMessage::CloseWindow(window_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_messages_until_redraw<Behavior>(&mut self, behavior: &mut Behavior) -> bool
|
fn process_messages_until_redraw<Behavior>(&mut self, behavior: &mut Behavior) -> bool
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
let message = match TimeUntilRedraw::from(self.next_redraw_target) {
|
let message = match TimeUntilRedraw::from(self.next_redraw_target) {
|
||||||
|
|
@ -364,7 +370,7 @@ impl RunningWindow {
|
||||||
#[allow(clippy::too_many_lines)] // can't avoid the match
|
#[allow(clippy::too_many_lines)] // can't avoid the match
|
||||||
fn handle_message<Behavior>(&mut self, message: WindowMessage, behavior: &mut Behavior) -> bool
|
fn handle_message<Behavior>(&mut self, message: WindowMessage, behavior: &mut Behavior) -> bool
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
{
|
{
|
||||||
match message {
|
match message {
|
||||||
WindowMessage::Redraw => {
|
WindowMessage::Redraw => {
|
||||||
|
|
@ -559,10 +565,27 @@ impl RunningWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for RunningWindow {}
|
impl<AppMessage> Application<AppMessage> for RunningWindow<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn send(&mut self, message: AppMessage) -> Option<<AppMessage as Message>::Response> {
|
||||||
|
self.app
|
||||||
|
.proxy
|
||||||
|
.send_event(EventLoopMessage::User {
|
||||||
|
message,
|
||||||
|
response_sender: self.responses.0.clone(),
|
||||||
|
})
|
||||||
|
.ok()?;
|
||||||
|
self.responses.1.recv().ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl private::ApplicationSealed for RunningWindow {
|
impl<AppMessage> private::ApplicationSealed<AppMessage> for RunningWindow<AppMessage>
|
||||||
fn app(&self) -> App {
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn app(&self) -> App<AppMessage> {
|
||||||
self.app.clone()
|
self.app.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -575,7 +598,7 @@ impl private::ApplicationSealed for RunningWindow {
|
||||||
if self
|
if self
|
||||||
.app
|
.app
|
||||||
.proxy
|
.proxy
|
||||||
.send_event(AppMessage::OpenWindow {
|
.send_event(EventLoopMessage::OpenWindow {
|
||||||
attrs,
|
attrs,
|
||||||
sender,
|
sender,
|
||||||
open_sender,
|
open_sender,
|
||||||
|
|
@ -623,7 +646,10 @@ enum TimeUntilRedraw {
|
||||||
/// consumers of the libraries. This trait provides functions for each of the
|
/// consumers of the libraries. This trait provides functions for each of the
|
||||||
/// events a window may receive, enabling the type to react and update its
|
/// events a window may receive, enabling the type to react and update its
|
||||||
/// state.
|
/// state.
|
||||||
pub trait WindowBehavior: UnwindSafe + Sized + 'static {
|
pub trait WindowBehavior<AppMessage>: UnwindSafe + Sized + 'static
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
/// A type that is passed to [`initialize()`](Self::initialize).
|
/// A type that is passed to [`initialize()`](Self::initialize).
|
||||||
///
|
///
|
||||||
/// This allows providing data to the window from the thread that is opening
|
/// This allows providing data to the window from the thread that is opening
|
||||||
|
|
@ -632,9 +658,9 @@ pub trait WindowBehavior: UnwindSafe + Sized + 'static {
|
||||||
|
|
||||||
/// 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>
|
fn build<App>(app: &App) -> WindowBuilder<'_, Self, App, AppMessage>
|
||||||
where
|
where
|
||||||
App: Application,
|
App: Application<AppMessage>,
|
||||||
Self::Context: Default,
|
Self::Context: Default,
|
||||||
{
|
{
|
||||||
Self::build_with(app, <Self::Context as Default>::default())
|
Self::build_with(app, <Self::Context as Default>::default())
|
||||||
|
|
@ -642,13 +668,53 @@ pub trait WindowBehavior: UnwindSafe + Sized + 'static {
|
||||||
|
|
||||||
/// 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>(app: &App, context: Self::Context) -> WindowBuilder<'_, Self, App>
|
fn build_with<App>(
|
||||||
|
app: &App,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> WindowBuilder<'_, Self, App, AppMessage>
|
||||||
where
|
where
|
||||||
App: Application,
|
App: Application<AppMessage>,
|
||||||
{
|
{
|
||||||
WindowBuilder::new(app, context)
|
WindowBuilder::new(app, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs a window with a default instance of this behavior's
|
||||||
|
/// [`Context`](Self::Context).
|
||||||
|
///
|
||||||
|
/// This function is shorthand for creating a [`PendingApp`], opening this
|
||||||
|
/// window inside of it, and running the pending app.
|
||||||
|
///
|
||||||
|
/// Messages can be sent to the application's main thread using
|
||||||
|
/// [`Application::send`]. Each time a message is received by the main event
|
||||||
|
/// loop, `app_callback` will be invoked.
|
||||||
|
fn run_with_event_callback(
|
||||||
|
app_callback: impl FnMut(AppMessage, &Windows<AppMessage>) -> AppMessage::Response + 'static,
|
||||||
|
) -> !
|
||||||
|
where
|
||||||
|
Self::Context: Default,
|
||||||
|
{
|
||||||
|
let app = PendingApp::new_with_event_callback(app_callback);
|
||||||
|
Self::open(&app).expect("error opening initial window");
|
||||||
|
app.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs a window with the provided [`Context`](Self::Context).
|
||||||
|
///
|
||||||
|
/// This function is shorthand for creating a [`PendingApp`], opening this
|
||||||
|
/// window inside of it, and running the pending app.
|
||||||
|
///
|
||||||
|
/// Messages can be sent to the application's main thread using
|
||||||
|
/// [`Application::send`]. Each time a message is received by the main event
|
||||||
|
/// loop, `app_callback` will be invoked.
|
||||||
|
fn run_with_context_and_event_callback(
|
||||||
|
context: Self::Context,
|
||||||
|
app_callback: impl FnMut(AppMessage, &Windows<AppMessage>) -> AppMessage::Response + 'static,
|
||||||
|
) -> ! {
|
||||||
|
let app = PendingApp::new_with_event_callback(app_callback);
|
||||||
|
Self::open_with(&app, context).expect("error opening initial window");
|
||||||
|
app.run()
|
||||||
|
}
|
||||||
|
|
||||||
/// Opens a new window with a default instance of this behavior's
|
/// Opens a new window with a default instance of this behavior's
|
||||||
/// [`Context`](Self::Context). The events of the window will be processed
|
/// [`Context`](Self::Context). The events of the window will be processed
|
||||||
/// in a thread spawned by this function.
|
/// in a thread spawned by this function.
|
||||||
|
|
@ -661,7 +727,7 @@ pub trait WindowBehavior: UnwindSafe + Sized + 'static {
|
||||||
/// [`winit::window::WindowBuilder::build`].
|
/// [`winit::window::WindowBuilder::build`].
|
||||||
fn open<App>(app: &App) -> Result<Option<Window>, OsError>
|
fn open<App>(app: &App) -> Result<Option<Window>, OsError>
|
||||||
where
|
where
|
||||||
App: Application,
|
App: Application<AppMessage>,
|
||||||
Self::Context: Default,
|
Self::Context: Default,
|
||||||
{
|
{
|
||||||
Self::build(app).open()
|
Self::build(app).open()
|
||||||
|
|
@ -679,11 +745,183 @@ pub trait WindowBehavior: UnwindSafe + Sized + 'static {
|
||||||
/// [`winit::window::WindowBuilder::build`].
|
/// [`winit::window::WindowBuilder::build`].
|
||||||
fn open_with<App>(app: &App, context: Self::Context) -> Result<Option<Window>, OsError>
|
fn open_with<App>(app: &App, context: Self::Context) -> Result<Option<Window>, OsError>
|
||||||
where
|
where
|
||||||
App: Application,
|
App: Application<AppMessage>,
|
||||||
{
|
{
|
||||||
Self::build_with(app, context).open()
|
Self::build_with(app, context).open()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a new instance of this behavior after initializing itself with
|
||||||
|
/// the window and context.
|
||||||
|
fn initialize(window: &mut RunningWindow<AppMessage>, context: Self::Context) -> Self;
|
||||||
|
|
||||||
|
/// Displays the contents of the window.
|
||||||
|
fn redraw(&mut self, window: &mut RunningWindow<AppMessage>);
|
||||||
|
|
||||||
|
/// The window has been requested to be closed. This can happen as a result
|
||||||
|
/// of the user clicking the close button.
|
||||||
|
///
|
||||||
|
/// If the window should be closed, return true. To prevent closing the
|
||||||
|
/// window, return false.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn close_requested(&mut self, window: &mut RunningWindow<AppMessage>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The window has gained or lost keyboard focus.
|
||||||
|
/// [`RunningWindow::focused()`] returns the current state.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn focus_changed(&mut self, window: &mut RunningWindow<AppMessage>) {}
|
||||||
|
|
||||||
|
/// The window has been occluded or revealed. [`RunningWindow::occluded()`]
|
||||||
|
/// returns the current state.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn occlusion_changed(&mut self, window: &mut RunningWindow<AppMessage>) {}
|
||||||
|
|
||||||
|
/// The window's scale factor has changed. [`RunningWindow::scale()`]
|
||||||
|
/// returns the current scale.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn scale_factor_changed(&mut self, window: &mut RunningWindow<AppMessage>) {}
|
||||||
|
|
||||||
|
/// The window has been resized. [`RunningWindow::inner_size()`]
|
||||||
|
/// returns the current size.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn resized(&mut self, window: &mut RunningWindow<AppMessage>) {}
|
||||||
|
|
||||||
|
/// The window's theme has been updated. [`RunningWindow::theme()`]
|
||||||
|
/// returns the current theme.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn theme_changed(&mut self, window: &mut RunningWindow<AppMessage>) {}
|
||||||
|
|
||||||
|
/// A file has been dropped on the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn dropped_file(&mut self, window: &mut RunningWindow<AppMessage>, path: PathBuf) {}
|
||||||
|
|
||||||
|
/// A file is hovering over the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn hovered_file(&mut self, window: &mut RunningWindow<AppMessage>, path: PathBuf) {}
|
||||||
|
|
||||||
|
/// A file being overed has been cancelled.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn hovered_file_cancelled(&mut self, window: &mut RunningWindow<AppMessage>) {}
|
||||||
|
|
||||||
|
/// An input event has generated a character.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn received_character(&mut self, window: &mut RunningWindow<AppMessage>, char: char) {}
|
||||||
|
|
||||||
|
/// A keyboard event occurred while the window was focused.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn keyboard_input(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
input: KeyboardInput,
|
||||||
|
is_synthetic: bool,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The keyboard modifier keys have changed. [`RunningWindow::modifiers()`]
|
||||||
|
/// returns the current modifier keys state.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn modifiers_changed(&mut self, window: &mut RunningWindow<AppMessage>) {}
|
||||||
|
|
||||||
|
/// An international input even thas occurred for the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn ime(&mut self, window: &mut RunningWindow<AppMessage>, ime: Ime) {}
|
||||||
|
|
||||||
|
/// A cursor has moved over the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn cursor_moved(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
position: PhysicalPosition<f64>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A cursor has hovered over the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn cursor_entered(&mut self, window: &mut RunningWindow<AppMessage>, device_id: DeviceId) {}
|
||||||
|
|
||||||
|
/// A cursor is no longer hovering over the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn cursor_left(&mut self, window: &mut RunningWindow<AppMessage>, device_id: DeviceId) {}
|
||||||
|
|
||||||
|
/// An event from a mouse wheel.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn mouse_wheel(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
delta: MouseScrollDelta,
|
||||||
|
phase: TouchPhase,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A mouse button was pressed or released.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn mouse_input(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
state: ElementState,
|
||||||
|
button: MouseButton,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A pressure-sensitive touchpad was touched.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn touchpad_pressure(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
pressure: f32,
|
||||||
|
stage: i64,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A multi-axis input device has registered motion.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn axis_motion(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
axis: AxisId,
|
||||||
|
value: f64,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A touch event.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn touch(&mut self, window: &mut RunningWindow<AppMessage>, touch: Touch) {}
|
||||||
|
|
||||||
|
/// A touchpad-originated magnification gesture.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn touchpad_magnify(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
delta: f64,
|
||||||
|
phase: TouchPhase,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A request to smart-magnify the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn smart_magnify(&mut self, window: &mut RunningWindow<AppMessage>, device_id: DeviceId) {}
|
||||||
|
|
||||||
|
/// A touchpad-originated rotation gesture.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn touchpad_rotate(
|
||||||
|
&mut self,
|
||||||
|
window: &mut RunningWindow<AppMessage>,
|
||||||
|
device_id: DeviceId,
|
||||||
|
delta: f32,
|
||||||
|
phase: TouchPhase,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Run: WindowBehavior<()> {
|
||||||
/// Runs a window with a default instance of this behavior's
|
/// Runs a window with a default instance of this behavior's
|
||||||
/// [`Context`](Self::Context).
|
/// [`Context`](Self::Context).
|
||||||
///
|
///
|
||||||
|
|
@ -707,174 +945,6 @@ pub trait WindowBehavior: UnwindSafe + Sized + 'static {
|
||||||
Self::open_with(&app, context).expect("error opening initial window");
|
Self::open_with(&app, context).expect("error opening initial window");
|
||||||
app.run()
|
app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new instance of this behavior after initializing itself with
|
|
||||||
/// the window and context.
|
|
||||||
fn initialize(window: &mut RunningWindow, context: Self::Context) -> Self;
|
|
||||||
|
|
||||||
/// Displays the contents of the window.
|
|
||||||
fn redraw(&mut self, window: &mut RunningWindow);
|
|
||||||
|
|
||||||
/// The window has been requested to be closed. This can happen as a result
|
|
||||||
/// of the user clicking the close button.
|
|
||||||
///
|
|
||||||
/// If the window should be closed, return true. To prevent closing the
|
|
||||||
/// window, return false.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn close_requested(&mut self, window: &mut RunningWindow) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The window has gained or lost keyboard focus.
|
|
||||||
/// [`RunningWindow::focused()`] returns the current state.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn focus_changed(&mut self, window: &mut RunningWindow) {}
|
|
||||||
|
|
||||||
/// The window has been occluded or revealed. [`RunningWindow::occluded()`]
|
|
||||||
/// returns the current state.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn occlusion_changed(&mut self, window: &mut RunningWindow) {}
|
|
||||||
|
|
||||||
/// The window's scale factor has changed. [`RunningWindow::scale()`]
|
|
||||||
/// returns the current scale.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn scale_factor_changed(&mut self, window: &mut RunningWindow) {}
|
|
||||||
|
|
||||||
/// The window has been resized. [`RunningWindow::inner_size()`]
|
|
||||||
/// returns the current size.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn resized(&mut self, window: &mut RunningWindow) {}
|
|
||||||
|
|
||||||
/// The window's theme has been updated. [`RunningWindow::theme()`]
|
|
||||||
/// returns the current theme.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn theme_changed(&mut self, window: &mut RunningWindow) {}
|
|
||||||
|
|
||||||
/// A file has been dropped on the window.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn dropped_file(&mut self, window: &mut RunningWindow, path: PathBuf) {}
|
|
||||||
|
|
||||||
/// A file is hovering over the window.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn hovered_file(&mut self, window: &mut RunningWindow, path: PathBuf) {}
|
|
||||||
|
|
||||||
/// A file being overed has been cancelled.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn hovered_file_cancelled(&mut self, window: &mut RunningWindow) {}
|
|
||||||
|
|
||||||
/// An input event has generated a character.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn received_character(&mut self, window: &mut RunningWindow, char: char) {}
|
|
||||||
|
|
||||||
/// A keyboard event occurred while the window was focused.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn keyboard_input(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
input: KeyboardInput,
|
|
||||||
is_synthetic: bool,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The keyboard modifier keys have changed. [`RunningWindow::modifiers()`]
|
|
||||||
/// returns the current modifier keys state.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn modifiers_changed(&mut self, window: &mut RunningWindow) {}
|
|
||||||
|
|
||||||
/// An international input even thas occurred for the window.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn ime(&mut self, window: &mut RunningWindow, ime: Ime) {}
|
|
||||||
|
|
||||||
/// A cursor has moved over the window.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn cursor_moved(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
position: PhysicalPosition<f64>,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A cursor has hovered over the window.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn cursor_entered(&mut self, window: &mut RunningWindow, device_id: DeviceId) {}
|
|
||||||
|
|
||||||
/// A cursor is no longer hovering over the window.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn cursor_left(&mut self, window: &mut RunningWindow, device_id: DeviceId) {}
|
|
||||||
|
|
||||||
/// An event from a mouse wheel.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn mouse_wheel(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
delta: MouseScrollDelta,
|
|
||||||
phase: TouchPhase,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A mouse button was pressed or released.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn mouse_input(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
state: ElementState,
|
|
||||||
button: MouseButton,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A pressure-sensitive touchpad was touched.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn touchpad_pressure(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
pressure: f32,
|
|
||||||
stage: i64,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A multi-axis input device has registered motion.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn axis_motion(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
axis: AxisId,
|
|
||||||
value: f64,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A touch event.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn touch(&mut self, window: &mut RunningWindow, touch: Touch) {}
|
|
||||||
|
|
||||||
/// A touchpad-originated magnification gesture.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn touchpad_magnify(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
delta: f64,
|
|
||||||
phase: TouchPhase,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A request to smart-magnify the window.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn smart_magnify(&mut self, window: &mut RunningWindow, device_id: DeviceId) {}
|
|
||||||
|
|
||||||
/// A touchpad-originated rotation gesture.
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn touchpad_rotate(
|
|
||||||
&mut self,
|
|
||||||
window: &mut RunningWindow,
|
|
||||||
device_id: DeviceId,
|
|
||||||
delta: f32,
|
|
||||||
phase: TouchPhase,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Run for T where T: WindowBehavior<()> {}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue