Add Linux platform, gate usage of CVImageBuffer by macOS

Dzmitry Malyshau created

Change summary

crates/gpui/build.rs                       |   6 
crates/gpui/src/elements/img.rs            |   4 
crates/gpui/src/platform.rs                |   8 
crates/gpui/src/platform/linux.rs          |   3 
crates/gpui/src/platform/linux/platform.rs | 242 ++++++++++++++++++++++++
crates/gpui/src/scene.rs                   |   1 
crates/gpui/src/window/element_cx.rs       |   6 
7 files changed, 265 insertions(+), 5 deletions(-)

Detailed changes

crates/gpui/build.rs 🔗

@@ -7,14 +7,14 @@ use cbindgen::Config;
 
 fn main() {
     //generate_dispatch_bindings();
-    let header_path = generate_shader_bindings();
+    let _header_path = generate_shader_bindings();
     //#[cfg(feature = "runtime_shaders")]
     //emit_stitched_shaders(&header_path);
     //#[cfg(not(feature = "runtime_shaders"))]
     //compile_metal_shaders(&header_path);
 }
 
-fn generate_dispatch_bindings() {
+fn _generate_dispatch_bindings() {
     println!("cargo:rustc-link-lib=framework=System");
     println!("cargo:rerun-if-changed=src/platform/mac/dispatch.h");
 
@@ -116,7 +116,7 @@ fn emit_stitched_shaders(header_path: &Path) {
     println!("cargo:rerun-if-changed={}", &shader_source_path);
 }
 #[cfg(not(feature = "runtime_shaders"))]
-fn compile_metal_shaders(header_path: &Path) {
+fn _compile_metal_shaders(header_path: &Path) {
     use std::process::{self, Command};
     let shader_path = "./src/platform/mac/shaders.metal";
     let air_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.air");

crates/gpui/src/elements/img.rs 🔗

@@ -7,6 +7,7 @@ use crate::{
     StyleRefinement, Styled, UriOrPath,
 };
 use futures::FutureExt;
+#[cfg(target_os = "macos")]
 use media::core_video::CVImageBuffer;
 use util::ResultExt;
 
@@ -21,6 +22,7 @@ pub enum ImageSource {
     Data(Arc<ImageData>),
     // TODO: move surface definitions into mac platform module
     /// A CoreVideo image buffer
+    #[cfg(target_os = "macos")]
     Surface(CVImageBuffer),
 }
 
@@ -54,6 +56,7 @@ impl From<Arc<ImageData>> for ImageSource {
     }
 }
 
+#[cfg(target_os = "macos")]
 impl From<CVImageBuffer> for ImageSource {
     fn from(value: CVImageBuffer) -> Self {
         Self::Surface(value)
@@ -144,6 +147,7 @@ impl Element for Img {
                                 .log_err();
                         }
 
+                        #[cfg(target_os = "macos")]
                         ImageSource::Surface(surface) => {
                             let size = size(surface.width().into(), surface.height().into());
                             let new_bounds = preserve_aspect_ratio(bounds, size);

crates/gpui/src/platform.rs 🔗

@@ -2,6 +2,8 @@ mod app_menu;
 mod keystroke;
 #[cfg(target_os = "macos")]
 mod mac;
+#[cfg(target_os = "linux")]
+mod linux;
 #[cfg(any(test, feature = "test-support"))]
 mod test;
 
@@ -35,6 +37,8 @@ pub use app_menu::*;
 pub use keystroke::*;
 #[cfg(target_os = "macos")]
 pub(crate) use mac::*;
+#[cfg(target_os = "linux")]
+pub(crate) use linux::*;
 #[cfg(any(test, feature = "test-support"))]
 pub(crate) use test::*;
 use time::UtcOffset;
@@ -44,6 +48,10 @@ pub use util::SemanticVersion;
 pub(crate) fn current_platform() -> Rc<dyn Platform> {
     Rc::new(MacPlatform::new())
 }
+#[cfg(target_os = "linux")]
+pub(crate) fn current_platform() -> Rc<dyn Platform> {
+    Rc::new(LinuxPlatform::new())
+}
 
 pub(crate) trait Platform: 'static {
     fn background_executor(&self) -> BackgroundExecutor;

crates/gpui/src/platform/linux/platform.rs 🔗

@@ -0,0 +1,242 @@
+#![allow(unused)]
+
+use crate::{
+    Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
+    Keymap, Menu, PathPromptOptions, Platform, PlatformDisplay, PlatformInput,
+    PlatformTextSystem, PlatformWindow, Result, SemanticVersion, Task, WindowOptions,
+};
+
+use futures::channel::oneshot;
+use parking_lot::Mutex;
+
+use std::{
+    path::{Path, PathBuf},
+    rc::Rc,
+    sync::Arc,
+    time::Duration,
+};
+use time::UtcOffset;
+
+
+pub(crate) struct LinuxPlatform(Mutex<LinuxPlatformState>);
+
+pub(crate) struct LinuxPlatformState {
+}
+
+impl Default for LinuxPlatform {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl LinuxPlatform {
+    pub(crate) fn new() -> Self {
+        Self(Mutex::new(LinuxPlatformState {
+        }))
+    }
+}
+
+impl Platform for LinuxPlatform {
+    fn background_executor(&self) -> BackgroundExecutor {
+        unimplemented!()
+    }
+
+    fn foreground_executor(&self) -> crate::ForegroundExecutor {
+        unimplemented!()
+    }
+
+    fn text_system(&self) -> Arc<dyn PlatformTextSystem> {
+        unimplemented!()
+    }
+
+    fn run(&self, on_finish_launching: Box<dyn FnOnce()>) {
+        unimplemented!()
+    }
+
+    fn quit(&self) {
+        unimplemented!()
+    }
+
+    fn restart(&self) {
+        unimplemented!()
+    }
+
+    fn activate(&self, ignoring_other_apps: bool) {
+        unimplemented!()
+    }
+
+    fn hide(&self) {
+        unimplemented!()
+    }
+
+    fn hide_other_apps(&self) {
+        unimplemented!()
+    }
+
+    fn unhide_other_apps(&self) {
+        unimplemented!()
+    }
+
+    fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
+        unimplemented!()
+    }
+
+    fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
+        unimplemented!()
+    }
+
+    fn active_window(&self) -> Option<AnyWindowHandle> {
+        unimplemented!()
+    }
+
+    fn open_window(
+        &self,
+        handle: AnyWindowHandle,
+        options: WindowOptions,
+    ) -> Box<dyn PlatformWindow> {
+        unimplemented!()
+    }
+
+    fn set_display_link_output_callback(
+        &self,
+        display_id: DisplayId,
+        callback: Box<dyn FnMut() + Send>,
+    ) {
+        unimplemented!()
+    }
+
+    fn start_display_link(&self, display_id: DisplayId) {
+        unimplemented!()
+    }
+
+    fn stop_display_link(&self, display_id: DisplayId) {
+        unimplemented!()
+    }
+
+    fn open_url(&self, url: &str) {
+        unimplemented!()
+    }
+
+    fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {
+        unimplemented!()
+    }
+
+    fn prompt_for_paths(
+        &self,
+        options: PathPromptOptions,
+    ) -> oneshot::Receiver<Option<Vec<PathBuf>>> {
+        unimplemented!()
+    }
+
+    fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Option<PathBuf>> {
+        unimplemented!()
+    }
+
+    fn reveal_path(&self, path: &Path) {
+        unimplemented!()
+    }
+
+    fn on_become_active(&self, callback: Box<dyn FnMut()>) {
+        unimplemented!()
+    }
+
+    fn on_resign_active(&self, callback: Box<dyn FnMut()>) {
+        unimplemented!()
+    }
+
+    fn on_quit(&self, callback: Box<dyn FnMut()>) {
+        unimplemented!()
+    }
+
+    fn on_reopen(&self, callback: Box<dyn FnMut()>) {
+        unimplemented!()
+    }
+
+    fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {
+        unimplemented!()
+    }
+
+    fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>) {
+        unimplemented!()
+    }
+
+    fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>) {
+        unimplemented!()
+    }
+
+    fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
+        unimplemented!()
+    }
+
+    fn os_name(&self) -> &'static str {
+        "Linux"
+    }
+
+    fn double_click_interval(&self) -> Duration {
+        unimplemented!()
+    }
+
+    fn os_version(&self) -> Result<SemanticVersion> {
+        unimplemented!()
+    }
+
+    fn app_version(&self) -> Result<SemanticVersion> {
+        unimplemented!()
+    }
+
+    fn app_path(&self) -> Result<PathBuf> {
+        unimplemented!()
+    }
+
+    fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap) {
+        unimplemented!()
+    }
+
+    fn local_timezone(&self) -> UtcOffset {
+        unimplemented!()
+    }
+
+    fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
+        unimplemented!()
+    }
+
+    fn set_cursor_style(&self, style: CursorStyle) {
+        unimplemented!()
+    }
+
+    fn should_auto_hide_scrollbars(&self) -> bool {
+        unimplemented!()
+    }
+
+    fn write_to_clipboard(&self, item: ClipboardItem) {
+        unimplemented!()
+    }
+
+    fn read_from_clipboard(&self) -> Option<ClipboardItem> {
+        unimplemented!()
+    }
+
+    fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task<Result<()>> {
+        unimplemented!()
+    }
+
+    fn read_credentials(&self, url: &str) -> Task<Result<Option<(String, Vec<u8>)>>> {
+        unimplemented!()
+    }
+
+    fn delete_credentials(&self, url: &str) -> Task<Result<()>> {
+        unimplemented!()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::ClipboardItem;
+
+    use super::*;
+
+    fn build_platform() -> LinuxPlatform {
+        let platform = LinuxPlatform::new();
+        platform
+    }
+}

