Open/close window events

This commit is contained in:
mars 2022-10-29 16:54:51 -06:00
parent 63691ebc28
commit e624edc36f
3 changed files with 86 additions and 34 deletions

View File

@ -9,4 +9,5 @@ glium = "0.32"
magpie-types = { path = "../../crates/magpie-types" }
mio = { version = "0.8", features = ["net", "os-poll"] }
mio-signals = "0.2"
parking_lot = "0.12"
slab = "0.4"

View File

@ -3,12 +3,14 @@ use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::str::from_utf8;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Arc;
use std::time::Duration;
use magpie_types::ServerMessenger;
use magpie_types::{CreatePanel, MagpieClientMsg, MagpieServerMsg, ServerMessenger};
use mio::net::{UnixListener, UnixStream};
use mio::{Events, Interest, Poll, Token, Waker};
use mio_signals::{Signal, Signals};
use parking_lot::RwLock;
use slab::Slab;
use crate::window::{WindowMessage, WindowMessageSender};
@ -51,24 +53,31 @@ impl DerefMut for Listener {
}
}
pub struct IpcData {
poll: Poll,
}
pub struct Client {
data: Arc<RwLock<IpcData>>,
window_sender: WindowMessageSender,
messenger: ServerMessenger<UnixStream>,
token: Token,
}
impl Client {
pub fn new(connection: UnixStream, token: Token) -> Self {
Self {
messenger: ServerMessenger::new(connection),
token,
}
}
pub fn on_readable(&mut self) -> std::io::Result<bool> {
self.messenger.flush_recv()?;
while let Some(msg) = self.messenger.recv() {
println!("Client #{}: {:?}", self.token.0, msg);
match msg {
MagpieServerMsg::CreatePanel(CreatePanel { id }) => {
let id = id as usize;
let msg = WindowMessage::OpenWindow { id };
let _ = self.window_sender.send_event(msg);
}
_ => unimplemented!(),
}
}
Ok(self.messenger.is_closed())
@ -76,9 +85,9 @@ impl Client {
}
pub struct Ipc {
pub message_recv: Receiver<IpcMessage>,
pub data: Arc<RwLock<IpcData>>,
pub window_sender: WindowMessageSender,
pub poll: Poll,
pub message_recv: Receiver<IpcMessage>,
pub events: Events,
pub quit: bool,
pub listener: Listener,
@ -121,10 +130,12 @@ impl Ipc {
sender,
};
let data = IpcData { poll };
let ipc = Self {
message_recv,
data: Arc::new(RwLock::new(data)),
window_sender,
poll,
message_recv,
events,
quit: false,
listener,
@ -139,7 +150,7 @@ impl Ipc {
}
pub fn poll(&mut self, timeout: Option<Duration>) -> std::io::Result<()> {
self.poll.poll(&mut self.events, timeout)?;
self.data.write().poll.poll(&mut self.events, timeout)?;
for event in self.events.iter() {
if event.token() == self.listener_token {
@ -153,12 +164,18 @@ impl Ipc {
);
let interest = Interest::READABLE;
self.poll
.registry()
.register(&mut connection, token, interest)?;
self.data.write().poll.registry().register(
&mut connection,
token,
interest,
)?;
let client = Client::new(connection, token);
self.clients.insert(client);
self.clients.insert(Client {
messenger: ServerMessenger::new(connection),
token,
data: self.data.clone(),
window_sender: self.window_sender.clone(),
});
}
Err(ref err) if err.kind() == std::io::ErrorKind::WouldBlock => break,
Err(err) => return Err(err),
@ -175,7 +192,11 @@ impl Ipc {
if disconnected {
println!("Client #{} disconnected", event.token().0);
let mut client = self.clients.remove(event.token().0);
self.poll.registry().deregister(&mut client.messenger.transport)?;
self.data
.write()
.poll
.registry()
.deregister(&mut client.messenger.transport)?;
}
} else {
panic!("Unrecognized event token: {:?}", event);

View File

@ -1,15 +1,17 @@
use std::collections::HashMap;
use glium::backend::glutin::DisplayCreationError;
use glium::glutin;
use glium::{glutin, Surface};
use glutin::event::{Event, WindowEvent};
use glutin::event_loop::{ControlFlow, EventLoop, EventLoopProxy};
use glutin::event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindowTarget};
use glutin::window::WindowId;
use crate::gl::Graphics;
use crate::ipc::{IpcMessage, IpcMessageSender};
pub enum WindowMessage {
OpenWindow { id: usize },
CloseWindow { id: usize },
Quit,
}
@ -21,7 +23,9 @@ pub struct Window {
}
impl Window {
pub fn new(event_loop: &EventLoop<()>) -> Result<Self, DisplayCreationError> {
pub fn new(
event_loop: &EventLoopWindowTarget<WindowMessage>,
) -> Result<Self, DisplayCreationError> {
let wb = glutin::window::WindowBuilder::new();
let cb = glutin::ContextBuilder::new();
let display = glium::Display::new(wb, cb, &event_loop)?;
@ -29,10 +33,15 @@ impl Window {
Ok(Self { display, graphics })
}
pub fn request_redraw(&mut self) {
self.display.gl_window().window().request_redraw();
}
}
pub struct WindowStore {
pub ipc_sender: IpcMessageSender,
pub ipc_to_window: HashMap<usize, WindowId>,
pub windows: HashMap<WindowId, Window>,
}
@ -40,23 +49,44 @@ impl WindowStore {
pub fn new(ipc_sender: IpcMessageSender) -> Self {
Self {
ipc_sender,
ipc_to_window: Default::default(),
windows: Default::default(),
}
}
pub fn run(self, event_loop: EventLoop<WindowMessage>) -> ! {
event_loop.run(move |event, event_loop, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent { window_id, event } => match event {
_ => {}
},
Event::MainEventsCleared => {}
Event::UserEvent(event) => match event {
WindowMessage::Quit => *control_flow = ControlFlow::Exit,
},
_ => {}
pub fn run(mut self, event_loop: EventLoop<WindowMessage>) -> ! {
event_loop.run(move |event, event_loop, control_flow| match event {
Event::WindowEvent { window_id, event } => {
if let Some(window) = self.windows.get_mut(&window_id) {
match event {
WindowEvent::Resized(_) => window.request_redraw(),
_ => {}
}
}
}
Event::RedrawRequested(id) => {
if let Some(window) = self.windows.get(&id) {
let mut target = window.display.draw();
target.clear_color(0.0, 0.0, 0.0, 1.0);
target.finish().unwrap();
}
}
Event::UserEvent(event) => match event {
WindowMessage::OpenWindow { id } => {
println!("Opening window {}", id);
let window = Window::new(&event_loop).unwrap();
let window_id = window.display.gl_window().window().id();
self.windows.insert(window_id, window);
self.ipc_to_window.insert(id, window_id);
}
WindowMessage::CloseWindow { id } => {
if let Some(window_id) = self.ipc_to_window.remove(&id) {
self.windows.remove(&window_id);
}
}
WindowMessage::Quit => *control_flow = ControlFlow::Exit,
},
_ => {}
});
}
}