platform.rs

  1#![allow(unused)]
  2
  3use crate::{
  4    Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
  5    ForegroundExecutor, Keymap, LinuxDispatcher, LinuxDisplay, LinuxTextSystem, LinuxWindow, Menu,
  6    PathPromptOptions, Platform, PlatformDisplay, PlatformInput, PlatformTextSystem,
  7    PlatformWindow, Result, SemanticVersion, Task, WindowOptions,
  8};
  9
 10use futures::channel::oneshot;
 11use parking_lot::Mutex;
 12
 13use std::{
 14    path::{Path, PathBuf},
 15    rc::Rc,
 16    sync::Arc,
 17    time::Duration,
 18};
 19use time::UtcOffset;
 20use x11rb::{connection::Connection as _, rust_connection::RustConnection};
 21
 22pub(crate) struct LinuxPlatform(Mutex<LinuxPlatformState>);
 23
 24pub(crate) struct LinuxPlatformState {
 25    x11_connection: RustConnection,
 26    x11_root_index: usize,
 27    gpu: Arc<blade::Context>,
 28    background_executor: BackgroundExecutor,
 29    foreground_executor: ForegroundExecutor,
 30    text_system: Arc<LinuxTextSystem>,
 31}
 32
 33impl Default for LinuxPlatform {
 34    fn default() -> Self {
 35        Self::new()
 36    }
 37}
 38
 39impl LinuxPlatform {
 40    pub(crate) fn new() -> Self {
 41        let (x11_connection, x11_root_index) = x11rb::connect(None).unwrap();
 42
 43        let dispatcher = Arc::new(LinuxDispatcher::new());
 44        let gpu = Arc::new(
 45            unsafe {
 46                blade::Context::init(blade::ContextDesc {
 47                    validation: cfg!(debug_assertions),
 48                    capture: false,
 49                })
 50            }
 51            .unwrap(),
 52        );
 53
 54        Self(Mutex::new(LinuxPlatformState {
 55            x11_connection,
 56            x11_root_index,
 57            gpu,
 58            background_executor: BackgroundExecutor::new(dispatcher.clone()),
 59            foreground_executor: ForegroundExecutor::new(dispatcher),
 60            text_system: Arc::new(LinuxTextSystem::new()),
 61        }))
 62    }
 63}
 64
 65impl Platform for LinuxPlatform {
 66    fn background_executor(&self) -> BackgroundExecutor {
 67        self.0.lock().background_executor.clone()
 68    }
 69
 70    fn foreground_executor(&self) -> crate::ForegroundExecutor {
 71        self.0.lock().foreground_executor.clone()
 72    }
 73
 74    fn text_system(&self) -> Arc<dyn PlatformTextSystem> {
 75        self.0.lock().text_system.clone()
 76    }
 77
 78    fn run(&self, on_finish_launching: Box<dyn FnOnce()>) {
 79        on_finish_launching()
 80    }
 81
 82    fn quit(&self) {}
 83
 84    fn restart(&self) {}
 85
 86    fn activate(&self, ignoring_other_apps: bool) {}
 87
 88    fn hide(&self) {}
 89
 90    fn hide_other_apps(&self) {}
 91
 92    fn unhide_other_apps(&self) {}
 93
 94    fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
 95        let lock = self.0.lock();
 96        let setup = lock.x11_connection.setup();
 97        (0..setup.roots.len())
 98            .map(|id| {
 99                Rc::new(LinuxDisplay::new(&lock.x11_connection, id)) as Rc<dyn PlatformDisplay>
100            })
101            .collect()
102    }
103
104    fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
105        let lock = self.0.lock();
106        Some(Rc::new(LinuxDisplay::new(
107            &lock.x11_connection,
108            id.0 as usize,
109        )))
110    }
111
112    fn active_window(&self) -> Option<AnyWindowHandle> {
113        None
114    }
115
116    fn open_window(
117        &self,
118        handle: AnyWindowHandle,
119        options: WindowOptions,
120    ) -> Box<dyn PlatformWindow> {
121        let lock = self.0.lock();
122        Box::new(LinuxWindow::new(
123            options,
124            handle,
125            &lock.x11_connection,
126            lock.x11_root_index,
127            &lock.gpu,
128        ))
129    }
130
131    fn set_display_link_output_callback(
132        &self,
133        display_id: DisplayId,
134        callback: Box<dyn FnMut() + Send>,
135    ) {
136        unimplemented!()
137    }
138
139    fn start_display_link(&self, display_id: DisplayId) {}
140
141    fn stop_display_link(&self, display_id: DisplayId) {}
142
143    fn open_url(&self, url: &str) {}
144
145    fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {}
146
147    fn prompt_for_paths(
148        &self,
149        options: PathPromptOptions,
150    ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
151        unimplemented!()
152    }
153
154    fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
155        unimplemented!()
156    }
157
158    fn reveal_path(&self, path: &Path) {}
159
160    fn on_become_active(&self, callback: Box<dyn FnMut()>) {}
161
162    fn on_resign_active(&self, callback: Box<dyn FnMut()>) {}
163
164    fn on_quit(&self, callback: Box<dyn FnMut()>) {}
165
166    fn on_reopen(&self, callback: Box<dyn FnMut()>) {}
167
168    fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {}
169
170    fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>) {}
171
172    fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>) {}
173
174    fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {}
175
176    fn os_name(&self) -> &'static str {
177        "Linux"
178    }
179
180    fn double_click_interval(&self) -> Duration {
181        Duration::default()
182    }
183
184    fn os_version(&self) -> Result<SemanticVersion> {
185        Ok(SemanticVersion {
186            major: 1,
187            minor: 0,
188            patch: 0,
189        })
190    }
191
192    fn app_version(&self) -> Result<SemanticVersion> {
193        Ok(SemanticVersion {
194            major: 1,
195            minor: 0,
196            patch: 0,
197        })
198    }
199
200    fn app_path(&self) -> Result<PathBuf> {
201        unimplemented!()
202    }
203
204    fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap) {}
205
206    fn local_timezone(&self) -> UtcOffset {
207        UtcOffset::UTC
208    }
209
210    fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
211        unimplemented!()
212    }
213
214    fn set_cursor_style(&self, style: CursorStyle) {}
215
216    fn should_auto_hide_scrollbars(&self) -> bool {
217        false
218    }
219
220    fn write_to_clipboard(&self, item: ClipboardItem) {}
221
222    fn read_from_clipboard(&self) -> Option<ClipboardItem> {
223        None
224    }
225
226    fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task<Result<()>> {
227        unimplemented!()
228    }
229
230    fn read_credentials(&self, url: &str) -> Task<Result<Option<(String, Vec<u8>)>>> {
231        unimplemented!()
232    }
233
234    fn delete_credentials(&self, url: &str) -> Task<Result<()>> {
235        unimplemented!()
236    }
237}
238
239#[cfg(test)]
240mod tests {
241    use crate::ClipboardItem;
242
243    use super::*;
244
245    fn build_platform() -> LinuxPlatform {
246        let platform = LinuxPlatform::new();
247        platform
248    }
249}