crates/gpui/src/scene.rs 🔗

@@ -671,6 +671,7 @@ pub(crate) struct Surface {
     pub order: DrawOrder,
     pub bounds: Bounds<ScaledPixels>,
     pub content_mask: ContentMask<ScaledPixels>,
+    #[cfg(target_os = "macos")]
     pub image_buffer: media::core_video::CVImageBuffer,
 }
 

crates/gpui/src/window/element_cx.rs 🔗

@@ -23,6 +23,7 @@ use std::{
 use anyhow::Result;
 use collections::{FxHashMap, FxHashSet};
 use derive_more::{Deref, DerefMut};
+#[cfg(target_os = "macos")]
 use media::core_video::CVImageBuffer;
 use smallvec::SmallVec;
 use util::post_inc;
@@ -34,7 +35,7 @@ use crate::{
     InputHandler, IsZero, KeyContext, KeyEvent, KeymatchMode, LayoutId, MonochromeSprite,
     MouseEvent, PaintQuad, Path, Pixels, PlatformInputHandler, Point, PolychromeSprite, Quad,
     RenderGlyphParams, RenderImageParams, RenderSvgParams, Scene, Shadow, SharedString, Size,
-    StackingContext, StackingOrder, Style, Surface, TextStyleRefinement, Underline, UnderlineStyle,
+    StackingContext, StackingOrder, Style, TextStyleRefinement, Underline, UnderlineStyle,
     Window, WindowContext, SUBPIXEL_VARIANTS,
 };
 
@@ -962,6 +963,7 @@ impl<'a> ElementContext<'a> {
     }
 
     /// Paint a surface into the scene for the next frame at the current z-index.
+    #[cfg(target_os = "macos")]
     pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
         let scale_factor = self.scale_factor();
         let bounds = bounds.scale(scale_factor);
@@ -970,7 +972,7 @@ impl<'a> ElementContext<'a> {
         let window = &mut *self.window;
         window.next_frame.scene.insert(
             &window.next_frame.z_index_stack,
-            Surface {
+            crate::Surface {
                 view_id: view_id.into(),
                 layer_id: 0,
                 order: 0,