mirror of
https://github.com/danbulant/appit
synced 2026-06-24 17:11:54 +00:00
Added ability to send messages to windows.
Gooey is using this to send invalidation messages from the UI callbacks.
This commit is contained in:
parent
13e0864bcd
commit
1b5da400f3
3 changed files with 117 additions and 67 deletions
65
src/lib.rs
65
src/lib.rs
|
|
@ -15,7 +15,6 @@ 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};
|
||||||
|
|
@ -33,8 +32,12 @@ where
|
||||||
running: App<AppMessage>,
|
running: App<AppMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type BoxedEventCallback<AppMessage> =
|
type BoxedEventCallback<AppMessage> = Box<
|
||||||
Box<dyn FnMut(AppMessage, &Windows<AppMessage>) -> <AppMessage as Message>::Response>;
|
dyn FnMut(
|
||||||
|
AppMessage,
|
||||||
|
&Windows<<AppMessage as Message>::Window>,
|
||||||
|
) -> <AppMessage as Message>::Response,
|
||||||
|
>;
|
||||||
|
|
||||||
impl Default for PendingApp<()> {
|
impl Default for PendingApp<()> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|
@ -59,7 +62,8 @@ where
|
||||||
/// app is run, the app will immediately close.
|
/// app is run, the app will immediately close.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_with_event_callback(
|
pub fn new_with_event_callback(
|
||||||
event_callback: impl FnMut(AppMessage, &Windows<AppMessage>) -> AppMessage::Response + 'static,
|
event_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response
|
||||||
|
+ 'static,
|
||||||
) -> Self {
|
) -> 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();
|
||||||
|
|
@ -134,7 +138,7 @@ where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
proxy: EventLoopProxy<EventLoopMessage<AppMessage>>,
|
proxy: EventLoopProxy<EventLoopMessage<AppMessage>>,
|
||||||
windows: Windows<AppMessage>,
|
windows: Windows<AppMessage::Window>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AppMessage> Clone for App<AppMessage>
|
impl<AppMessage> Clone for App<AppMessage>
|
||||||
|
|
@ -154,6 +158,9 @@ pub trait Application<AppMessage>: private::ApplicationSealed<AppMessage>
|
||||||
where
|
where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
|
/// Returns a handle to the running application.
|
||||||
|
fn app(&self) -> App<AppMessage>;
|
||||||
|
|
||||||
/// Sends an app message to the main event loop to be handled by the
|
/// Sends an app message to the main event loop to be handled by the
|
||||||
/// callback provided when the app was created.
|
/// callback provided when the app was created.
|
||||||
///
|
///
|
||||||
|
|
@ -165,18 +172,25 @@ where
|
||||||
|
|
||||||
/// A message with an associated response type.
|
/// A message with an associated response type.
|
||||||
pub trait Message: Send + 'static {
|
pub trait Message: Send + 'static {
|
||||||
|
/// The message type that is able to be sent to individual windows.
|
||||||
|
type Window: Send;
|
||||||
/// The type returned when responding to this message.
|
/// The type returned when responding to this message.
|
||||||
type Response: Send;
|
type Response: Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message for () {
|
impl Message for () {
|
||||||
type Response = ();
|
type Response = ();
|
||||||
|
type Window = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AppMessage> Application<AppMessage> for PendingApp<AppMessage>
|
impl<AppMessage> Application<AppMessage> for PendingApp<AppMessage>
|
||||||
where
|
where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
|
fn app(&self) -> App<AppMessage> {
|
||||||
|
self.running.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn send(&mut self, message: AppMessage) -> Option<<AppMessage as Message>::Response> {
|
fn send(&mut self, message: AppMessage) -> Option<<AppMessage as Message>::Response> {
|
||||||
Some((self.message_callback)(message, &self.running.windows))
|
Some((self.message_callback)(message, &self.running.windows))
|
||||||
}
|
}
|
||||||
|
|
@ -186,14 +200,10 @@ impl<AppMessage> private::ApplicationSealed<AppMessage> for PendingApp<AppMessag
|
||||||
where
|
where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
fn app(&self) -> App<AppMessage> {
|
|
||||||
self.running.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn open(
|
fn open(
|
||||||
&self,
|
&self,
|
||||||
window: WindowAttributes,
|
window: WindowAttributes<AppMessage::Window>,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>,
|
||||||
) -> Result<Option<Arc<winit::window::Window>>, OsError> {
|
) -> Result<Option<Arc<winit::window::Window>>, OsError> {
|
||||||
self.running
|
self.running
|
||||||
.windows
|
.windows
|
||||||
|
|
@ -203,33 +213,27 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of open windows.
|
/// A collection of open windows.
|
||||||
pub struct Windows<AppMessage> {
|
pub struct Windows<Message> {
|
||||||
data: Arc<Mutex<HashMap<WindowId, OpenWindow>>>,
|
data: Arc<Mutex<HashMap<WindowId, OpenWindow<Message>>>>,
|
||||||
_message: PhantomData<AppMessage>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AppMessage> Default for Windows<AppMessage> {
|
impl<Message> Default for Windows<Message> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: Arc::default(),
|
data: Arc::default(),
|
||||||
_message: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AppMessage> Clone for Windows<AppMessage> {
|
impl<Message> Clone for Windows<Message> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: self.data.clone(),
|
data: self.data.clone(),
|
||||||
_message: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<AppMessage> Windows<AppMessage>
|
impl<Message> Windows<Message> {
|
||||||
where
|
|
||||||
AppMessage: 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 is
|
||||||
/// still open.
|
/// still open.
|
||||||
pub fn get(&self, id: WindowId) -> Option<Arc<winit::window::Window>> {
|
pub fn get(&self, id: WindowId) -> Option<Arc<winit::window::Window>> {
|
||||||
|
|
@ -238,12 +242,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn open(
|
fn open<AppMessage>(
|
||||||
&self,
|
&self,
|
||||||
target: &EventLoopWindowTarget<EventLoopMessage<AppMessage>>,
|
target: &EventLoopWindowTarget<EventLoopMessage<AppMessage>>,
|
||||||
attrs: WindowAttributes,
|
attrs: WindowAttributes<Message>,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage<Message>>,
|
||||||
) -> Result<Arc<winit::window::Window>, OsError> {
|
) -> Result<Arc<winit::window::Window>, OsError>
|
||||||
|
where
|
||||||
|
AppMessage: crate::Message<Window = Message>,
|
||||||
|
{
|
||||||
let mut builder = winit::window::WindowBuilder::new()
|
let mut builder = winit::window::WindowBuilder::new()
|
||||||
.with_active(attrs.active)
|
.with_active(attrs.active)
|
||||||
.with_resizable(attrs.resizable)
|
.with_resizable(attrs.resizable)
|
||||||
|
|
@ -297,7 +304,7 @@ where
|
||||||
Ok(winit)
|
Ok(winit)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&self, window: WindowId, message: WindowMessage) {
|
fn send(&self, window: WindowId, message: WindowMessage<Message>) {
|
||||||
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) {
|
||||||
|
|
@ -320,7 +327,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OpenWindow {
|
struct OpenWindow<User> {
|
||||||
winit: Arc<winit::window::Window>,
|
winit: Arc<winit::window::Window>,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage<User>>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,16 @@ use winit::event::{
|
||||||
use winit::window::{Theme, WindowId};
|
use winit::window::{Theme, WindowId};
|
||||||
|
|
||||||
use crate::window::WindowAttributes;
|
use crate::window::WindowAttributes;
|
||||||
use crate::{App, Message};
|
use crate::Message;
|
||||||
|
|
||||||
pub trait ApplicationSealed<AppMessage>
|
pub trait ApplicationSealed<AppMessage>
|
||||||
where
|
where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
fn app(&self) -> App<AppMessage>;
|
|
||||||
fn open(
|
fn open(
|
||||||
&self,
|
&self,
|
||||||
window: WindowAttributes,
|
window: WindowAttributes<AppMessage::Window>,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>,
|
||||||
) -> Result<Option<Arc<winit::window::Window>>, OsError>;
|
) -> Result<Option<Arc<winit::window::Window>>, OsError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,8 +28,8 @@ where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
OpenWindow {
|
OpenWindow {
|
||||||
attrs: WindowAttributes,
|
attrs: WindowAttributes<AppMessage::Window>,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>,
|
||||||
open_sender: mpsc::SyncSender<Result<Arc<winit::window::Window>, OsError>>,
|
open_sender: mpsc::SyncSender<Result<Arc<winit::window::Window>, OsError>>,
|
||||||
},
|
},
|
||||||
CloseWindow(WindowId),
|
CloseWindow(WindowId),
|
||||||
|
|
@ -42,8 +41,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum WindowMessage {
|
pub enum WindowMessage<User> {
|
||||||
Redraw,
|
Redraw,
|
||||||
|
User(User),
|
||||||
Event(WindowEvent),
|
Event(WindowEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
105
src/window.rs
105
src/window.rs
|
|
@ -18,17 +18,35 @@ use crate::private::{self, WindowEvent};
|
||||||
use crate::{App, Application, EventLoopMessage, Message, PendingApp, WindowMessage, Windows};
|
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(Debug, Clone)]
|
||||||
pub struct Window {
|
pub struct Window<Message> {
|
||||||
id: WindowId,
|
id: WindowId,
|
||||||
|
sender: mpsc::SyncSender<WindowMessage<Message>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
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 const fn id(&self) -> WindowId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sends a message to the window.
|
||||||
|
///
|
||||||
|
/// Returns `Ok` if the message was successfully sent. The message may not
|
||||||
|
/// be received even if this function returns `Ok`, if the window closes
|
||||||
|
/// between when the message was sent and when the message is received.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If the window is already closed, this function returns `Err(message)`.
|
||||||
|
pub fn send(&self, message: Message) -> Result<(), Message> {
|
||||||
|
match self.sender.send(WindowMessage::User(message)) {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(mpsc::SendError(WindowMessage::User(message))) => Err(message),
|
||||||
|
_ => unreachable!("same input as output"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A builder for a window.
|
/// A builder for a window.
|
||||||
|
|
@ -45,7 +63,7 @@ where
|
||||||
{
|
{
|
||||||
owner: &'a Application,
|
owner: &'a Application,
|
||||||
context: Behavior::Context,
|
context: Behavior::Context,
|
||||||
attributes: WindowAttributes,
|
attributes: WindowAttributes<AppMessage::Window>,
|
||||||
}
|
}
|
||||||
impl<'a, Behavior, Application, AppMessage> Deref
|
impl<'a, Behavior, Application, AppMessage> Deref
|
||||||
for WindowBuilder<'a, Behavior, Application, AppMessage>
|
for WindowBuilder<'a, Behavior, Application, AppMessage>
|
||||||
|
|
@ -53,7 +71,7 @@ where
|
||||||
Behavior: self::WindowBehavior<AppMessage>,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
type Target = WindowAttributes;
|
type Target = WindowAttributes<AppMessage::Window>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.attributes
|
&self.attributes
|
||||||
|
|
@ -72,7 +90,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct WindowAttributes {
|
pub struct WindowAttributes<ParentWindowEvent> {
|
||||||
pub inner_size: Option<Size>,
|
pub inner_size: Option<Size>,
|
||||||
pub min_inner_size: Option<Size>,
|
pub min_inner_size: Option<Size>,
|
||||||
pub max_inner_size: Option<Size>,
|
pub max_inner_size: Option<Size>,
|
||||||
|
|
@ -90,11 +108,11 @@ pub struct WindowAttributes {
|
||||||
pub resize_increments: Option<Size>,
|
pub resize_increments: Option<Size>,
|
||||||
pub content_protected: bool,
|
pub content_protected: bool,
|
||||||
pub window_level: WindowLevel,
|
pub window_level: WindowLevel,
|
||||||
pub parent_window: Option<Window>,
|
pub parent_window: Option<Window<ParentWindowEvent>>,
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WindowAttributes {
|
impl<User> Default for WindowAttributes<User> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let defaults = winit::window::WindowAttributes::default();
|
let defaults = winit::window::WindowAttributes::default();
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -145,18 +163,21 @@ 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`].
|
||||||
pub fn open(self) -> Result<Option<Window>, winit::error::OsError> {
|
pub fn open(self) -> Result<Option<Window<AppMessage::Window>>, winit::error::OsError> {
|
||||||
// The window's thread shouldn't ever block for long periods of time. To
|
// The window's thread shouldn't ever block for long periods of time. To
|
||||||
// avoid a "frozen" window causing massive memory allocations, we'll use
|
// avoid a "frozen" window causing massive memory allocations, we'll use
|
||||||
// a fixed-size channel and be cautious to not block the main event loop
|
// a fixed-size channel and be cautious to not block the main event loop
|
||||||
// by always using try_send.
|
// by always using try_send.
|
||||||
let (sender, receiver) = mpsc::sync_channel(1024);
|
let (sender, receiver) = mpsc::sync_channel(1024);
|
||||||
let Some(winit) = self.owner.open(self.attributes, sender)? else {
|
let Some(winit) = self.owner.open(self.attributes, sender.clone())? else {
|
||||||
return Ok(None)
|
return Ok(None)
|
||||||
};
|
};
|
||||||
let window = Window { id: winit.id() };
|
let window = Window {
|
||||||
|
id: winit.id(),
|
||||||
|
sender: sender.clone(),
|
||||||
|
};
|
||||||
let running_window = RunningWindow {
|
let running_window = RunningWindow {
|
||||||
messages: receiver,
|
messages: (sender, receiver),
|
||||||
responses: mpsc::sync_channel(1),
|
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),
|
||||||
|
|
@ -180,6 +201,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SyncChannel<T> = (mpsc::SyncSender<T>, mpsc::Receiver<T>);
|
||||||
|
|
||||||
/// A window that is running in its own thread.
|
/// A window that is running in its own thread.
|
||||||
pub struct RunningWindow<AppMessage>
|
pub struct RunningWindow<AppMessage>
|
||||||
where
|
where
|
||||||
|
|
@ -187,11 +210,8 @@ where
|
||||||
{
|
{
|
||||||
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: SyncChannel<WindowMessage<AppMessage::Window>>,
|
||||||
responses: (
|
responses: SyncChannel<AppMessage::Response>,
|
||||||
mpsc::SyncSender<AppMessage::Response>,
|
|
||||||
mpsc::Receiver<AppMessage::Response>,
|
|
||||||
),
|
|
||||||
app: App<AppMessage>,
|
app: App<AppMessage>,
|
||||||
inner_size: PhysicalSize<u32>,
|
inner_size: PhysicalSize<u32>,
|
||||||
location: PhysicalPosition<i32>,
|
location: PhysicalPosition<i32>,
|
||||||
|
|
@ -216,6 +236,15 @@ where
|
||||||
&self.window
|
&self.window
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a handle to this window.
|
||||||
|
#[must_use]
|
||||||
|
pub fn handle(&self) -> Window<AppMessage::Window> {
|
||||||
|
Window {
|
||||||
|
id: self.window.id(),
|
||||||
|
sender: self.messages.0.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the target for when the window will be redrawn.
|
/// Returns the target for when the window will be redrawn.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn next_redraw_target(&self) -> Option<RedrawTarget> {
|
pub const fn next_redraw_target(&self) -> Option<RedrawTarget> {
|
||||||
|
|
@ -340,7 +369,7 @@ where
|
||||||
// The scheduled redraw time has already elapsed, or we need to
|
// The scheduled redraw time has already elapsed, or we need to
|
||||||
// redraw. Process messages that are already enqueued, but don't
|
// redraw. Process messages that are already enqueued, but don't
|
||||||
// block.
|
// block.
|
||||||
TimeUntilRedraw::None => match self.messages.try_recv() {
|
TimeUntilRedraw::None => match self.messages.1.try_recv() {
|
||||||
Ok(message) => message,
|
Ok(message) => message,
|
||||||
Err(mpsc::TryRecvError::Disconnected) => return false,
|
Err(mpsc::TryRecvError::Disconnected) => return false,
|
||||||
Err(mpsc::TryRecvError::Empty) => return true,
|
Err(mpsc::TryRecvError::Empty) => return true,
|
||||||
|
|
@ -348,14 +377,14 @@ where
|
||||||
// We have a scheduled time for the next frame, and it hasn't
|
// We have a scheduled time for the next frame, and it hasn't
|
||||||
// elapsed yet.
|
// elapsed yet.
|
||||||
TimeUntilRedraw::Some(duration_remaining) => {
|
TimeUntilRedraw::Some(duration_remaining) => {
|
||||||
match self.messages.recv_timeout(duration_remaining) {
|
match self.messages.1.recv_timeout(duration_remaining) {
|
||||||
Ok(message) => message,
|
Ok(message) => message,
|
||||||
Err(mpsc::RecvTimeoutError::Timeout) => return true,
|
Err(mpsc::RecvTimeoutError::Timeout) => return true,
|
||||||
Err(mpsc::RecvTimeoutError::Disconnected) => return false,
|
Err(mpsc::RecvTimeoutError::Disconnected) => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No scheduled redraw time, sleep until the next message.
|
// No scheduled redraw time, sleep until the next message.
|
||||||
TimeUntilRedraw::Indefinite => match self.messages.recv() {
|
TimeUntilRedraw::Indefinite => match self.messages.1.recv() {
|
||||||
Ok(message) => message,
|
Ok(message) => message,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
},
|
},
|
||||||
|
|
@ -368,7 +397,11 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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<AppMessage::Window>,
|
||||||
|
behavior: &mut Behavior,
|
||||||
|
) -> bool
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior<AppMessage>,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
{
|
{
|
||||||
|
|
@ -376,6 +409,7 @@ where
|
||||||
WindowMessage::Redraw => {
|
WindowMessage::Redraw => {
|
||||||
self.set_needs_redraw();
|
self.set_needs_redraw();
|
||||||
}
|
}
|
||||||
|
WindowMessage::User(user) => behavior.event(self, user),
|
||||||
WindowMessage::Event(evt) => match evt {
|
WindowMessage::Event(evt) => match evt {
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
if behavior.close_requested(self) {
|
if behavior.close_requested(self) {
|
||||||
|
|
@ -569,6 +603,10 @@ impl<AppMessage> Application<AppMessage> for RunningWindow<AppMessage>
|
||||||
where
|
where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
|
fn app(&self) -> App<AppMessage> {
|
||||||
|
self.app.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn send(&mut self, message: AppMessage) -> Option<<AppMessage as Message>::Response> {
|
fn send(&mut self, message: AppMessage) -> Option<<AppMessage as Message>::Response> {
|
||||||
self.app
|
self.app
|
||||||
.proxy
|
.proxy
|
||||||
|
|
@ -585,14 +623,10 @@ impl<AppMessage> private::ApplicationSealed<AppMessage> for RunningWindow<AppMes
|
||||||
where
|
where
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
fn app(&self) -> App<AppMessage> {
|
|
||||||
self.app.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn open(
|
fn open(
|
||||||
&self,
|
&self,
|
||||||
attrs: WindowAttributes,
|
attrs: WindowAttributes<AppMessage::Window>,
|
||||||
sender: mpsc::SyncSender<WindowMessage>,
|
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>,
|
||||||
) -> Result<Option<Arc<winit::window::Window>>, OsError> {
|
) -> Result<Option<Arc<winit::window::Window>>, OsError> {
|
||||||
let (open_sender, open_receiver) = mpsc::sync_channel(1);
|
let (open_sender, open_receiver) = mpsc::sync_channel(1);
|
||||||
if self
|
if self
|
||||||
|
|
@ -688,7 +722,8 @@ where
|
||||||
/// [`Application::send`]. Each time a message is received by the main event
|
/// [`Application::send`]. Each time a message is received by the main event
|
||||||
/// loop, `app_callback` will be invoked.
|
/// loop, `app_callback` will be invoked.
|
||||||
fn run_with_event_callback(
|
fn run_with_event_callback(
|
||||||
app_callback: impl FnMut(AppMessage, &Windows<AppMessage>) -> AppMessage::Response + 'static,
|
app_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response
|
||||||
|
+ 'static,
|
||||||
) -> !
|
) -> !
|
||||||
where
|
where
|
||||||
Self::Context: Default,
|
Self::Context: Default,
|
||||||
|
|
@ -708,7 +743,8 @@ where
|
||||||
/// loop, `app_callback` will be invoked.
|
/// loop, `app_callback` will be invoked.
|
||||||
fn run_with_context_and_event_callback(
|
fn run_with_context_and_event_callback(
|
||||||
context: Self::Context,
|
context: Self::Context,
|
||||||
app_callback: impl FnMut(AppMessage, &Windows<AppMessage>) -> AppMessage::Response + 'static,
|
app_callback: impl FnMut(AppMessage, &Windows<AppMessage::Window>) -> AppMessage::Response
|
||||||
|
+ 'static,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
let app = PendingApp::new_with_event_callback(app_callback);
|
let app = PendingApp::new_with_event_callback(app_callback);
|
||||||
Self::open_with(&app, context).expect("error opening initial window");
|
Self::open_with(&app, context).expect("error opening initial window");
|
||||||
|
|
@ -725,7 +761,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>, OsError>
|
fn open<App>(app: &App) -> Result<Option<Window<AppMessage::Window>>, OsError>
|
||||||
where
|
where
|
||||||
App: Application<AppMessage>,
|
App: Application<AppMessage>,
|
||||||
Self::Context: Default,
|
Self::Context: Default,
|
||||||
|
|
@ -743,7 +779,10 @@ 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>(app: &App, context: Self::Context) -> Result<Option<Window>, OsError>
|
fn open_with<App>(
|
||||||
|
app: &App,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Result<Option<Window<AppMessage::Window>>, OsError>
|
||||||
where
|
where
|
||||||
App: Application<AppMessage>,
|
App: Application<AppMessage>,
|
||||||
{
|
{
|
||||||
|
|
@ -919,6 +958,10 @@ where
|
||||||
phase: TouchPhase,
|
phase: TouchPhase,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A user event has been received by the window.
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn event(&mut self, window: &mut RunningWindow<AppMessage>, event: AppMessage::Window) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Run: WindowBehavior<()> {
|
pub trait Run: WindowBehavior<()> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue