1653 lines · 50.2 KB · Rust
RawDownload
// todo(windows): remove#![cfg_attr(windows, allow(dead_code))] mod app_menu;mod keystroke; #[cfg(any(target_os = "linux", target_os = "freebsd"))]mod linux; #[cfg(target_os = "macos")]mod mac; #[cfg(any(    all(        any(target_os = "linux", target_os = "freebsd"),        any(feature = "x11", feature = "wayland")    ),    target_os = "windows",    feature = "macos-blade"))]mod blade; #[cfg(any(test, feature = "test-support"))]mod test; #[cfg(target_os = "windows")]mod windows; #[cfg(all(    any(target_os = "linux", target_os = "freebsd"),    any(feature = "wayland", feature = "x11"),))]pub(crate) mod scap_screen_capture; use crate::{    Action, AnyWindowHandle, App, AsyncWindowContext, BackgroundExecutor, Bounds,    DEFAULT_WINDOW_SIZE, DevicePixels, DispatchEventResult, Font, FontId, FontMetrics, FontRun,    ForegroundExecutor, GlyphId, GpuSpecs, ImageSource, Keymap, LineLayout, Pixels, PlatformInput,    Point, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, ScaledPixels, Scene,    ShapedGlyph, ShapedRun, SharedString, Size, SvgRenderer, SvgSize, Task, TaskLabel, Window,    point, px, size,};use anyhow::Result;use async_task::Runnable;use futures::channel::oneshot;use image::codecs::gif::GifDecoder;use image::{AnimationDecoder as _, Frame};use parking::Unparker;use raw_window_handle::{HasDisplayHandle, HasWindowHandle};use seahash::SeaHasher;use serde::{Deserialize, Serialize};use smallvec::SmallVec;use std::borrow::Cow;use std::hash::{Hash, Hasher};use std::io::Cursor;use std::ops;use std::time::{Duration, Instant};use std::{    fmt::{self, Debug},    ops::Range,    path::{Path, PathBuf},    rc::Rc,    sync::Arc,};use strum::EnumIter;use uuid::Uuid; pub use app_menu::*;pub use keystroke::*; #[cfg(any(target_os = "linux", target_os = "freebsd"))]pub(crate) use linux::*;#[cfg(target_os = "macos")]pub(crate) use mac::*;pub use semantic_version::SemanticVersion;#[cfg(any(test, feature = "test-support"))]pub(crate) use test::*;#[cfg(target_os = "windows")]pub(crate) use windows::*; #[cfg(any(test, feature = "test-support"))]pub use test::TestScreenCaptureSource; /// Returns a background executor for the current platform.pub fn background_executor() -> BackgroundExecutor {    current_platform(true).background_executor()} #[cfg(target_os = "macos")]pub(crate) fn current_platform(headless: bool) -> Rc<dyn Platform> {    Rc::new(MacPlatform::new(headless))} #[cfg(any(target_os = "linux", target_os = "freebsd"))]pub(crate) fn current_platform(headless: bool) -> Rc<dyn Platform> {    if headless {        return Rc::new(HeadlessClient::new());    }     match guess_compositor() {        #[cfg(feature = "wayland")]        "Wayland" => Rc::new(WaylandClient::new()),         #[cfg(feature = "x11")]        "X11" => Rc::new(X11Client::new()),         "Headless" => Rc::new(HeadlessClient::new()),        _ => unreachable!(),    }} /// Return which compositor we're guessing we'll use./// Does not attempt to connect to the given compositor#[cfg(any(target_os = "linux", target_os = "freebsd"))]#[inline]pub fn guess_compositor() -> &'static str {    if std::env::var_os("ZED_HEADLESS").is_some() {        return "Headless";    }     #[cfg(feature = "wayland")]    let wayland_display = std::env::var_os("WAYLAND_DISPLAY");    #[cfg(not(feature = "wayland"))]    let wayland_display: Option<std::ffi::OsString> = None;     #[cfg(feature = "x11")]    let x11_display = std::env::var_os("DISPLAY");    #[cfg(not(feature = "x11"))]    let x11_display: Option<std::ffi::OsString> = None;     let use_wayland = wayland_display.is_some_and(|display| !display.is_empty());    let use_x11 = x11_display.is_some_and(|display| !display.is_empty());     if use_wayland {        "Wayland"    } else if use_x11 {        "X11"    } else {        "Headless"    }} #[cfg(target_os = "windows")]pub(crate) fn current_platform(_headless: bool) -> Rc<dyn Platform> {    Rc::new(WindowsPlatform::new())} pub(crate) trait Platform: 'static {    fn background_executor(&self) -> BackgroundExecutor;    fn foreground_executor(&self) -> ForegroundExecutor;    fn text_system(&self) -> Arc<dyn PlatformTextSystem>;     fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>);    fn quit(&self);    fn restart(&self, binary_path: Option<PathBuf>);    fn activate(&self, ignoring_other_apps: bool);    fn hide(&self);    fn hide_other_apps(&self);    fn unhide_other_apps(&self);     fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>>;    fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;    fn active_window(&self) -> Option<AnyWindowHandle>;    fn window_stack(&self) -> Option<Vec<AnyWindowHandle>> {        None    }     fn is_screen_capture_supported(&self) -> bool;    fn screen_capture_sources(        &self,    ) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>>;     fn open_window(        &self,        handle: AnyWindowHandle,        options: WindowParams,    ) -> anyhow::Result<Box<dyn PlatformWindow>>;     /// Returns the appearance of the application's windows.    fn window_appearance(&self) -> WindowAppearance;     fn open_url(&self, url: &str);    fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>);    fn register_url_scheme(&self, url: &str) -> Task<Result<()>>;     fn prompt_for_paths(        &self,        options: PathPromptOptions,    ) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>>;    fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>>;    fn can_select_mixed_files_and_dirs(&self) -> bool;    fn reveal_path(&self, path: &Path);    fn open_with_system(&self, path: &Path);     fn on_quit(&self, callback: Box<dyn FnMut()>);    fn on_reopen(&self, callback: Box<dyn FnMut()>);    fn on_keyboard_layout_change(&self, callback: Box<dyn FnMut()>);     fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap);    fn get_menus(&self) -> Option<Vec<OwnedMenu>> {        None    }     fn set_dock_menu(&self, menu: Vec<MenuItem>, keymap: &Keymap);    fn perform_dock_menu_action(&self, _action: usize) {}    fn add_recent_document(&self, _path: &Path) {}    fn update_jump_list(        &self,        _menus: Vec<MenuItem>,        _entries: Vec<SmallVec<[PathBuf; 2]>>,    ) -> Vec<SmallVec<[PathBuf; 2]>> {        Vec::new()    }    fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>);    fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>);    fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>);    fn keyboard_layout(&self) -> Box<dyn PlatformKeyboardLayout>;     fn compositor_name(&self) -> &'static str {        ""    }    fn app_path(&self) -> Result<PathBuf>;    fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf>;     fn set_cursor_style(&self, style: CursorStyle);    fn should_auto_hide_scrollbars(&self) -> bool;     #[cfg(any(target_os = "linux", target_os = "freebsd"))]    fn write_to_primary(&self, item: ClipboardItem);    fn write_to_clipboard(&self, item: ClipboardItem);    #[cfg(any(target_os = "linux", target_os = "freebsd"))]    fn read_from_primary(&self) -> Option<ClipboardItem>;    fn read_from_clipboard(&self) -> Option<ClipboardItem>;     fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task<Result<()>>;    fn read_credentials(&self, url: &str) -> Task<Result<Option<(String, Vec<u8>)>>>;    fn delete_credentials(&self, url: &str) -> Task<Result<()>>;} /// A handle to a platform's display, e.g. a monitor or laptop screen.pub trait PlatformDisplay: Send + Sync + Debug {    /// Get the ID for this display    fn id(&self) -> DisplayId;     /// Returns a stable identifier for this display that can be persisted and used    /// across system restarts.    fn uuid(&self) -> Result<Uuid>;     /// Get the bounds for this display    fn bounds(&self) -> Bounds<Pixels>;     /// Get the default bounds for this display to place a window    fn default_bounds(&self) -> Bounds<Pixels> {        let center = self.bounds().center();        let offset = DEFAULT_WINDOW_SIZE / 2.0;        let origin = point(center.x - offset.width, center.y - offset.height);        Bounds::new(origin, DEFAULT_WINDOW_SIZE)    }} /// A source of on-screen video content that can be captured.pub trait ScreenCaptureSource {    /// Returns the video resolution of this source.    fn resolution(&self) -> Result<Size<DevicePixels>>;     /// Start capture video from this source, invoking the given callback    /// with each frame.    fn stream(        &self,        foreground_executor: &ForegroundExecutor,        frame_callback: Box<dyn Fn(ScreenCaptureFrame) + Send>,    ) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>>;} /// A video stream captured from a screen.pub trait ScreenCaptureStream {} /// A frame of video captured from a screen.pub struct ScreenCaptureFrame(pub PlatformScreenCaptureFrame); /// An opaque identifier for a hardware display#[derive(PartialEq, Eq, Hash, Copy, Clone)]pub struct DisplayId(pub(crate) u32); impl From<DisplayId> for u32 {    fn from(id: DisplayId) -> Self {        id.0    }} impl Debug for DisplayId {    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {        write!(f, "DisplayId({})", self.0)    }} unsafe impl Send for DisplayId {} /// Which part of the window to resize#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub enum ResizeEdge {    /// The top edge    Top,    /// The top right corner    TopRight,    /// The right edge    Right,    /// The bottom right corner    BottomRight,    /// The bottom edge    Bottom,    /// The bottom left corner    BottomLeft,    /// The left edge    Left,    /// The top left corner    TopLeft,} /// A type to describe the appearance of a window#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]pub enum WindowDecorations {    #[default]    /// Server side decorations    Server,    /// Client side decorations    Client,} /// A type to describe how this window is currently configured#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]pub enum Decorations {    /// The window is configured to use server side decorations    #[default]    Server,    /// The window is configured to use client side decorations    Client {        /// The edge tiling state        tiling: Tiling,    },} /// What window controls this platform supports#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]pub struct WindowControls {    /// Whether this platform supports fullscreen    pub fullscreen: bool,    /// Whether this platform supports maximize    pub maximize: bool,    /// Whether this platform supports minimize    pub minimize: bool,    /// Whether this platform supports a window menu    pub window_menu: bool,} impl Default for WindowControls {    fn default() -> Self {        // Assume that we can do anything, unless told otherwise        Self {            fullscreen: true,            maximize: true,            minimize: true,            window_menu: true,        }    }} /// A type to describe which sides of the window are currently tiled in some way#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]pub struct Tiling {    /// Whether the top edge is tiled    pub top: bool,    /// Whether the left edge is tiled    pub left: bool,    /// Whether the right edge is tiled    pub right: bool,    /// Whether the bottom edge is tiled    pub bottom: bool,} impl Tiling {    /// Initializes a [`Tiling`] type with all sides tiled    pub fn tiled() -> Self {        Self {            top: true,            left: true,            right: true,            bottom: true,        }    }     /// Whether any edge is tiled    pub fn is_tiled(&self) -> bool {        self.top || self.left || self.right || self.bottom    }} #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]pub(crate) struct RequestFrameOptions {    pub(crate) require_presentation: bool,} pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {    fn bounds(&self) -> Bounds<Pixels>;    fn is_maximized(&self) -> bool;    fn window_bounds(&self) -> WindowBounds;    fn content_size(&self) -> Size<Pixels>;    fn resize(&mut self, size: Size<Pixels>);    fn scale_factor(&self) -> f32;    fn appearance(&self) -> WindowAppearance;    fn display(&self) -> Option<Rc<dyn PlatformDisplay>>;    fn mouse_position(&self) -> Point<Pixels>;    fn modifiers(&self) -> Modifiers;    fn set_input_handler(&mut self, input_handler: PlatformInputHandler);    fn take_input_handler(&mut self) -> Option<PlatformInputHandler>;    fn prompt(        &self,        level: PromptLevel,        msg: &str,        detail: Option<&str>,        answers: &[&str],    ) -> Option<oneshot::Receiver<usize>>;    fn activate(&self);    fn is_active(&self) -> bool;    fn is_hovered(&self) -> bool;    fn set_title(&mut self, title: &str);    fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance);    fn minimize(&self);    fn zoom(&self);    fn toggle_fullscreen(&self);    fn is_fullscreen(&self) -> bool;    fn on_request_frame(&self, callback: Box<dyn FnMut(RequestFrameOptions)>);    fn on_input(&self, callback: Box<dyn FnMut(PlatformInput) -> DispatchEventResult>);    fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>);    fn on_hover_status_change(&self, callback: Box<dyn FnMut(bool)>);    fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>);    fn on_moved(&self, callback: Box<dyn FnMut()>);    fn on_should_close(&self, callback: Box<dyn FnMut() -> bool>);    fn on_close(&self, callback: Box<dyn FnOnce()>);    fn on_appearance_changed(&self, callback: Box<dyn FnMut()>);    fn draw(&self, scene: &Scene);    fn completed_frame(&self) {}    fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas>;     // macOS specific methods    fn set_edited(&mut self, _edited: bool) {}    fn show_character_palette(&self) {}     #[cfg(target_os = "windows")]    fn get_raw_handle(&self) -> windows::HWND;     // Linux specific methods    fn inner_window_bounds(&self) -> WindowBounds {        self.window_bounds()    }    fn request_decorations(&self, _decorations: WindowDecorations) {}    fn show_window_menu(&self, _position: Point<Pixels>) {}    fn start_window_move(&self) {}    fn start_window_resize(&self, _edge: ResizeEdge) {}    fn window_decorations(&self) -> Decorations {        Decorations::Server    }    fn set_app_id(&mut self, _app_id: &str) {}    fn map_window(&mut self) -> anyhow::Result<()> {        Ok(())    }    fn window_controls(&self) -> WindowControls {        WindowControls::default()    }    fn set_client_inset(&self, _inset: Pixels) {}    fn gpu_specs(&self) -> Option<GpuSpecs>;     fn update_ime_position(&self, _bounds: Bounds<ScaledPixels>);     #[cfg(any(test, feature = "test-support"))]    fn as_test(&mut self) -> Option<&mut TestWindow> {        None    }} /// This type is public so that our test macro can generate and use it, but it should not/// be considered part of our public API.#[doc(hidden)]pub trait PlatformDispatcher: Send + Sync {    fn is_main_thread(&self) -> bool;    fn dispatch(&self, runnable: Runnable, label: Option<TaskLabel>);    fn dispatch_on_main_thread(&self, runnable: Runnable);    fn dispatch_after(&self, duration: Duration, runnable: Runnable);    fn park(&self, timeout: Option<Duration>) -> bool;    fn unparker(&self) -> Unparker;    fn now(&self) -> Instant {        Instant::now()    }     #[cfg(any(test, feature = "test-support"))]    fn as_test(&self) -> Option<&TestDispatcher> {        None    }} 

Lines 1–500 of 1653.