use std::sync::mpsc;
use winit::{
event_loop::EventLoopWindowTarget,
monitor::MonitorHandle,
window::{
WindowBuilder,
WindowAttributes,
Window,
},
error::OsError,
};
pub trait Request: Sized + Send {
type Response: Send;
fn run(self, window_target: &EventLoopWindowTarget<()>) -> Self::Response;
}
pub struct RequestCallback<R: Request> {
pub request: R,
pub callback: mpsc::Sender<R::Response>,
}
impl<R: Request> RequestCallback<R> {
pub fn run_respond(self, window_target: &EventLoopWindowTarget<()>) {
let _ = self.callback.send(self.request.run(window_target));
}
}
pub struct GetAvailableMonitors;
impl Request for GetAvailableMonitors {
type Response = Vec<MonitorHandle>;
fn run(self, window_target: &EventLoopWindowTarget<()>) -> Self::Response {
window_target.available_monitors().collect()
}
}
pub struct GetPrimaryMonitor;
impl Request for GetPrimaryMonitor {
type Response = Option<MonitorHandle>;
fn run(self, window_target: &EventLoopWindowTarget<()>) -> Self::Response {
window_target.primary_monitor()
}
}
pub struct CreateWindow(pub WindowAttributes);
impl Request for CreateWindow {
type Response = Result<Window, OsError>;
fn run(self, window_target: &EventLoopWindowTarget<()>) -> Self::Response {
let CreateWindow(attributes) = self;
let mut builder = WindowBuilder::new();
builder.window = attributes;
builder.build(window_target)
}
}
macro_rules! request_message {
($($request:ident),*$(,)?)=>{
pub enum RequestMessage {
$( $request(RequestCallback<$request>), )*
}
impl RequestMessage {
pub fn run_respond(self, window_target: &EventLoopWindowTarget<()>) {
match self {
$(
RequestMessage::$request(inner) => {
inner.run_respond(window_target);
}
)*
}
}
}
$(
impl From<RequestCallback<$request>> for RequestMessage {
fn from(request_callback: RequestCallback<$request>) -> Self {
RequestMessage::$request(request_callback)
}
}
)*
};
}
request_message! {
GetAvailableMonitors,
GetPrimaryMonitor,
CreateWindow,
}