mirror of
https://github.com/danbulant/appit
synced 2026-06-24 17:11:54 +00:00
AsApplication + impl Application for App
This commit is contained in:
parent
a10c250683
commit
1e162ed8df
3 changed files with 93 additions and 10 deletions
|
|
@ -17,6 +17,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- This crate's default features now include `wayland-csd-adwaita`. This enables
|
- This crate's default features now include `wayland-csd-adwaita`. This enables
|
||||||
winit's built-in decoration drawing on Wayland.
|
winit's built-in decoration drawing on Wayland.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `App` now implements `Application`.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `AsApplication` is a new trait that can be implemented to resolve to the `App`
|
||||||
|
type. This allows wrapper types to be written that hide the appit types.
|
||||||
|
|
||||||
## v0.1.1 (2023-12-18)
|
## v0.1.1 (2023-12-18)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
||||||
72
src/lib.rs
72
src/lib.rs
|
|
@ -174,6 +174,27 @@ where
|
||||||
fn send(&mut self, message: AppMessage) -> Option<AppMessage::Response>;
|
fn send(&mut self, message: AppMessage) -> Option<AppMessage::Response>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A type that contains a reference to an [`Application`] implementor.
|
||||||
|
pub trait AsApplication<AppMessage> {
|
||||||
|
/// Returns this type's application.
|
||||||
|
fn as_application(&self) -> &dyn Application<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, AppMessage> AsApplication<AppMessage> for T
|
||||||
|
where
|
||||||
|
T: Application<AppMessage>,
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn as_application(&self) -> &dyn Application<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
/// The message type that is able to be sent to individual windows.
|
||||||
|
|
@ -216,6 +237,52 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> Application<AppMessage> for App<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn app(&self) -> App<AppMessage> {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send(&mut self, message: AppMessage) -> Option<<AppMessage as Message>::Response> {
|
||||||
|
let (response_sender, response_receiver) = mpsc::sync_channel(1);
|
||||||
|
self.proxy
|
||||||
|
.send_event(EventLoopMessage::User {
|
||||||
|
message,
|
||||||
|
response_sender,
|
||||||
|
})
|
||||||
|
.ok()?;
|
||||||
|
response_receiver.recv().ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AppMessage> private::ApplicationSealed<AppMessage> for App<AppMessage>
|
||||||
|
where
|
||||||
|
AppMessage: Message,
|
||||||
|
{
|
||||||
|
fn open(
|
||||||
|
&self,
|
||||||
|
attrs: WindowAttributes,
|
||||||
|
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>,
|
||||||
|
) -> Result<Option<Arc<winit::window::Window>>, OsError> {
|
||||||
|
let (open_sender, open_receiver) = mpsc::sync_channel(1);
|
||||||
|
if self
|
||||||
|
.proxy
|
||||||
|
.send_event(EventLoopMessage::OpenWindow {
|
||||||
|
attrs,
|
||||||
|
sender,
|
||||||
|
open_sender,
|
||||||
|
})
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
open_receiver.recv().map_or(Ok(None), |opt| opt.map(Some))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A collection of open windows.
|
/// A collection of open windows.
|
||||||
pub struct Windows<Message> {
|
pub struct Windows<Message> {
|
||||||
data: Arc<Mutex<HashMap<WindowId, OpenWindow<Message>>>>,
|
data: Arc<Mutex<HashMap<WindowId, OpenWindow<Message>>>>,
|
||||||
|
|
@ -282,8 +349,9 @@ impl<Message> Windows<Message> {
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
builder =
|
builder = winit::platform::windows::WindowBuilderExtWindows::with_class_name(
|
||||||
winit::platform::windows::WindowBuilderExtWindows::with_class_name(builder, app_name);
|
builder, app_name,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ use winit::keyboard::PhysicalKey;
|
||||||
use winit::window::{Fullscreen, Icon, Theme, WindowButtons, WindowId, WindowLevel};
|
use winit::window::{Fullscreen, Icon, Theme, WindowButtons, WindowId, WindowLevel};
|
||||||
|
|
||||||
use crate::private::{self, WindowEvent};
|
use crate::private::{self, WindowEvent};
|
||||||
use crate::{App, Application, EventLoopMessage, Message, PendingApp, WindowMessage, Windows};
|
use crate::{
|
||||||
|
App, Application, AsApplication, EventLoopMessage, Message, PendingApp, WindowMessage, Windows,
|
||||||
|
};
|
||||||
|
|
||||||
/// A weak reference to a running window.
|
/// A weak reference to a running window.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -175,7 +177,7 @@ impl Default for WindowAttributes {
|
||||||
impl<'a, Behavior, Application, AppMessage> WindowBuilder<'a, Behavior, Application, AppMessage>
|
impl<'a, Behavior, Application, AppMessage> WindowBuilder<'a, Behavior, Application, AppMessage>
|
||||||
where
|
where
|
||||||
Behavior: self::WindowBehavior<AppMessage>,
|
Behavior: self::WindowBehavior<AppMessage>,
|
||||||
Application: crate::Application<AppMessage>,
|
Application: crate::AsApplication<AppMessage>,
|
||||||
AppMessage: Message,
|
AppMessage: Message,
|
||||||
{
|
{
|
||||||
pub(crate) fn new(owner: &'a Application, context: Behavior::Context) -> Self {
|
pub(crate) fn new(owner: &'a Application, context: Behavior::Context) -> Self {
|
||||||
|
|
@ -202,7 +204,11 @@ where
|
||||||
// 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(65536);
|
let (sender, receiver) = mpsc::sync_channel(65536);
|
||||||
let Some(winit) = self.owner.open(self.attributes, sender.clone())? else {
|
let Some(winit) = self
|
||||||
|
.owner
|
||||||
|
.as_application()
|
||||||
|
.open(self.attributes, sender.clone())?
|
||||||
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let window = Window {
|
let window = Window {
|
||||||
|
|
@ -212,7 +218,7 @@ where
|
||||||
let running_window = RunningWindow {
|
let running_window = RunningWindow {
|
||||||
messages: (sender, receiver),
|
messages: (sender, receiver),
|
||||||
responses: mpsc::sync_channel(1),
|
responses: mpsc::sync_channel(1),
|
||||||
app: self.owner.app(),
|
app: self.owner.as_application().app(),
|
||||||
occluded: winit.is_visible().unwrap_or(false),
|
occluded: winit.is_visible().unwrap_or(false),
|
||||||
focused: winit.has_focus(),
|
focused: winit.has_focus(),
|
||||||
inner_size: winit.inner_size(),
|
inner_size: winit.inner_size(),
|
||||||
|
|
@ -761,7 +767,7 @@ where
|
||||||
/// initialized, a default [`Context`](Self::Context) will be passed.
|
/// initialized, a default [`Context`](Self::Context) will be passed.
|
||||||
fn build<App>(app: &App) -> WindowBuilder<'_, Self, App, AppMessage>
|
fn build<App>(app: &App) -> WindowBuilder<'_, Self, App, AppMessage>
|
||||||
where
|
where
|
||||||
App: Application<AppMessage>,
|
App: AsApplication<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())
|
||||||
|
|
@ -774,7 +780,7 @@ where
|
||||||
context: Self::Context,
|
context: Self::Context,
|
||||||
) -> WindowBuilder<'_, Self, App, AppMessage>
|
) -> WindowBuilder<'_, Self, App, AppMessage>
|
||||||
where
|
where
|
||||||
App: Application<AppMessage>,
|
App: AsApplication<AppMessage>,
|
||||||
{
|
{
|
||||||
WindowBuilder::new(app, context)
|
WindowBuilder::new(app, context)
|
||||||
}
|
}
|
||||||
|
|
@ -840,7 +846,7 @@ where
|
||||||
/// [`winit::window::WindowBuilder::build`].
|
/// [`winit::window::WindowBuilder::build`].
|
||||||
fn open<App>(app: &App) -> Result<Option<Window<AppMessage::Window>>, OsError>
|
fn open<App>(app: &App) -> Result<Option<Window<AppMessage::Window>>, OsError>
|
||||||
where
|
where
|
||||||
App: Application<AppMessage>,
|
App: AsApplication<AppMessage>,
|
||||||
Self::Context: Default,
|
Self::Context: Default,
|
||||||
{
|
{
|
||||||
Self::build(app).open()
|
Self::build(app).open()
|
||||||
|
|
@ -861,7 +867,7 @@ where
|
||||||
context: Self::Context,
|
context: Self::Context,
|
||||||
) -> Result<Option<Window<AppMessage::Window>>, OsError>
|
) -> Result<Option<Window<AppMessage::Window>>, OsError>
|
||||||
where
|
where
|
||||||
App: Application<AppMessage>,
|
App: AsApplication<AppMessage>,
|
||||||
{
|
{
|
||||||
Self::build_with(app, context).open()
|
Self::build_with(app, context).open()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue