Add remote server cross compilation (#19136)
This will allow us to compile debug builds of the remote-server for a different architecture than the one we are developing on. This also adds a CI step for building our remote server with minimal dependencies. Release Notes: - N/A
This commit is contained in:
parent
f73a076a63
commit
bebe24ea77
23 changed files with 542 additions and 161 deletions
31
.github/workflows/ci.yml
vendored
31
.github/workflows/ci.yml
vendored
|
@ -99,7 +99,10 @@ jobs:
|
||||||
run: cargo build -p collab
|
run: cargo build -p collab
|
||||||
|
|
||||||
- name: Build other binaries and features
|
- name: Build other binaries and features
|
||||||
run: cargo build --workspace --bins --all-features; cargo check -p gpui --features "macos-blade"
|
run: |
|
||||||
|
cargo build --workspace --bins --all-features
|
||||||
|
cargo check -p gpui --features "macos-blade"
|
||||||
|
cargo build -p remote_server
|
||||||
|
|
||||||
linux_tests:
|
linux_tests:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
|
@ -133,6 +136,32 @@ jobs:
|
||||||
- name: Build Zed
|
- name: Build Zed
|
||||||
run: cargo build -p zed
|
run: cargo build -p zed
|
||||||
|
|
||||||
|
build_remote_server:
|
||||||
|
timeout-minutes: 60
|
||||||
|
name: (Linux) Build Remote Server
|
||||||
|
runs-on:
|
||||||
|
- buildjet-16vcpu-ubuntu-2204
|
||||||
|
steps:
|
||||||
|
- name: Add Rust to the PATH
|
||||||
|
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
||||||
|
with:
|
||||||
|
clean: false
|
||||||
|
|
||||||
|
- name: Cache dependencies
|
||||||
|
uses: swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2
|
||||||
|
with:
|
||||||
|
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||||
|
cache-provider: "buildjet"
|
||||||
|
|
||||||
|
- name: Install Clang & Mold
|
||||||
|
run: ./script/remote-server && ./script/install-mold 2.34.0
|
||||||
|
|
||||||
|
- name: Build Remote Server
|
||||||
|
run: cargo build -p remote_server
|
||||||
|
|
||||||
# todo(windows): Actually run the tests
|
# todo(windows): Actually run the tests
|
||||||
windows_tests:
|
windows_tests:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -14669,6 +14669,7 @@ dependencies = [
|
||||||
"winresource",
|
"winresource",
|
||||||
"workspace",
|
"workspace",
|
||||||
"zed_actions",
|
"zed_actions",
|
||||||
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -220,7 +220,7 @@ git = { path = "crates/git" }
|
||||||
git_hosting_providers = { path = "crates/git_hosting_providers" }
|
git_hosting_providers = { path = "crates/git_hosting_providers" }
|
||||||
go_to_line = { path = "crates/go_to_line" }
|
go_to_line = { path = "crates/go_to_line" }
|
||||||
google_ai = { path = "crates/google_ai" }
|
google_ai = { path = "crates/google_ai" }
|
||||||
gpui = { path = "crates/gpui" }
|
gpui = { path = "crates/gpui", default-features = false, features = ["http_client"]}
|
||||||
gpui_macros = { path = "crates/gpui_macros" }
|
gpui_macros = { path = "crates/gpui_macros" }
|
||||||
headless = { path = "crates/headless" }
|
headless = { path = "crates/headless" }
|
||||||
html_to_markdown = { path = "crates/html_to_markdown" }
|
html_to_markdown = { path = "crates/html_to_markdown" }
|
||||||
|
@ -477,6 +477,7 @@ wasmtime = { version = "24", default-features = false, features = [
|
||||||
wasmtime-wasi = "24"
|
wasmtime-wasi = "24"
|
||||||
which = "6.0.0"
|
which = "6.0.0"
|
||||||
wit-component = "0.201"
|
wit-component = "0.201"
|
||||||
|
zstd = "0.11"
|
||||||
|
|
||||||
[workspace.dependencies.async-stripe]
|
[workspace.dependencies.async-stripe]
|
||||||
git = "https://github.com/zed-industries/async-stripe"
|
git = "https://github.com/zed-industries/async-stripe"
|
||||||
|
|
2
Cross.toml
Normal file
2
Cross.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
dockerfile = "Dockerfile-cross"
|
17
Dockerfile-cross
Normal file
17
Dockerfile-cross
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
ARG CROSS_BASE_IMAGE
|
||||||
|
FROM ${CROSS_BASE_IMAGE}
|
||||||
|
WORKDIR /app
|
||||||
|
ARG TZ=Etc/UTC \
|
||||||
|
LANG=C.UTF-8 \
|
||||||
|
LC_ALL=C.UTF-8 \
|
||||||
|
DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV CARGO_TERM_COLOR=always
|
||||||
|
|
||||||
|
COPY script/install-mold script/
|
||||||
|
RUN ./script/install-mold "2.34.0"
|
||||||
|
COPY script/remote-server script/
|
||||||
|
RUN ./script/remote-server
|
||||||
|
|
||||||
|
COPY . .
|
16
Dockerfile-cross.dockerignore
Normal file
16
Dockerfile-cross.dockerignore
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
.git
|
||||||
|
.github
|
||||||
|
**/.gitignore
|
||||||
|
**/.gitkeep
|
||||||
|
.gitattributes
|
||||||
|
.mailmap
|
||||||
|
**/target
|
||||||
|
zed.xcworkspace
|
||||||
|
.DS_Store
|
||||||
|
compose.yml
|
||||||
|
plugins/bin
|
||||||
|
script/node_modules
|
||||||
|
styles/node_modules
|
||||||
|
crates/collab/static/styles.css
|
||||||
|
vendor/bin
|
||||||
|
assets/themes/
|
|
@ -464,6 +464,7 @@ impl AutoUpdater {
|
||||||
smol::fs::create_dir_all(&platform_dir).await.ok();
|
smol::fs::create_dir_all(&platform_dir).await.ok();
|
||||||
|
|
||||||
let client = this.read_with(cx, |this, _| this.http_client.clone())?;
|
let client = this.read_with(cx, |this, _| this.http_client.clone())?;
|
||||||
|
|
||||||
if smol::fs::metadata(&version_path).await.is_err() {
|
if smol::fs::metadata(&version_path).await.is_err() {
|
||||||
log::info!("downloading zed-remote-server {os} {arch}");
|
log::info!("downloading zed-remote-server {os} {arch}");
|
||||||
download_remote_server_binary(&version_path, release, client, cx).await?;
|
download_remote_server_binary(&version_path, release, client, cx).await?;
|
||||||
|
|
|
@ -11,16 +11,53 @@ license = "Apache-2.0"
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["http_client"]
|
default = ["http_client", "font-kit", "wayland", "x11"]
|
||||||
test-support = [
|
test-support = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"collections/test-support",
|
"collections/test-support",
|
||||||
"rand",
|
"rand",
|
||||||
"util/test-support",
|
"util/test-support",
|
||||||
"http_client?/test-support",
|
"http_client?/test-support",
|
||||||
|
"wayland",
|
||||||
|
"x11",
|
||||||
]
|
]
|
||||||
runtime_shaders = []
|
runtime_shaders = []
|
||||||
macos-blade = ["blade-graphics", "blade-macros", "blade-util", "bytemuck"]
|
macos-blade = ["blade-graphics", "blade-macros", "blade-util", "bytemuck"]
|
||||||
|
wayland = [
|
||||||
|
"blade-graphics",
|
||||||
|
"blade-macros",
|
||||||
|
"blade-util",
|
||||||
|
"bytemuck",
|
||||||
|
"ashpd",
|
||||||
|
"cosmic-text",
|
||||||
|
"font-kit",
|
||||||
|
"calloop-wayland-source",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-cursor",
|
||||||
|
"wayland-protocols",
|
||||||
|
"wayland-protocols-plasma",
|
||||||
|
"filedescriptor",
|
||||||
|
"xkbcommon",
|
||||||
|
"open",
|
||||||
|
]
|
||||||
|
x11 = [
|
||||||
|
"blade-graphics",
|
||||||
|
"blade-macros",
|
||||||
|
"blade-util",
|
||||||
|
"bytemuck",
|
||||||
|
"ashpd",
|
||||||
|
"cosmic-text",
|
||||||
|
"font-kit",
|
||||||
|
"as-raw-xcb-connection",
|
||||||
|
"x11rb",
|
||||||
|
"xkbcommon",
|
||||||
|
"xim",
|
||||||
|
"x11-clipboard",
|
||||||
|
"filedescriptor",
|
||||||
|
"open",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "src/gpui.rs"
|
path = "src/gpui.rs"
|
||||||
|
@ -95,7 +132,7 @@ core-foundation.workspace = true
|
||||||
core-foundation-sys = "0.8"
|
core-foundation-sys = "0.8"
|
||||||
core-graphics = "0.23"
|
core-graphics = "0.23"
|
||||||
core-text = "20.1"
|
core-text = "20.1"
|
||||||
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7" }
|
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7", optional = true}
|
||||||
foreign-types = "0.5"
|
foreign-types = "0.5"
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
media.workspace = true
|
media.workspace = true
|
||||||
|
@ -105,31 +142,45 @@ objc = "0.2"
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
|
||||||
pathfinder_geometry = "0.5"
|
pathfinder_geometry = "0.5"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
|
|
||||||
blade-graphics.workspace = true
|
|
||||||
blade-macros.workspace = true
|
|
||||||
blade-util.workspace = true
|
|
||||||
bytemuck = "1"
|
|
||||||
flume = "0.11"
|
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
as-raw-xcb-connection = "1"
|
# Always used
|
||||||
ashpd.workspace = true
|
flume = "0.11"
|
||||||
calloop = "0.13.0"
|
oo7 = "0.3.0"
|
||||||
calloop-wayland-source = "0.3.0"
|
|
||||||
cosmic-text = { git = "https://github.com/pop-os/cosmic-text", rev = "542b20c" }
|
# Used in both windowing options
|
||||||
wayland-backend = { version = "0.3.3", features = ["client_system", "dlopen"] }
|
ashpd = { workspace = true, optional = true }
|
||||||
wayland-client = { version = "0.31.2" }
|
blade-graphics = { workspace = true, optional = true }
|
||||||
wayland-cursor = "0.31.1"
|
blade-macros = { workspace = true, optional = true }
|
||||||
|
blade-util = { workspace = true, optional = true }
|
||||||
|
bytemuck = { version = "1", optional = true }
|
||||||
|
cosmic-text = { git = "https://github.com/pop-os/cosmic-text", rev = "542b20c", optional = true }
|
||||||
|
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7", features = [
|
||||||
|
"source-fontconfig-dlopen",
|
||||||
|
], optional = true }
|
||||||
|
calloop = { version = "0.13.0" }
|
||||||
|
filedescriptor = { version = "0.8.2", optional = true }
|
||||||
|
open = { version = "5.2.0", optional = true }
|
||||||
|
|
||||||
|
# Wayland
|
||||||
|
calloop-wayland-source = { version = "0.3.0", optional = true }
|
||||||
|
wayland-backend = { version = "0.3.3", features = [
|
||||||
|
"client_system",
|
||||||
|
"dlopen",
|
||||||
|
], optional = true }
|
||||||
|
wayland-client = { version = "0.31.2", optional = true }
|
||||||
|
wayland-cursor = { version = "0.31.1", optional = true }
|
||||||
wayland-protocols = { version = "0.31.2", features = [
|
wayland-protocols = { version = "0.31.2", features = [
|
||||||
"client",
|
"client",
|
||||||
"staging",
|
"staging",
|
||||||
"unstable",
|
"unstable",
|
||||||
] }
|
], optional = true }
|
||||||
wayland-protocols-plasma = { version = "0.2.0", features = ["client"] }
|
wayland-protocols-plasma = { version = "0.2.0", features = [
|
||||||
oo7 = "0.3.0"
|
"client",
|
||||||
open = "5.2.0"
|
], optional = true }
|
||||||
filedescriptor = "0.8.2"
|
|
||||||
|
|
||||||
|
# X11
|
||||||
|
as-raw-xcb-connection = { version = "1", optional = true }
|
||||||
x11rb = { version = "0.13.0", features = [
|
x11rb = { version = "0.13.0", features = [
|
||||||
"allow-unsafe-code",
|
"allow-unsafe-code",
|
||||||
"xkb",
|
"xkb",
|
||||||
|
@ -138,21 +189,23 @@ x11rb = { version = "0.13.0", features = [
|
||||||
"cursor",
|
"cursor",
|
||||||
"resource_manager",
|
"resource_manager",
|
||||||
"sync",
|
"sync",
|
||||||
] }
|
], optional = true }
|
||||||
xkbcommon = { git = "https://github.com/ConradIrwin/xkbcommon-rs", rev = "fcbb4612185cc129ceeff51d22f7fb51810a03b2", features = [
|
xkbcommon = { git = "https://github.com/ConradIrwin/xkbcommon-rs", rev = "fcbb4612185cc129ceeff51d22f7fb51810a03b2", features = [
|
||||||
"wayland",
|
"wayland",
|
||||||
"x11",
|
"x11",
|
||||||
] }
|
], optional = true }
|
||||||
xim = { git = "https://github.com/XDeme1/xim-rs", rev = "d50d461764c2213655cd9cf65a0ea94c70d3c4fd", features = [
|
xim = { git = "https://github.com/XDeme1/xim-rs", rev = "d50d461764c2213655cd9cf65a0ea94c70d3c4fd", features = [
|
||||||
"x11rb-xcb",
|
"x11rb-xcb",
|
||||||
"x11rb-client",
|
"x11rb-client",
|
||||||
] }
|
], optional = true }
|
||||||
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7", features = [
|
x11-clipboard = { version = "0.9.2", optional = true }
|
||||||
"source-fontconfig-dlopen",
|
|
||||||
] }
|
|
||||||
x11-clipboard = "0.9.2"
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
blade-util.workspace = true
|
||||||
|
bytemuck = "1"
|
||||||
|
blade-graphics.workspace = true
|
||||||
|
blade-macros.workspace = true
|
||||||
|
flume = "0.11"
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
windows.workspace = true
|
windows.workspace = true
|
||||||
windows-core = "0.58"
|
windows-core = "0.58"
|
||||||
|
|
|
@ -10,7 +10,11 @@ mod linux;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
mod mac;
|
mod mac;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "windows", feature = "macos-blade"))]
|
#[cfg(any(
|
||||||
|
all(target_os = "linux", any(feature = "x11", feature = "wayland")),
|
||||||
|
target_os = "windows",
|
||||||
|
feature = "macos-blade"
|
||||||
|
))]
|
||||||
mod blade;
|
mod blade;
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
@ -26,7 +30,7 @@ use crate::{
|
||||||
RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, ScaledPixels, Scene,
|
RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, ScaledPixels, Scene,
|
||||||
SharedString, Size, SvgSize, Task, TaskLabel, WindowContext, DEFAULT_WINDOW_SIZE,
|
SharedString, Size, SvgSize, Task, TaskLabel, WindowContext, DEFAULT_WINDOW_SIZE,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::{anyhow, Result};
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
use futures::channel::oneshot;
|
use futures::channel::oneshot;
|
||||||
use image::codecs::gif::GifDecoder;
|
use image::codecs::gif::GifDecoder;
|
||||||
|
@ -75,8 +79,12 @@ pub(crate) fn current_platform(headless: bool) -> Rc<dyn Platform> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match guess_compositor() {
|
match guess_compositor() {
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
"Wayland" => Rc::new(WaylandClient::new()),
|
"Wayland" => Rc::new(WaylandClient::new()),
|
||||||
|
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
"X11" => Rc::new(X11Client::new()),
|
"X11" => Rc::new(X11Client::new()),
|
||||||
|
|
||||||
"Headless" => Rc::new(HeadlessClient::new()),
|
"Headless" => Rc::new(HeadlessClient::new()),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -90,8 +98,16 @@ pub fn guess_compositor() -> &'static str {
|
||||||
if std::env::var_os("ZED_HEADLESS").is_some() {
|
if std::env::var_os("ZED_HEADLESS").is_some() {
|
||||||
return "Headless";
|
return "Headless";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
let wayland_display = std::env::var_os("WAYLAND_DISPLAY");
|
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");
|
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_wayland = wayland_display.is_some_and(|display| !display.is_empty());
|
||||||
let use_x11 = x11_display.is_some_and(|display| !display.is_empty());
|
let use_x11 = x11_display.is_some_and(|display| !display.is_empty());
|
||||||
|
@ -426,6 +442,61 @@ pub(crate) trait PlatformTextSystem: Send + Sync {
|
||||||
fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout;
|
fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct NoopTextSystem;
|
||||||
|
|
||||||
|
impl NoopTextSystem {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlatformTextSystem for NoopTextSystem {
|
||||||
|
fn add_fonts(&self, _fonts: Vec<Cow<'static, [u8]>>) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_font_names(&self) -> Vec<String> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn font_id(&self, descriptor: &Font) -> Result<FontId> {
|
||||||
|
Err(anyhow!("No font found for {:?}", descriptor))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn font_metrics(&self, _font_id: FontId) -> FontMetrics {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn typographic_bounds(&self, font_id: FontId, _glyph_id: GlyphId) -> Result<Bounds<f32>> {
|
||||||
|
Err(anyhow!("No font found for {:?}", font_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn advance(&self, font_id: FontId, _glyph_id: GlyphId) -> Result<Size<f32>> {
|
||||||
|
Err(anyhow!("No font found for {:?}", font_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn glyph_for_char(&self, _font_id: FontId, _ch: char) -> Option<GlyphId> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn glyph_raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
|
||||||
|
Err(anyhow!("No font found for {:?}", params))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rasterize_glyph(
|
||||||
|
&self,
|
||||||
|
params: &RenderGlyphParams,
|
||||||
|
_raster_bounds: Bounds<DevicePixels>,
|
||||||
|
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||||
|
Err(anyhow!("No font found for {:?}", params))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout_line(&self, _text: &str, _font_size: Pixels, _runs: &[FontRun]) -> LineLayout {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||||
pub(crate) enum AtlasKey {
|
pub(crate) enum AtlasKey {
|
||||||
Glyph(RenderGlyphParams),
|
Glyph(RenderGlyphParams),
|
||||||
|
@ -434,6 +505,10 @@ pub(crate) enum AtlasKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtlasKey {
|
impl AtlasKey {
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
pub(crate) fn texture_kind(&self) -> AtlasTextureKind {
|
pub(crate) fn texture_kind(&self) -> AtlasTextureKind {
|
||||||
match self {
|
match self {
|
||||||
AtlasKey::Glyph(params) => {
|
AtlasKey::Glyph(params) => {
|
||||||
|
@ -494,6 +569,10 @@ pub(crate) struct AtlasTextureId {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
pub(crate) enum AtlasTextureKind {
|
pub(crate) enum AtlasTextureKind {
|
||||||
Monochrome = 0,
|
Monochrome = 0,
|
||||||
Polychrome = 1,
|
Polychrome = 1,
|
||||||
|
@ -521,6 +600,10 @@ pub(crate) struct PlatformInputHandler {
|
||||||
handler: Box<dyn InputHandler>,
|
handler: Box<dyn InputHandler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
impl PlatformInputHandler {
|
impl PlatformInputHandler {
|
||||||
pub fn new(cx: AsyncWindowContext, handler: Box<dyn InputHandler>) -> Self {
|
pub fn new(cx: AsyncWindowContext, handler: Box<dyn InputHandler>) -> Self {
|
||||||
Self { cx, handler }
|
Self { cx, handler }
|
||||||
|
@ -728,10 +811,15 @@ pub struct WindowOptions {
|
||||||
|
|
||||||
/// The variables that can be configured when creating a new window
|
/// The variables that can be configured when creating a new window
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
pub(crate) struct WindowParams {
|
pub(crate) struct WindowParams {
|
||||||
pub bounds: Bounds<Pixels>,
|
pub bounds: Bounds<Pixels>,
|
||||||
|
|
||||||
/// The titlebar configuration of the window
|
/// The titlebar configuration of the window
|
||||||
|
#[cfg_attr(feature = "wayland", allow(dead_code))]
|
||||||
pub titlebar: Option<TitlebarOptions>,
|
pub titlebar: Option<TitlebarOptions>,
|
||||||
|
|
||||||
/// The kind of window to create
|
/// The kind of window to create
|
||||||
|
@ -748,6 +836,7 @@ pub(crate) struct WindowParams {
|
||||||
#[cfg_attr(target_os = "linux", allow(dead_code))]
|
#[cfg_attr(target_os = "linux", allow(dead_code))]
|
||||||
pub show: bool,
|
pub show: bool,
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "wayland", allow(dead_code))]
|
||||||
pub display_id: Option<DisplayId>,
|
pub display_id: Option<DisplayId>,
|
||||||
|
|
||||||
pub window_min_size: Option<Size<Pixels>>,
|
pub window_min_size: Option<Size<Pixels>>,
|
||||||
|
|
|
@ -455,7 +455,7 @@ impl BladeRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(target_os = "macos", allow(dead_code))]
|
#[cfg_attr(any(target_os = "macos", feature = "wayland"), allow(dead_code))]
|
||||||
pub fn viewport_size(&self) -> gpu::Extent {
|
pub fn viewport_size(&self) -> gpu::Extent {
|
||||||
self.surface_config.size
|
self.surface_config.size
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
mod dispatcher;
|
mod dispatcher;
|
||||||
mod headless;
|
mod headless;
|
||||||
mod platform;
|
mod platform;
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
mod text_system;
|
mod text_system;
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
mod wayland;
|
mod wayland;
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
mod x11;
|
mod x11;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
mod xdg_desktop_portal;
|
mod xdg_desktop_portal;
|
||||||
|
|
||||||
pub(crate) use dispatcher::*;
|
pub(crate) use dispatcher::*;
|
||||||
pub(crate) use headless::*;
|
pub(crate) use headless::*;
|
||||||
pub(crate) use platform::*;
|
pub(crate) use platform::*;
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
pub(crate) use text_system::*;
|
pub(crate) use text_system::*;
|
||||||
|
#[cfg(feature = "wayland")]
|
||||||
pub(crate) use wayland::*;
|
pub(crate) use wayland::*;
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
pub(crate) use x11::*;
|
pub(crate) use x11::*;
|
||||||
|
|
|
@ -19,32 +19,26 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use ashpd::desktop::file_chooser::{OpenFileRequest, SaveFileRequest};
|
|
||||||
use ashpd::desktop::open_uri::{OpenDirectoryRequest, OpenFileRequest as OpenUriRequest};
|
|
||||||
use ashpd::{url, ActivationToken};
|
|
||||||
use async_task::Runnable;
|
use async_task::Runnable;
|
||||||
use calloop::channel::Channel;
|
use calloop::channel::Channel;
|
||||||
use calloop::{EventLoop, LoopHandle, LoopSignal};
|
use calloop::{EventLoop, LoopHandle, LoopSignal};
|
||||||
use filedescriptor::FileDescriptor;
|
|
||||||
use flume::{Receiver, Sender};
|
use flume::{Receiver, Sender};
|
||||||
use futures::channel::oneshot;
|
use futures::channel::oneshot;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use wayland_client::Connection;
|
|
||||||
use wayland_protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::Shape;
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
use xkbcommon::xkb::{self, Keycode, Keysym, State};
|
use xkbcommon::xkb::{self, Keycode, Keysym, State};
|
||||||
|
|
||||||
use crate::platform::linux::wayland::WaylandClient;
|
use crate::platform::NoopTextSystem;
|
||||||
use crate::{
|
use crate::{
|
||||||
px, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CosmicTextSystem, CursorStyle,
|
px, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
||||||
DisplayId, ForegroundExecutor, Keymap, Keystroke, LinuxDispatcher, Menu, MenuItem, Modifiers,
|
ForegroundExecutor, Keymap, Keystroke, LinuxDispatcher, Menu, MenuItem, Modifiers, OwnedMenu,
|
||||||
OwnedMenu, PathPromptOptions, Pixels, Platform, PlatformDisplay, PlatformInputHandler,
|
PathPromptOptions, Pixels, Platform, PlatformDisplay, PlatformInputHandler, PlatformTextSystem,
|
||||||
PlatformTextSystem, PlatformWindow, Point, PromptLevel, Result, SemanticVersion, SharedString,
|
PlatformWindow, Point, PromptLevel, Result, SemanticVersion, SharedString, Size, Task,
|
||||||
Size, Task, WindowAppearance, WindowOptions, WindowParams,
|
WindowAppearance, WindowOptions, WindowParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::x11::X11Client;
|
|
||||||
|
|
||||||
pub(crate) const SCROLL_LINES: f32 = 3.0;
|
pub(crate) const SCROLL_LINES: f32 = 3.0;
|
||||||
|
|
||||||
// Values match the defaults on GTK.
|
// Values match the defaults on GTK.
|
||||||
|
@ -93,7 +87,7 @@ pub(crate) struct PlatformHandlers {
|
||||||
pub(crate) struct LinuxCommon {
|
pub(crate) struct LinuxCommon {
|
||||||
pub(crate) background_executor: BackgroundExecutor,
|
pub(crate) background_executor: BackgroundExecutor,
|
||||||
pub(crate) foreground_executor: ForegroundExecutor,
|
pub(crate) foreground_executor: ForegroundExecutor,
|
||||||
pub(crate) text_system: Arc<CosmicTextSystem>,
|
pub(crate) text_system: Arc<dyn PlatformTextSystem>,
|
||||||
pub(crate) appearance: WindowAppearance,
|
pub(crate) appearance: WindowAppearance,
|
||||||
pub(crate) auto_hide_scrollbars: bool,
|
pub(crate) auto_hide_scrollbars: bool,
|
||||||
pub(crate) callbacks: PlatformHandlers,
|
pub(crate) callbacks: PlatformHandlers,
|
||||||
|
@ -104,7 +98,12 @@ pub(crate) struct LinuxCommon {
|
||||||
impl LinuxCommon {
|
impl LinuxCommon {
|
||||||
pub fn new(signal: LoopSignal) -> (Self, Channel<Runnable>) {
|
pub fn new(signal: LoopSignal) -> (Self, Channel<Runnable>) {
|
||||||
let (main_sender, main_receiver) = calloop::channel::channel::<Runnable>();
|
let (main_sender, main_receiver) = calloop::channel::channel::<Runnable>();
|
||||||
let text_system = Arc::new(CosmicTextSystem::new());
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
|
let text_system = Arc::new(crate::CosmicTextSystem::new());
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "wayland", feature = "x11")))]
|
||||||
|
let text_system = Arc::new(crate::NoopTextSystem::new());
|
||||||
|
|
||||||
let callbacks = PlatformHandlers::default();
|
let callbacks = PlatformHandlers::default();
|
||||||
|
|
||||||
let dispatcher = Arc::new(LinuxDispatcher::new(main_sender.clone()));
|
let dispatcher = Arc::new(LinuxDispatcher::new(main_sender.clone()));
|
||||||
|
@ -264,6 +263,11 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||||
options: PathPromptOptions,
|
options: PathPromptOptions,
|
||||||
) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>> {
|
) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>> {
|
||||||
let (done_tx, done_rx) = oneshot::channel();
|
let (done_tx, done_rx) = oneshot::channel();
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "wayland", feature = "x11")))]
|
||||||
|
done_tx.send(Ok(None));
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
self.foreground_executor()
|
self.foreground_executor()
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
let title = if options.directories {
|
let title = if options.directories {
|
||||||
|
@ -272,7 +276,7 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||||
"Open File"
|
"Open File"
|
||||||
};
|
};
|
||||||
|
|
||||||
let request = match OpenFileRequest::default()
|
let request = match ashpd::desktop::file_chooser::OpenFileRequest::default()
|
||||||
.modal(true)
|
.modal(true)
|
||||||
.title(title)
|
.title(title)
|
||||||
.multiple(options.multiple)
|
.multiple(options.multiple)
|
||||||
|
@ -310,10 +314,17 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||||
|
|
||||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||||
let (done_tx, done_rx) = oneshot::channel();
|
let (done_tx, done_rx) = oneshot::channel();
|
||||||
let directory = directory.to_owned();
|
|
||||||
|
#[cfg(not(any(feature = "wayland", feature = "x11")))]
|
||||||
|
done_tx.send(Ok(None));
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
self.foreground_executor()
|
self.foreground_executor()
|
||||||
.spawn(async move {
|
.spawn({
|
||||||
let request = match SaveFileRequest::default()
|
let directory = directory.to_owned();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let request = match ashpd::desktop::file_chooser::SaveFileRequest::default()
|
||||||
.modal(true)
|
.modal(true)
|
||||||
.title("Save File")
|
.title("Save File")
|
||||||
.current_folder(directory)
|
.current_folder(directory)
|
||||||
|
@ -324,7 +335,9 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||||
Ok(request) => request,
|
Ok(request) => request,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let result = match err {
|
let result = match err {
|
||||||
ashpd::Error::PortalNotFound(_) => anyhow!(FILE_PICKER_PORTAL_MISSING),
|
ashpd::Error::PortalNotFound(_) => {
|
||||||
|
anyhow!(FILE_PICKER_PORTAL_MISSING)
|
||||||
|
}
|
||||||
err => err.into(),
|
err => err.into(),
|
||||||
};
|
};
|
||||||
done_tx.send(Err(result));
|
done_tx.send(Err(result));
|
||||||
|
@ -341,6 +354,7 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||||
Err(e) => Err(e.into()),
|
Err(e) => Err(e.into()),
|
||||||
};
|
};
|
||||||
done_tx.send(result);
|
done_tx.send(result);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
|
@ -518,16 +532,17 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||||
fn add_recent_document(&self, _path: &Path) {}
|
fn add_recent_document(&self, _path: &Path) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
pub(super) fn open_uri_internal(
|
pub(super) fn open_uri_internal(
|
||||||
executor: BackgroundExecutor,
|
executor: BackgroundExecutor,
|
||||||
uri: &str,
|
uri: &str,
|
||||||
activation_token: Option<String>,
|
activation_token: Option<String>,
|
||||||
) {
|
) {
|
||||||
if let Some(uri) = url::Url::parse(uri).log_err() {
|
if let Some(uri) = ashpd::url::Url::parse(uri).log_err() {
|
||||||
executor
|
executor
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
match OpenUriRequest::default()
|
match ashpd::desktop::open_uri::OpenFileRequest::default()
|
||||||
.activation_token(activation_token.clone().map(ActivationToken::from))
|
.activation_token(activation_token.clone().map(ashpd::ActivationToken::from))
|
||||||
.send_uri(&uri)
|
.send_uri(&uri)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
@ -551,6 +566,7 @@ pub(super) fn open_uri_internal(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "x11", feature = "wayland"))]
|
||||||
pub(super) fn reveal_path_internal(
|
pub(super) fn reveal_path_internal(
|
||||||
executor: BackgroundExecutor,
|
executor: BackgroundExecutor,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
@ -559,8 +575,8 @@ pub(super) fn reveal_path_internal(
|
||||||
executor
|
executor
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
if let Some(dir) = File::open(path.clone()).log_err() {
|
if let Some(dir) = File::open(path.clone()).log_err() {
|
||||||
match OpenDirectoryRequest::default()
|
match ashpd::desktop::open_uri::OpenDirectoryRequest::default()
|
||||||
.activation_token(activation_token.map(ActivationToken::from))
|
.activation_token(activation_token.map(ashpd::ActivationToken::from))
|
||||||
.send(&dir.as_fd())
|
.send(&dir.as_fd())
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
@ -582,6 +598,7 @@ pub(super) fn is_within_click_distance(a: Point<Pixels>, b: Point<Pixels>) -> bo
|
||||||
diff.x.abs() <= DOUBLE_CLICK_DISTANCE && diff.y.abs() <= DOUBLE_CLICK_DISTANCE
|
diff.x.abs() <= DOUBLE_CLICK_DISTANCE && diff.y.abs() <= DOUBLE_CLICK_DISTANCE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::State> {
|
pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::State> {
|
||||||
let mut locales = Vec::default();
|
let mut locales = Vec::default();
|
||||||
if let Some(locale) = std::env::var_os("LC_CTYPE") {
|
if let Some(locale) = std::env::var_os("LC_CTYPE") {
|
||||||
|
@ -603,7 +620,8 @@ pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::S
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) unsafe fn read_fd(mut fd: FileDescriptor) -> Result<Vec<u8>> {
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
|
pub(super) unsafe fn read_fd(mut fd: filedescriptor::FileDescriptor) -> Result<Vec<u8>> {
|
||||||
let mut file = File::from_raw_fd(fd.as_raw_fd());
|
let mut file = File::from_raw_fd(fd.as_raw_fd());
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
file.read_to_end(&mut buffer)?;
|
file.read_to_end(&mut buffer)?;
|
||||||
|
@ -611,32 +629,6 @@ pub(super) unsafe fn read_fd(mut fd: FileDescriptor) -> Result<Vec<u8>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CursorStyle {
|
impl CursorStyle {
|
||||||
pub(super) fn to_shape(&self) -> Shape {
|
|
||||||
match self {
|
|
||||||
CursorStyle::Arrow => Shape::Default,
|
|
||||||
CursorStyle::IBeam => Shape::Text,
|
|
||||||
CursorStyle::Crosshair => Shape::Crosshair,
|
|
||||||
CursorStyle::ClosedHand => Shape::Grabbing,
|
|
||||||
CursorStyle::OpenHand => Shape::Grab,
|
|
||||||
CursorStyle::PointingHand => Shape::Pointer,
|
|
||||||
CursorStyle::ResizeLeft => Shape::WResize,
|
|
||||||
CursorStyle::ResizeRight => Shape::EResize,
|
|
||||||
CursorStyle::ResizeLeftRight => Shape::EwResize,
|
|
||||||
CursorStyle::ResizeUp => Shape::NResize,
|
|
||||||
CursorStyle::ResizeDown => Shape::SResize,
|
|
||||||
CursorStyle::ResizeUpDown => Shape::NsResize,
|
|
||||||
CursorStyle::ResizeUpLeftDownRight => Shape::NwseResize,
|
|
||||||
CursorStyle::ResizeUpRightDownLeft => Shape::NeswResize,
|
|
||||||
CursorStyle::ResizeColumn => Shape::ColResize,
|
|
||||||
CursorStyle::ResizeRow => Shape::RowResize,
|
|
||||||
CursorStyle::IBeamCursorForVerticalLayout => Shape::VerticalText,
|
|
||||||
CursorStyle::OperationNotAllowed => Shape::NotAllowed,
|
|
||||||
CursorStyle::DragLink => Shape::Alias,
|
|
||||||
CursorStyle::DragCopy => Shape::Copy,
|
|
||||||
CursorStyle::ContextualMenu => Shape::ContextMenu,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn to_icon_name(&self) -> String {
|
pub(super) fn to_icon_name(&self) -> String {
|
||||||
// Based on cursor names from https://gitlab.gnome.org/GNOME/adwaita-icon-theme (GNOME)
|
// Based on cursor names from https://gitlab.gnome.org/GNOME/adwaita-icon-theme (GNOME)
|
||||||
// and https://github.com/KDE/breeze (KDE). Both of them seem to be also derived from
|
// and https://github.com/KDE/breeze (KDE). Both of them seem to be also derived from
|
||||||
|
@ -668,6 +660,7 @@ impl CursorStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
impl Keystroke {
|
impl Keystroke {
|
||||||
pub(super) fn from_xkb(state: &State, modifiers: Modifiers, keycode: Keycode) -> Self {
|
pub(super) fn from_xkb(state: &State, modifiers: Modifiers, keycode: Keycode) -> Self {
|
||||||
let mut modifiers = modifiers;
|
let mut modifiers = modifiers;
|
||||||
|
@ -813,6 +806,7 @@ impl Keystroke {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
impl Modifiers {
|
impl Modifiers {
|
||||||
pub(super) fn from_xkb(keymap_state: &State) -> Self {
|
pub(super) fn from_xkb(keymap_state: &State) -> Self {
|
||||||
let shift = keymap_state.mod_name_is_active(xkb::MOD_NAME_SHIFT, xkb::STATE_MODS_EFFECTIVE);
|
let shift = keymap_state.mod_name_is_active(xkb::MOD_NAME_SHIFT, xkb::STATE_MODS_EFFECTIVE);
|
||||||
|
|
|
@ -6,3 +6,35 @@ mod serial;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
pub(crate) use client::*;
|
pub(crate) use client::*;
|
||||||
|
|
||||||
|
use wayland_protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::Shape;
|
||||||
|
|
||||||
|
use crate::CursorStyle;
|
||||||
|
|
||||||
|
impl CursorStyle {
|
||||||
|
pub(super) fn to_shape(&self) -> Shape {
|
||||||
|
match self {
|
||||||
|
CursorStyle::Arrow => Shape::Default,
|
||||||
|
CursorStyle::IBeam => Shape::Text,
|
||||||
|
CursorStyle::Crosshair => Shape::Crosshair,
|
||||||
|
CursorStyle::ClosedHand => Shape::Grabbing,
|
||||||
|
CursorStyle::OpenHand => Shape::Grab,
|
||||||
|
CursorStyle::PointingHand => Shape::Pointer,
|
||||||
|
CursorStyle::ResizeLeft => Shape::WResize,
|
||||||
|
CursorStyle::ResizeRight => Shape::EResize,
|
||||||
|
CursorStyle::ResizeLeftRight => Shape::EwResize,
|
||||||
|
CursorStyle::ResizeUp => Shape::NResize,
|
||||||
|
CursorStyle::ResizeDown => Shape::SResize,
|
||||||
|
CursorStyle::ResizeUpDown => Shape::NsResize,
|
||||||
|
CursorStyle::ResizeUpLeftDownRight => Shape::NwseResize,
|
||||||
|
CursorStyle::ResizeUpRightDownLeft => Shape::NeswResize,
|
||||||
|
CursorStyle::ResizeColumn => Shape::ColResize,
|
||||||
|
CursorStyle::ResizeRow => Shape::RowResize,
|
||||||
|
CursorStyle::IBeamCursorForVerticalLayout => Shape::VerticalText,
|
||||||
|
CursorStyle::OperationNotAllowed => Shape::NotAllowed,
|
||||||
|
CursorStyle::DragLink => Shape::Alias,
|
||||||
|
CursorStyle::DragCopy => Shape::Copy,
|
||||||
|
CursorStyle::ContextualMenu => Shape::ContextMenu,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1421,10 +1421,12 @@ impl LinuxClient for X11Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_uri(&self, uri: &str) {
|
fn open_uri(&self, uri: &str) {
|
||||||
|
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||||
open_uri_internal(self.background_executor(), uri, None);
|
open_uri_internal(self.background_executor(), uri, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reveal_path(&self, path: PathBuf) {
|
fn reveal_path(&self, path: PathBuf) {
|
||||||
|
#[cfg(any(feature = "x11", feature = "wayland"))]
|
||||||
reveal_path_internal(self.background_executor(), path, None);
|
reveal_path_internal(self.background_executor(), path, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@ use crate::{BackgroundExecutor, WindowAppearance};
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
WindowAppearance(WindowAppearance),
|
WindowAppearance(WindowAppearance),
|
||||||
|
#[cfg_attr(feature = "x11", allow(dead_code))]
|
||||||
CursorTheme(String),
|
CursorTheme(String),
|
||||||
|
#[cfg_attr(feature = "x11", allow(dead_code))]
|
||||||
CursorSize(u32),
|
CursorSize(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,14 @@ use metal_renderer as renderer;
|
||||||
use crate::platform::blade as renderer;
|
use crate::platform::blade as renderer;
|
||||||
|
|
||||||
mod attributed_string;
|
mod attributed_string;
|
||||||
|
|
||||||
|
#[cfg(feature = "font-kit")]
|
||||||
mod open_type;
|
mod open_type;
|
||||||
mod platform;
|
|
||||||
|
#[cfg(feature = "font-kit")]
|
||||||
mod text_system;
|
mod text_system;
|
||||||
|
|
||||||
|
mod platform;
|
||||||
mod window;
|
mod window;
|
||||||
mod window_appearance;
|
mod window_appearance;
|
||||||
|
|
||||||
|
@ -39,9 +44,11 @@ pub(crate) use dispatcher::*;
|
||||||
pub(crate) use display::*;
|
pub(crate) use display::*;
|
||||||
pub(crate) use display_link::*;
|
pub(crate) use display_link::*;
|
||||||
pub(crate) use platform::*;
|
pub(crate) use platform::*;
|
||||||
pub(crate) use text_system::*;
|
|
||||||
pub(crate) use window::*;
|
pub(crate) use window::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "font-kit")]
|
||||||
|
pub(crate) use text_system::*;
|
||||||
|
|
||||||
trait BoolExt {
|
trait BoolExt {
|
||||||
fn to_objc(self) -> BOOL;
|
fn to_objc(self) -> BOOL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ use super::{
|
||||||
use crate::{
|
use crate::{
|
||||||
hash, Action, AnyWindowHandle, BackgroundExecutor, ClipboardEntry, ClipboardItem,
|
hash, Action, AnyWindowHandle, BackgroundExecutor, ClipboardEntry, ClipboardItem,
|
||||||
ClipboardString, CursorStyle, ForegroundExecutor, Image, ImageFormat, Keymap, MacDispatcher,
|
ClipboardString, CursorStyle, ForegroundExecutor, Image, ImageFormat, Keymap, MacDispatcher,
|
||||||
MacDisplay, MacTextSystem, MacWindow, Menu, MenuItem, PathPromptOptions, Platform,
|
MacDisplay, MacWindow, Menu, MenuItem, PathPromptOptions, Platform, PlatformDisplay,
|
||||||
PlatformDisplay, PlatformTextSystem, PlatformWindow, Result, SemanticVersion, Task,
|
PlatformTextSystem, PlatformWindow, Result, SemanticVersion, Task, WindowAppearance,
|
||||||
WindowAppearance, WindowParams,
|
WindowParams,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
@ -145,7 +145,7 @@ pub(crate) struct MacPlatform(Mutex<MacPlatformState>);
|
||||||
pub(crate) struct MacPlatformState {
|
pub(crate) struct MacPlatformState {
|
||||||
background_executor: BackgroundExecutor,
|
background_executor: BackgroundExecutor,
|
||||||
foreground_executor: ForegroundExecutor,
|
foreground_executor: ForegroundExecutor,
|
||||||
text_system: Arc<MacTextSystem>,
|
text_system: Arc<dyn PlatformTextSystem>,
|
||||||
renderer_context: renderer::Context,
|
renderer_context: renderer::Context,
|
||||||
headless: bool,
|
headless: bool,
|
||||||
pasteboard: id,
|
pasteboard: id,
|
||||||
|
@ -171,11 +171,18 @@ impl Default for MacPlatform {
|
||||||
impl MacPlatform {
|
impl MacPlatform {
|
||||||
pub(crate) fn new(headless: bool) -> Self {
|
pub(crate) fn new(headless: bool) -> Self {
|
||||||
let dispatcher = Arc::new(MacDispatcher::new());
|
let dispatcher = Arc::new(MacDispatcher::new());
|
||||||
|
|
||||||
|
#[cfg(feature = "font-kit")]
|
||||||
|
let text_system = Arc::new(crate::MacTextSystem::new());
|
||||||
|
|
||||||
|
#[cfg(not(feature = "font-kit"))]
|
||||||
|
let text_system = Arc::new(crate::NoopTextSystem::new());
|
||||||
|
|
||||||
Self(Mutex::new(MacPlatformState {
|
Self(Mutex::new(MacPlatformState {
|
||||||
background_executor: BackgroundExecutor::new(dispatcher.clone()),
|
|
||||||
headless,
|
headless,
|
||||||
|
text_system,
|
||||||
|
background_executor: BackgroundExecutor::new(dispatcher.clone()),
|
||||||
foreground_executor: ForegroundExecutor::new(dispatcher),
|
foreground_executor: ForegroundExecutor::new(dispatcher),
|
||||||
text_system: Arc::new(MacTextSystem::new()),
|
|
||||||
renderer_context: renderer::Context::default(),
|
renderer_context: renderer::Context::default(),
|
||||||
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
|
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
|
||||||
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
|
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
|
||||||
|
|
|
@ -40,6 +40,10 @@ impl Scene {
|
||||||
self.surfaces.clear();
|
self.surfaces.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
pub fn paths(&self) -> &[Path<ScaledPixels>] {
|
pub fn paths(&self) -> &[Path<ScaledPixels>] {
|
||||||
&self.paths
|
&self.paths
|
||||||
}
|
}
|
||||||
|
@ -130,6 +134,10 @@ impl Scene {
|
||||||
self.surfaces.sort();
|
self.surfaces.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
pub(crate) fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
|
pub(crate) fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
|
||||||
BatchIterator {
|
BatchIterator {
|
||||||
shadows: &self.shadows,
|
shadows: &self.shadows,
|
||||||
|
@ -158,6 +166,10 @@ impl Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Default)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Default)]
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
pub(crate) enum PrimitiveKind {
|
pub(crate) enum PrimitiveKind {
|
||||||
Shadow,
|
Shadow,
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -212,6 +224,10 @@ impl Primitive {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
struct BatchIterator<'a> {
|
struct BatchIterator<'a> {
|
||||||
shadows: &'a [Shadow],
|
shadows: &'a [Shadow],
|
||||||
shadows_start: usize,
|
shadows_start: usize,
|
||||||
|
@ -398,6 +414,10 @@ impl<'a> Iterator for BatchIterator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(
|
||||||
|
all(target_os = "linux", not(any(feature = "x11", feature = "wayland"))),
|
||||||
|
allow(dead_code)
|
||||||
|
)]
|
||||||
pub(crate) enum PrimitiveBatch<'a> {
|
pub(crate) enum PrimitiveBatch<'a> {
|
||||||
Shadows(&'a [Shadow]),
|
Shadows(&'a [Shadow]),
|
||||||
Quads(&'a [Quad]),
|
Quads(&'a [Quad]),
|
||||||
|
|
|
@ -390,40 +390,11 @@ impl SshClientDelegate {
|
||||||
|
|
||||||
// In dev mode, build the remote server binary from source
|
// In dev mode, build the remote server binary from source
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
if release_channel == ReleaseChannel::Dev
|
if release_channel == ReleaseChannel::Dev {
|
||||||
&& platform.arch == std::env::consts::ARCH
|
let result = self.build_local(cx, platform, version).await?;
|
||||||
&& platform.os == std::env::consts::OS
|
// Fall through to a remote binary if we're not able to compile a local binary
|
||||||
{
|
if let Some(result) = result {
|
||||||
use smol::process::{Command, Stdio};
|
return Ok(result);
|
||||||
|
|
||||||
self.update_status(Some("building remote server binary from source"), cx);
|
|
||||||
log::info!("building remote server binary from source");
|
|
||||||
run_cmd(Command::new("cargo").args([
|
|
||||||
"build",
|
|
||||||
"--package",
|
|
||||||
"remote_server",
|
|
||||||
"--target-dir",
|
|
||||||
"target/remote_server",
|
|
||||||
]))
|
|
||||||
.await?;
|
|
||||||
// run_cmd(Command::new("strip").args(["target/remote_server/debug/remote_server"]))
|
|
||||||
// .await?;
|
|
||||||
run_cmd(Command::new("gzip").args([
|
|
||||||
"-9",
|
|
||||||
"-f",
|
|
||||||
"target/remote_server/debug/remote_server",
|
|
||||||
]))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let path = std::env::current_dir()?.join("target/remote_server/debug/remote_server.gz");
|
|
||||||
return Ok((path, version));
|
|
||||||
|
|
||||||
async fn run_cmd(command: &mut Command) -> Result<()> {
|
|
||||||
let output = command.stderr(Stdio::inherit()).output().await?;
|
|
||||||
if !output.status.success() {
|
|
||||||
Err(anyhow::anyhow!("failed to run command: {:?}", command))?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,6 +417,105 @@ impl SshClientDelegate {
|
||||||
|
|
||||||
Ok((binary_path, version))
|
Ok((binary_path, version))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
async fn build_local(
|
||||||
|
&self,
|
||||||
|
cx: &mut AsyncAppContext,
|
||||||
|
platform: SshPlatform,
|
||||||
|
version: SemanticVersion,
|
||||||
|
) -> Result<Option<(PathBuf, SemanticVersion)>> {
|
||||||
|
use smol::process::{Command, Stdio};
|
||||||
|
|
||||||
|
async fn run_cmd(command: &mut Command) -> Result<()> {
|
||||||
|
let output = command.stderr(Stdio::inherit()).output().await?;
|
||||||
|
if !output.status.success() {
|
||||||
|
Err(anyhow::anyhow!("failed to run command: {:?}", command))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
if platform.arch == std::env::consts::ARCH && platform.os == std::env::consts::OS {
|
||||||
|
self.update_status(Some("Building remote server binary from source"), cx);
|
||||||
|
log::info!("building remote server binary from source");
|
||||||
|
run_cmd(Command::new("cargo").args([
|
||||||
|
"build",
|
||||||
|
"--package",
|
||||||
|
"remote_server",
|
||||||
|
"--target-dir",
|
||||||
|
"target/remote_server",
|
||||||
|
]))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.update_status(Some("Compressing binary"), cx);
|
||||||
|
|
||||||
|
run_cmd(Command::new("gzip").args([
|
||||||
|
"-9",
|
||||||
|
"-f",
|
||||||
|
"target/remote_server/debug/remote_server",
|
||||||
|
]))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let path = std::env::current_dir()?.join("target/remote_server/debug/remote_server.gz");
|
||||||
|
return Ok(Some((path, version)));
|
||||||
|
} else if let Some(triple) = platform.triple() {
|
||||||
|
smol::fs::create_dir_all("target/remote-server").await?;
|
||||||
|
|
||||||
|
self.update_status(Some("Installing cross.rs"), cx);
|
||||||
|
log::info!("installing cross");
|
||||||
|
run_cmd(Command::new("cargo").args([
|
||||||
|
"install",
|
||||||
|
"cross",
|
||||||
|
"--git",
|
||||||
|
"https://github.com/cross-rs/cross",
|
||||||
|
]))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.update_status(
|
||||||
|
Some(&format!(
|
||||||
|
"Building remote server binary from source for {}",
|
||||||
|
&triple
|
||||||
|
)),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
log::info!("building remote server binary from source for {}", &triple);
|
||||||
|
run_cmd(
|
||||||
|
Command::new("cross")
|
||||||
|
.args([
|
||||||
|
"build",
|
||||||
|
"--package",
|
||||||
|
"remote_server",
|
||||||
|
"--target-dir",
|
||||||
|
"target/remote_server",
|
||||||
|
"--target",
|
||||||
|
&triple,
|
||||||
|
])
|
||||||
|
.env(
|
||||||
|
"CROSS_CONTAINER_OPTS",
|
||||||
|
"--mount type=bind,src=./target,dst=/app/target",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.update_status(Some("Compressing binary"), cx);
|
||||||
|
|
||||||
|
run_cmd(Command::new("gzip").args([
|
||||||
|
"-9",
|
||||||
|
"-f",
|
||||||
|
&format!("target/remote_server/{}/debug/remote_server", triple),
|
||||||
|
]))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let path = std::env::current_dir()?.join(format!(
|
||||||
|
"target/remote_server/{}/debug/remote_server.gz",
|
||||||
|
triple
|
||||||
|
));
|
||||||
|
|
||||||
|
return Ok(Some((path, version)));
|
||||||
|
} else {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_over_ssh(
|
pub fn connect_over_ssh(
|
||||||
|
|
|
@ -118,6 +118,20 @@ pub struct SshPlatform {
|
||||||
pub arch: &'static str,
|
pub arch: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SshPlatform {
|
||||||
|
pub fn triple(&self) -> Option<String> {
|
||||||
|
Some(format!(
|
||||||
|
"{}-{}",
|
||||||
|
self.arch,
|
||||||
|
match self.os {
|
||||||
|
"linux" => "unknown-linux-gnu",
|
||||||
|
"macos" => "apple-darwin",
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SshClientDelegate: Send + Sync {
|
pub trait SshClientDelegate: Send + Sync {
|
||||||
fn ask_password(
|
fn ask_password(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -35,10 +35,7 @@ sha2.workspace = true
|
||||||
strum.workspace = true
|
strum.workspace = true
|
||||||
tracing = { version = "0.1.34", features = ["log"] }
|
tracing = { version = "0.1.34", features = ["log"] }
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
zstd = "0.11"
|
zstd.workspace = true
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
|
||||||
zstd = { version = "0.11", features = [ "pkg-config" ] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
collections = { workspace = true, features = ["test-support"] }
|
collections = { workspace = true, features = ["test-support"] }
|
||||||
|
|
|
@ -51,7 +51,7 @@ futures.workspace = true
|
||||||
git.workspace = true
|
git.workspace = true
|
||||||
git_hosting_providers.workspace = true
|
git_hosting_providers.workspace = true
|
||||||
go_to_line.workspace = true
|
go_to_line.workspace = true
|
||||||
gpui.workspace = true
|
gpui = { workspace = true, features = ["wayland", "x11", "font-kit"] }
|
||||||
headless.workspace = true
|
headless.workspace = true
|
||||||
http_client.workspace = true
|
http_client.workspace = true
|
||||||
image_viewer.workspace = true
|
image_viewer.workspace = true
|
||||||
|
@ -125,6 +125,8 @@ winresource = "0.1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
ashpd.workspace = true
|
ashpd.workspace = true
|
||||||
|
# We don't use zstd in the zed crate, but we want to add this feature when compiling a desktop build of Zed
|
||||||
|
zstd = { workspace = true, features = [ "pkg-config" ] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
call = { workspace = true, features = ["test-support"] }
|
call = { workspace = true, features = ["test-support"] }
|
||||||
|
@ -169,4 +171,4 @@ osx_info_plist_exts = ["resources/info/*"]
|
||||||
osx_url_schemes = ["zed"]
|
osx_url_schemes = ["zed"]
|
||||||
|
|
||||||
[package.metadata.cargo-machete]
|
[package.metadata.cargo-machete]
|
||||||
ignored = ["profiling"]
|
ignored = ["profiling", "zstd"]
|
||||||
|
|
17
script/remote-server
Executable file
17
script/remote-server
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -xeuo pipefail
|
||||||
|
|
||||||
|
# if root or if sudo/unavailable, define an empty variable
|
||||||
|
if [ "$(id -u)" -eq 0 ]
|
||||||
|
then maysudo=''
|
||||||
|
else maysudo="$(command -v sudo || command -v doas || true)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
deps=(
|
||||||
|
clang
|
||||||
|
)
|
||||||
|
|
||||||
|
$maysudo apt-get update
|
||||||
|
$maysudo apt-get install -y "${deps[@]}"
|
||||||
|
exit 0
|
Loading…
Add table
Add a link
Reference in a new issue