2019-06-21 11:33:15 -04:00
|
|
|
use std::{error, fmt};
|
2019-05-29 21:29:54 -04:00
|
|
|
|
2019-06-18 02:27:00 +08:00
|
|
|
use crate::platform_impl;
|
2019-05-29 21:29:54 -04:00
|
|
|
|
Add EventLoopExtPumpEvents and EventLoopExtRunOnDemand
This adds two new extensions for running a Winit event loop which will
replace `EventLoopExtRunReturn`
The `run_return` API is trying to solve multiple problems and address
multiple, unrelated, use cases but in doing so it is not succeeding
at addressing any of them fully.
The notable use cases we have are:
1. Applications want to be able to implement their own external
event loop and call some Winit API to poll / pump events, once
per iteration of their own loop, without blocking the outer,
external loop. Addressing #2706
2. Applications want to be able to re-run separate instantiations
of some Winit-based GUI and want to allow the event loop to exit with
a status, and then later be able to run the loop again for a new
instantiation of their GUI. Addressing #2431
It's very notable that these use cases can't be supported across
all platforms and so they are extensions, similar to
`EventLoopExtRunReturn`
The intention is to support these extensions on:
- Windows
- Linux (X11 + Wayland)
- macOS
- Android
These extensions aren't compatible with Web or iOS though.
Each method of running the loop will behave consistently in terms of how
`NewEvents(Init)`, `Resumed` and `LoopDestroyed` events are dispatched
(so portable application code wouldn't necessarily need to have any awareness
of which method of running the loop was being used)
Once all backends have support for these extensions then we can
remove `EventLoopExtRunReturn`
For simplicity, the extensions are documented with the assumption that
the above platforms will be supported.
This patch makes no functional change, it only introduces these new
extensions so we can then handle adding platform-specific backends
in separate pull requests, so the work can be landed in stages.
2023-04-11 12:50:52 +01:00
|
|
|
// TODO: Rename
|
|
|
|
|
/// An error that may be generated when requesting Winit state
|
2019-05-29 21:29:54 -04:00
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum ExternalError {
|
|
|
|
|
/// The operation is not supported by the backend.
|
|
|
|
|
NotSupported(NotSupportedError),
|
2023-07-31 00:39:01 +04:00
|
|
|
/// The operation was ignored.
|
|
|
|
|
Ignored,
|
2019-05-29 21:29:54 -04:00
|
|
|
/// The OS cannot perform the operation.
|
|
|
|
|
Os(OsError),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The error type for when the requested operation is not supported by the backend.
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct NotSupportedError {
|
|
|
|
|
_marker: (),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The error type for when the OS cannot perform the requested operation.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct OsError {
|
|
|
|
|
line: u32,
|
|
|
|
|
file: &'static str,
|
|
|
|
|
error: platform_impl::OsError,
|
|
|
|
|
}
|
|
|
|
|
|
Add EventLoopExtPumpEvents and EventLoopExtRunOnDemand
This adds two new extensions for running a Winit event loop which will
replace `EventLoopExtRunReturn`
The `run_return` API is trying to solve multiple problems and address
multiple, unrelated, use cases but in doing so it is not succeeding
at addressing any of them fully.
The notable use cases we have are:
1. Applications want to be able to implement their own external
event loop and call some Winit API to poll / pump events, once
per iteration of their own loop, without blocking the outer,
external loop. Addressing #2706
2. Applications want to be able to re-run separate instantiations
of some Winit-based GUI and want to allow the event loop to exit with
a status, and then later be able to run the loop again for a new
instantiation of their GUI. Addressing #2431
It's very notable that these use cases can't be supported across
all platforms and so they are extensions, similar to
`EventLoopExtRunReturn`
The intention is to support these extensions on:
- Windows
- Linux (X11 + Wayland)
- macOS
- Android
These extensions aren't compatible with Web or iOS though.
Each method of running the loop will behave consistently in terms of how
`NewEvents(Init)`, `Resumed` and `LoopDestroyed` events are dispatched
(so portable application code wouldn't necessarily need to have any awareness
of which method of running the loop was being used)
Once all backends have support for these extensions then we can
remove `EventLoopExtRunReturn`
For simplicity, the extensions are documented with the assumption that
the above platforms will be supported.
This patch makes no functional change, it only introduces these new
extensions so we can then handle adding platform-specific backends
in separate pull requests, so the work can be landed in stages.
2023-04-11 12:50:52 +01:00
|
|
|
/// A general error that may occur while running the Winit event loop
|
|
|
|
|
#[derive(Debug)]
|
2023-08-06 06:07:01 +04:00
|
|
|
pub enum RunLoopError {
|
Add EventLoopExtPumpEvents and EventLoopExtRunOnDemand
This adds two new extensions for running a Winit event loop which will
replace `EventLoopExtRunReturn`
The `run_return` API is trying to solve multiple problems and address
multiple, unrelated, use cases but in doing so it is not succeeding
at addressing any of them fully.
The notable use cases we have are:
1. Applications want to be able to implement their own external
event loop and call some Winit API to poll / pump events, once
per iteration of their own loop, without blocking the outer,
external loop. Addressing #2706
2. Applications want to be able to re-run separate instantiations
of some Winit-based GUI and want to allow the event loop to exit with
a status, and then later be able to run the loop again for a new
instantiation of their GUI. Addressing #2431
It's very notable that these use cases can't be supported across
all platforms and so they are extensions, similar to
`EventLoopExtRunReturn`
The intention is to support these extensions on:
- Windows
- Linux (X11 + Wayland)
- macOS
- Android
These extensions aren't compatible with Web or iOS though.
Each method of running the loop will behave consistently in terms of how
`NewEvents(Init)`, `Resumed` and `LoopDestroyed` events are dispatched
(so portable application code wouldn't necessarily need to have any awareness
of which method of running the loop was being used)
Once all backends have support for these extensions then we can
remove `EventLoopExtRunReturn`
For simplicity, the extensions are documented with the assumption that
the above platforms will be supported.
This patch makes no functional change, it only introduces these new
extensions so we can then handle adding platform-specific backends
in separate pull requests, so the work can be landed in stages.
2023-04-11 12:50:52 +01:00
|
|
|
/// The operation is not supported by the backend.
|
|
|
|
|
NotSupported(NotSupportedError),
|
|
|
|
|
/// The OS cannot perform the operation.
|
|
|
|
|
Os(OsError),
|
|
|
|
|
/// The event loop can't be re-run while it's already running
|
|
|
|
|
AlreadyRunning,
|
|
|
|
|
/// Application has exit with an error status.
|
|
|
|
|
ExitFailure(i32),
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-29 21:29:54 -04:00
|
|
|
impl NotSupportedError {
|
|
|
|
|
#[inline]
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub(crate) fn new() -> NotSupportedError {
|
2019-06-21 11:33:15 -04:00
|
|
|
NotSupportedError { _marker: () }
|
2019-05-29 21:29:54 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl OsError {
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub(crate) fn new(line: u32, file: &'static str, error: platform_impl::OsError) -> OsError {
|
2019-06-21 11:33:15 -04:00
|
|
|
OsError { line, file, error }
|
2019-05-29 21:29:54 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(unused_macros)]
|
|
|
|
|
macro_rules! os_error {
|
|
|
|
|
($error:expr) => {{
|
|
|
|
|
crate::error::OsError::new(line!(), file!(), $error)
|
2019-06-21 11:33:15 -04:00
|
|
|
}};
|
2019-05-29 21:29:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for OsError {
|
2019-07-09 23:49:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
|
f.pad(&format!(
|
2019-06-21 11:33:15 -04:00
|
|
|
"os error at {}:{}: {}",
|
|
|
|
|
self.file, self.line, self.error
|
|
|
|
|
))
|
2019-05-29 21:29:54 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for ExternalError {
|
2019-07-09 23:49:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
2019-05-29 21:29:54 -04:00
|
|
|
match self {
|
2019-07-09 23:49:07 +02:00
|
|
|
ExternalError::NotSupported(e) => e.fmt(f),
|
2023-07-31 00:39:01 +04:00
|
|
|
ExternalError::Ignored => write!(f, "Operation was ignored"),
|
2019-07-09 23:49:07 +02:00
|
|
|
ExternalError::Os(e) => e.fmt(f),
|
2019-05-29 21:29:54 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Debug for NotSupportedError {
|
2019-07-09 23:49:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
|
f.debug_struct("NotSupportedError").finish()
|
2019-05-29 21:29:54 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for NotSupportedError {
|
2019-07-09 23:49:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
|
f.pad("the requested operation is not supported by Winit")
|
2019-05-29 21:29:54 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-06 06:07:01 +04:00
|
|
|
impl fmt::Display for RunLoopError {
|
Add EventLoopExtPumpEvents and EventLoopExtRunOnDemand
This adds two new extensions for running a Winit event loop which will
replace `EventLoopExtRunReturn`
The `run_return` API is trying to solve multiple problems and address
multiple, unrelated, use cases but in doing so it is not succeeding
at addressing any of them fully.
The notable use cases we have are:
1. Applications want to be able to implement their own external
event loop and call some Winit API to poll / pump events, once
per iteration of their own loop, without blocking the outer,
external loop. Addressing #2706
2. Applications want to be able to re-run separate instantiations
of some Winit-based GUI and want to allow the event loop to exit with
a status, and then later be able to run the loop again for a new
instantiation of their GUI. Addressing #2431
It's very notable that these use cases can't be supported across
all platforms and so they are extensions, similar to
`EventLoopExtRunReturn`
The intention is to support these extensions on:
- Windows
- Linux (X11 + Wayland)
- macOS
- Android
These extensions aren't compatible with Web or iOS though.
Each method of running the loop will behave consistently in terms of how
`NewEvents(Init)`, `Resumed` and `LoopDestroyed` events are dispatched
(so portable application code wouldn't necessarily need to have any awareness
of which method of running the loop was being used)
Once all backends have support for these extensions then we can
remove `EventLoopExtRunReturn`
For simplicity, the extensions are documented with the assumption that
the above platforms will be supported.
This patch makes no functional change, it only introduces these new
extensions so we can then handle adding platform-specific backends
in separate pull requests, so the work can be landed in stages.
2023-04-11 12:50:52 +01:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
|
match self {
|
2023-08-06 06:07:01 +04:00
|
|
|
RunLoopError::AlreadyRunning => write!(f, "EventLoop is already running"),
|
|
|
|
|
RunLoopError::NotSupported(e) => e.fmt(f),
|
|
|
|
|
RunLoopError::Os(e) => e.fmt(f),
|
|
|
|
|
RunLoopError::ExitFailure(status) => write!(f, "Exit Failure: {status}"),
|
Add EventLoopExtPumpEvents and EventLoopExtRunOnDemand
This adds two new extensions for running a Winit event loop which will
replace `EventLoopExtRunReturn`
The `run_return` API is trying to solve multiple problems and address
multiple, unrelated, use cases but in doing so it is not succeeding
at addressing any of them fully.
The notable use cases we have are:
1. Applications want to be able to implement their own external
event loop and call some Winit API to poll / pump events, once
per iteration of their own loop, without blocking the outer,
external loop. Addressing #2706
2. Applications want to be able to re-run separate instantiations
of some Winit-based GUI and want to allow the event loop to exit with
a status, and then later be able to run the loop again for a new
instantiation of their GUI. Addressing #2431
It's very notable that these use cases can't be supported across
all platforms and so they are extensions, similar to
`EventLoopExtRunReturn`
The intention is to support these extensions on:
- Windows
- Linux (X11 + Wayland)
- macOS
- Android
These extensions aren't compatible with Web or iOS though.
Each method of running the loop will behave consistently in terms of how
`NewEvents(Init)`, `Resumed` and `LoopDestroyed` events are dispatched
(so portable application code wouldn't necessarily need to have any awareness
of which method of running the loop was being used)
Once all backends have support for these extensions then we can
remove `EventLoopExtRunReturn`
For simplicity, the extensions are documented with the assumption that
the above platforms will be supported.
This patch makes no functional change, it only introduces these new
extensions so we can then handle adding platform-specific backends
in separate pull requests, so the work can be landed in stages.
2023-04-11 12:50:52 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-29 21:29:54 -04:00
|
|
|
impl error::Error for OsError {}
|
|
|
|
|
impl error::Error for ExternalError {}
|
|
|
|
|
impl error::Error for NotSupportedError {}
|
2023-08-06 06:07:01 +04:00
|
|
|
impl error::Error for RunLoopError {}
|
2023-08-05 08:58:38 -07:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
#![allow(clippy::redundant_clone)]
|
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
// Eat attributes for testing
|
|
|
|
|
#[test]
|
|
|
|
|
fn ensure_fmt_does_not_panic() {
|
|
|
|
|
let _ = format!(
|
|
|
|
|
"{:?}, {}",
|
|
|
|
|
NotSupportedError::new(),
|
|
|
|
|
NotSupportedError::new().clone()
|
|
|
|
|
);
|
|
|
|
|
let _ = format!(
|
|
|
|
|
"{:?}, {}",
|
|
|
|
|
ExternalError::NotSupported(NotSupportedError::new()),
|
|
|
|
|
ExternalError::NotSupported(NotSupportedError::new())
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|