client.rs

  1use std::cell::RefCell;
  2use std::ops::Deref;
  3use std::rc::Rc;
  4use std::time::{Duration, Instant};
  5
  6use calloop::{EventLoop, LoopHandle};
  7use collections::HashMap;
  8
  9use util::ResultExt;
 10
 11use crate::platform::linux::LinuxClient;
 12use crate::platform::{LinuxCommon, PlatformWindow};
 13use crate::{
 14    px, AnyWindowHandle, Bounds, CursorStyle, DisplayId, Modifiers, ModifiersChangedEvent, Pixels,
 15    PlatformDisplay, PlatformInput, Point, ScrollDelta, Size, TouchPhase, WindowParams,
 16};
 17
 18use calloop::{
 19    generic::{FdWrapper, Generic},
 20    RegistrationToken,
 21};
 22
 23pub struct HeadlessClientState {
 24    pub(crate) loop_handle: LoopHandle<'static, HeadlessClient>,
 25    pub(crate) event_loop: Option<calloop::EventLoop<'static, HeadlessClient>>,
 26    pub(crate) common: LinuxCommon,
 27}
 28
 29#[derive(Clone)]
 30pub(crate) struct HeadlessClient(Rc<RefCell<HeadlessClientState>>);
 31
 32impl HeadlessClient {
 33    pub(crate) fn new() -> Self {
 34        let event_loop = EventLoop::try_new().unwrap();
 35
 36        let (common, main_receiver) = LinuxCommon::new(event_loop.get_signal());
 37
 38        let handle = event_loop.handle();
 39
 40        handle.insert_source(main_receiver, |event, _, _: &mut HeadlessClient| {
 41            if let calloop::channel::Event::Msg(runnable) = event {
 42                runnable.run();
 43            }
 44        });
 45
 46        HeadlessClient(Rc::new(RefCell::new(HeadlessClientState {
 47            event_loop: Some(event_loop),
 48            loop_handle: handle,
 49            common,
 50        })))
 51    }
 52}
 53
 54impl LinuxClient for HeadlessClient {
 55    fn with_common<R>(&self, f: impl FnOnce(&mut LinuxCommon) -> R) -> R {
 56        f(&mut self.0.borrow_mut().common)
 57    }
 58
 59    fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
 60        vec![]
 61    }
 62
 63    fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
 64        None
 65    }
 66
 67    fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
 68        None
 69    }
 70
 71    fn open_window(
 72        &self,
 73        _handle: AnyWindowHandle,
 74        params: WindowParams,
 75    ) -> Box<dyn PlatformWindow> {
 76        unimplemented!()
 77    }
 78
 79    fn set_cursor_style(&self, _style: CursorStyle) {}
 80
 81    fn open_uri(&self, _uri: &str) {}
 82
 83    fn write_to_primary(&self, item: crate::ClipboardItem) {}
 84
 85    fn write_to_clipboard(&self, item: crate::ClipboardItem) {}
 86
 87    fn read_from_primary(&self) -> Option<crate::ClipboardItem> {
 88        None
 89    }
 90
 91    fn read_from_clipboard(&self) -> Option<crate::ClipboardItem> {
 92        None
 93    }
 94
 95    fn run(&self) {
 96        let mut event_loop = self
 97            .0
 98            .borrow_mut()
 99            .event_loop
100            .take()
101            .expect("App is already running");
102
103        event_loop.run(None, &mut self.clone(), |_| {}).log_err();
104    }
105}