Detailed changes
@@ -1750,15 +1750,6 @@ dependencies = [
"bit-vec 0.6.3",
]
-[[package]]
-name = "bit-set"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"
-dependencies = [
- "bit-vec 0.7.0",
-]
-
[[package]]
name = "bit-set"
version = "0.8.0"
@@ -1774,12 +1765,6 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
-[[package]]
-name = "bit-vec"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
-
[[package]]
name = "bit-vec"
version = "0.8.0"
@@ -1828,7 +1813,7 @@ dependencies = [
[[package]]
name = "blade-graphics"
version = "0.5.0"
-source = "git+https://github.com/kvark/blade?rev=e142a3a5e678eb6a13e642ad8401b1f3aa38e969#e142a3a5e678eb6a13e642ad8401b1f3aa38e969"
+source = "git+https://github.com/kvark/blade?rev=099555282605c7c4cca9e66a8f40148298347f80#099555282605c7c4cca9e66a8f40148298347f80"
dependencies = [
"ash",
"ash-window",
@@ -1858,7 +1843,7 @@ dependencies = [
[[package]]
name = "blade-macros"
version = "0.3.0"
-source = "git+https://github.com/kvark/blade?rev=e142a3a5e678eb6a13e642ad8401b1f3aa38e969#e142a3a5e678eb6a13e642ad8401b1f3aa38e969"
+source = "git+https://github.com/kvark/blade?rev=099555282605c7c4cca9e66a8f40148298347f80#099555282605c7c4cca9e66a8f40148298347f80"
dependencies = [
"proc-macro2",
"quote",
@@ -1868,7 +1853,7 @@ dependencies = [
[[package]]
name = "blade-util"
version = "0.1.0"
-source = "git+https://github.com/kvark/blade?rev=e142a3a5e678eb6a13e642ad8401b1f3aa38e969#e142a3a5e678eb6a13e642ad8401b1f3aa38e969"
+source = "git+https://github.com/kvark/blade?rev=099555282605c7c4cca9e66a8f40148298347f80#099555282605c7c4cca9e66a8f40148298347f80"
dependencies = [
"blade-graphics",
"bytemuck",
@@ -7594,9 +7579,8 @@ dependencies = [
[[package]]
name = "metal"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21"
+version = "0.30.0"
+source = "git+https://github.com/gfx-rs/metal-rs?rev=ef768ff9d742ae6a0f4e83ddc8031264e7d460c4#ef768ff9d742ae6a0f4e83ddc8031264e7d460c4"
dependencies = [
"bitflags 2.6.0",
"block",
@@ -7735,12 +7719,11 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
[[package]]
name = "naga"
-version = "22.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad"
+version = "23.0.0"
+source = "git+https://github.com/gfx-rs/wgpu?rev=1a643291c2e8854ba7e4f5445a4388202731bfa1#1a643291c2e8854ba7e4f5445a4388202731bfa1"
dependencies = [
"arrayvec",
- "bit-set 0.6.0",
+ "bit-set 0.8.0",
"bitflags 2.6.0",
"cfg_aliases 0.1.1",
"codespan-reporting",
@@ -355,9 +355,9 @@ async-watch = "0.3.1"
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
base64 = "0.22"
bitflags = "2.6.0"
-blade-graphics = { git = "https://github.com/kvark/blade", rev = "e142a3a5e678eb6a13e642ad8401b1f3aa38e969" }
-blade-macros = { git = "https://github.com/kvark/blade", rev = "e142a3a5e678eb6a13e642ad8401b1f3aa38e969" }
-blade-util = { git = "https://github.com/kvark/blade", rev = "e142a3a5e678eb6a13e642ad8401b1f3aa38e969" }
+blade-graphics = { git = "https://github.com/kvark/blade", rev = "099555282605c7c4cca9e66a8f40148298347f80" }
+blade-macros = { git = "https://github.com/kvark/blade", rev = "099555282605c7c4cca9e66a8f40148298347f80" }
+blade-util = { git = "https://github.com/kvark/blade", rev = "099555282605c7c4cca9e66a8f40148298347f80" }
blake3 = "1.5.3"
bytes = "1.0"
cargo_metadata = "0.19"
@@ -525,6 +525,12 @@ wasmtime-wasi = "24"
which = "6.0.0"
wit-component = "0.201"
zstd = "0.11"
+# Custom metal-rs is only needed for "macos-blade" feature of GPUI
+#TODO: switch to crates once these are published:
+# - https://github.com/gfx-rs/metal-rs/pull/335
+# - https://github.com/gfx-rs/metal-rs/pull/336
+# - https://github.com/gfx-rs/metal-rs/pull/337
+metal = { git = "https://github.com/gfx-rs/metal-rs", rev = "ef768ff9d742ae6a0f4e83ddc8031264e7d460c4" }
[workspace.dependencies.async-stripe]
git = "https://github.com/zed-industries/async-stripe"
@@ -136,8 +136,8 @@ font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "40391b7"
foreign-types = "0.5"
log.workspace = true
media.workspace = true
-metal = "0.29"
objc = "0.2"
+metal.workspace = true
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))'.dependencies]
pathfinder_geometry = "0.5"
@@ -1,5 +1,11 @@
+#[cfg(target_os = "macos")]
+mod apple_compat;
mod blade_atlas;
+mod blade_context;
mod blade_renderer;
+#[cfg(target_os = "macos")]
+pub(crate) use apple_compat::*;
pub(crate) use blade_atlas::*;
+pub(crate) use blade_context::*;
pub(crate) use blade_renderer::*;
@@ -0,0 +1,60 @@
+use super::{BladeContext, BladeRenderer, BladeSurfaceConfig};
+use blade_graphics as gpu;
+use std::{ffi::c_void, ptr::NonNull};
+
+#[derive(Clone)]
+pub struct Context {
+ inner: BladeContext,
+}
+impl Default for Context {
+ fn default() -> Self {
+ Self {
+ inner: BladeContext::new().unwrap(),
+ }
+ }
+}
+
+pub type Renderer = BladeRenderer;
+
+pub unsafe fn new_renderer(
+ context: Context,
+ _native_window: *mut c_void,
+ native_view: *mut c_void,
+ bounds: crate::Size<f32>,
+ transparent: bool,
+) -> Renderer {
+ use raw_window_handle as rwh;
+ struct RawWindow {
+ view: *mut c_void,
+ }
+
+ impl rwh::HasWindowHandle for RawWindow {
+ fn window_handle(&self) -> Result<rwh::WindowHandle, rwh::HandleError> {
+ let view = NonNull::new(self.view).unwrap();
+ let handle = rwh::AppKitWindowHandle::new(view);
+ Ok(unsafe { rwh::WindowHandle::borrow_raw(handle.into()) })
+ }
+ }
+ impl rwh::HasDisplayHandle for RawWindow {
+ fn display_handle(&self) -> Result<rwh::DisplayHandle, rwh::HandleError> {
+ let handle = rwh::AppKitDisplayHandle::new();
+ Ok(unsafe { rwh::DisplayHandle::borrow_raw(handle.into()) })
+ }
+ }
+
+ BladeRenderer::new(
+ &context.inner,
+ &RawWindow {
+ view: native_view as *mut _,
+ },
+ BladeSurfaceConfig {
+ size: gpu::Extent {
+ width: bounds.width as u32,
+ height: bounds.height as u32,
+ depth: 1,
+ },
+ transparent,
+ },
+ )
+ .unwrap()
+}
@@ -268,7 +268,7 @@ impl BladeAtlasState {
fn flush(&mut self, encoder: &mut gpu::CommandEncoder) {
self.flush_initializations(encoder);
- let mut transfers = encoder.transfer();
+ let mut transfers = encoder.transfer("atlas");
for upload in self.uploads.drain(..) {
let texture = &self.storage[upload.id];
transfers.copy_buffer_to_texture(
@@ -0,0 +1,24 @@
+use blade_graphics as gpu;
+use std::sync::Arc;
+
+#[cfg_attr(target_os = "macos", derive(Clone))]
+pub struct BladeContext {
+ pub(super) gpu: Arc<gpu::Context>,
+}
+
+impl BladeContext {
+ pub fn new() -> anyhow::Result<Self> {
+ let gpu = Arc::new(
+ unsafe {
+ gpu::Context::init(gpu::ContextDesc {
+ presentation: true,
+ validation: false,
+ device_id: 0, //TODO: hook up to user settings
+ ..Default::default()
+ })
+ }
+ .map_err(|e| anyhow::anyhow!("{:?}", e))?,
+ );
+ Ok(Self { gpu })
+ }
+}
@@ -1,7 +1,7 @@
// Doing `if let` gives you nice scoping with passes/encoders
#![allow(irrefutable_let_patterns)]
-use super::{BladeAtlas, PATH_TEXTURE_FORMAT};
+use super::{BladeAtlas, BladeContext, PATH_TEXTURE_FORMAT};
use crate::{
AtlasTextureKind, AtlasTile, Background, Bounds, ContentMask, DevicePixels, GpuSpecs,
MonochromeSprite, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad,
@@ -11,8 +11,6 @@ use bytemuck::{Pod, Zeroable};
use collections::HashMap;
#[cfg(target_os = "macos")]
use media::core_video::CVMetalTextureCache;
-#[cfg(target_os = "macos")]
-use std::{ffi::c_void, ptr::NonNull};
use blade_graphics as gpu;
use blade_util::{BufferBelt, BufferBeltDescriptor};
@@ -20,66 +18,6 @@ use std::{mem, sync::Arc};
const MAX_FRAME_TIME_MS: u32 = 10000;
-#[cfg(target_os = "macos")]
-#[derive(Clone, Default)]
-pub struct Context {}
-#[cfg(target_os = "macos")]
-pub type Renderer = BladeRenderer;
-
-#[cfg(target_os = "macos")]
-pub unsafe fn new_renderer(
- _context: self::Context,
- _native_window: *mut c_void,
- native_view: *mut c_void,
- bounds: crate::Size<f32>,
- transparent: bool,
-) -> Renderer {
- use raw_window_handle as rwh;
- struct RawWindow {
- view: *mut c_void,
- }
-
- impl rwh::HasWindowHandle for RawWindow {
- fn window_handle(&self) -> Result<rwh::WindowHandle, rwh::HandleError> {
- let view = NonNull::new(self.view).unwrap();
- let handle = rwh::AppKitWindowHandle::new(view);
- Ok(unsafe { rwh::WindowHandle::borrow_raw(handle.into()) })
- }
- }
- impl rwh::HasDisplayHandle for RawWindow {
- fn display_handle(&self) -> Result<rwh::DisplayHandle, rwh::HandleError> {
- let handle = rwh::AppKitDisplayHandle::new();
- Ok(unsafe { rwh::DisplayHandle::borrow_raw(handle.into()) })
- }
- }
-
- let gpu = Arc::new(
- gpu::Context::init_windowed(
- &RawWindow {
- view: native_view as *mut _,
- },
- gpu::ContextDesc {
- validation: cfg!(debug_assertions),
- capture: false,
- overlay: false,
- },
- )
- .unwrap(),
- );
-
- BladeRenderer::new(
- gpu,
- BladeSurfaceConfig {
- size: gpu::Extent {
- width: bounds.width as u32,
- height: bounds.height as u32,
- depth: 1,
- },
- transparent,
- },
- )
-}
-
#[repr(C)]
#[derive(Clone, Copy, Pod, Zeroable)]
struct GlobalParams {
@@ -354,10 +292,14 @@ pub struct BladeSurfaceConfig {
pub transparent: bool,
}
+//Note: we could see some of these fields moved into `BladeContext`
+// so that they are shared between windows. E.g. `pipelines`.
+// But that is complicated by the fact that pipelines depend on
+// the format and alpha mode.
pub struct BladeRenderer {
gpu: Arc<gpu::Context>,
+ surface: gpu::Surface,
surface_config: gpu::SurfaceConfig,
- alpha_mode: gpu::AlphaMode,
command_encoder: gpu::CommandEncoder,
last_sync_point: Option<gpu::SyncPoint>,
pipelines: BladePipelines,
@@ -370,7 +312,11 @@ pub struct BladeRenderer {
}
impl BladeRenderer {
- pub fn new(gpu: Arc<gpu::Context>, config: BladeSurfaceConfig) -> Self {
+ pub fn new<I: raw_window_handle::HasWindowHandle + raw_window_handle::HasDisplayHandle>(
+ context: &BladeContext,
+ window: &I,
+ config: BladeSurfaceConfig,
+ ) -> anyhow::Result<Self> {
let surface_config = gpu::SurfaceConfig {
size: config.size,
usage: gpu::TextureUsage::TARGET,
@@ -379,20 +325,23 @@ impl BladeRenderer {
allow_exclusive_full_screen: false,
transparent: config.transparent,
};
- let surface_info = gpu.resize(surface_config);
+ let surface = context
+ .gpu
+ .create_surface_configured(window, surface_config)
+ .unwrap();
- let command_encoder = gpu.create_command_encoder(gpu::CommandEncoderDesc {
+ let command_encoder = context.gpu.create_command_encoder(gpu::CommandEncoderDesc {
name: "main",
buffer_count: 2,
});
- let pipelines = BladePipelines::new(&gpu, surface_info);
+ let pipelines = BladePipelines::new(&context.gpu, surface.info());
let instance_belt = BufferBelt::new(BufferBeltDescriptor {
memory: gpu::Memory::Shared,
min_chunk_size: 0x1000,
alignment: 0x40, // Vulkan `minStorageBufferOffsetAlignment` on Intel Xe
});
- let atlas = Arc::new(BladeAtlas::new(&gpu));
- let atlas_sampler = gpu.create_sampler(gpu::SamplerDesc {
+ let atlas = Arc::new(BladeAtlas::new(&context.gpu));
+ let atlas_sampler = context.gpu.create_sampler(gpu::SamplerDesc {
name: "atlas",
mag_filter: gpu::FilterMode::Linear,
min_filter: gpu::FilterMode::Linear,
@@ -402,13 +351,13 @@ impl BladeRenderer {
#[cfg(target_os = "macos")]
let core_video_texture_cache = unsafe {
use foreign_types::ForeignType as _;
- CVMetalTextureCache::new(gpu.metal_device().as_ptr()).unwrap()
+ CVMetalTextureCache::new(context.gpu.metal_device().as_ptr()).unwrap()
};
- Self {
- gpu,
+ Ok(Self {
+ gpu: Arc::clone(&context.gpu),
+ surface,
surface_config,
- alpha_mode: surface_info.alpha,
command_encoder,
last_sync_point: None,
pipelines,
@@ -418,7 +367,7 @@ impl BladeRenderer {
atlas_sampler,
#[cfg(target_os = "macos")]
core_video_texture_cache,
- }
+ })
}
fn wait_for_gpu(&mut self) {
@@ -452,7 +401,8 @@ impl BladeRenderer {
if always_resize || gpu_size != self.surface_config.size {
self.wait_for_gpu();
self.surface_config.size = gpu_size;
- self.gpu.resize(self.surface_config);
+ self.gpu
+ .reconfigure_surface(&mut self.surface, self.surface_config);
}
}
@@ -460,10 +410,10 @@ impl BladeRenderer {
if transparent != self.surface_config.transparent {
self.wait_for_gpu();
self.surface_config.transparent = transparent;
- let surface_info = self.gpu.resize(self.surface_config);
+ self.gpu
+ .reconfigure_surface(&mut self.surface, self.surface_config);
self.pipelines.destroy(&self.gpu);
- self.pipelines = BladePipelines::new(&self.gpu, surface_info);
- self.alpha_mode = surface_info.alpha;
+ self.pipelines = BladePipelines::new(&self.gpu, self.surface.info());
}
}
@@ -490,13 +440,13 @@ impl BladeRenderer {
#[cfg(target_os = "macos")]
pub fn layer(&self) -> metal::MetalLayer {
- self.gpu.metal_layer().unwrap()
+ self.surface.metal_layer()
}
#[cfg(target_os = "macos")]
pub fn layer_ptr(&self) -> *mut metal::CAMetalLayer {
use metal::foreign_types::ForeignType as _;
- self.gpu.metal_layer().unwrap().as_ptr()
+ self.surface.metal_layer().as_ptr()
}
#[profiling::function]
@@ -538,14 +488,17 @@ impl BladeRenderer {
};
let vertex_buf = unsafe { self.instance_belt.alloc_typed(&vertices, &self.gpu) };
- let mut pass = self.command_encoder.render(gpu::RenderTargetSet {
- colors: &[gpu::RenderTarget {
- view: tex_info.raw_view,
- init_op: gpu::InitOp::Clear(gpu::TextureColor::OpaqueBlack),
- finish_op: gpu::FinishOp::Store,
- }],
- depth_stencil: None,
- });
+ let mut pass = self.command_encoder.render(
+ "paths",
+ gpu::RenderTargetSet {
+ colors: &[gpu::RenderTarget {
+ view: tex_info.raw_view,
+ init_op: gpu::InitOp::Clear(gpu::TextureColor::OpaqueBlack),
+ finish_op: gpu::FinishOp::Store,
+ }],
+ depth_stencil: None,
+ },
+ );
let mut encoder = pass.with(&self.pipelines.path_rasterization);
encoder.bind(
@@ -566,6 +519,7 @@ impl BladeRenderer {
self.instance_belt.destroy(&self.gpu);
self.gpu.destroy_command_encoder(&mut self.command_encoder);
self.pipelines.destroy(&self.gpu);
+ self.gpu.destroy_surface(&mut self.surface);
}
pub fn draw(&mut self, scene: &Scene) {
@@ -575,7 +529,7 @@ impl BladeRenderer {
let frame = {
profiling::scope!("acquire frame");
- self.gpu.acquire_frame()
+ self.surface.acquire_frame()
};
self.command_encoder.init_texture(frame.texture());
@@ -584,21 +538,24 @@ impl BladeRenderer {
self.surface_config.size.width as f32,
self.surface_config.size.height as f32,
],
- premultiplied_alpha: match self.alpha_mode {
+ premultiplied_alpha: match self.surface.info().alpha {
gpu::AlphaMode::Ignored | gpu::AlphaMode::PostMultiplied => 0,
gpu::AlphaMode::PreMultiplied => 1,
},
pad: 0,
};
- if let mut pass = self.command_encoder.render(gpu::RenderTargetSet {
- colors: &[gpu::RenderTarget {
- view: frame.texture_view(),
- init_op: gpu::InitOp::Clear(gpu::TextureColor::TransparentBlack),
- finish_op: gpu::FinishOp::Store,
- }],
- depth_stencil: None,
- }) {
+ if let mut pass = self.command_encoder.render(
+ "main",
+ gpu::RenderTargetSet {
+ colors: &[gpu::RenderTarget {
+ view: frame.texture_view(),
+ init_op: gpu::InitOp::Clear(gpu::TextureColor::TransparentBlack),
+ finish_op: gpu::FinishOp::Store,
+ }],
+ depth_stencil: None,
+ },
+ ) {
profiling::scope!("render pass");
for batch in scene.batches() {
match batch {
@@ -1,52 +1,45 @@
-#![allow(unused)]
-
-use std::any::{type_name, Any};
-use std::cell::{self, RefCell};
-use std::env;
-use std::ffi::OsString;
-use std::fs::File;
-use std::io::Read;
-use std::ops::{Deref, DerefMut};
-use std::os::fd::{AsFd, AsRawFd, FromRawFd};
-use std::panic::{AssertUnwindSafe, Location};
-use std::rc::Weak;
use std::{
+ env,
+ panic::AssertUnwindSafe,
path::{Path, PathBuf},
process::Command,
rc::Rc,
sync::Arc,
+};
+#[cfg(any(feature = "wayland", feature = "x11"))]
+use std::{
+ ffi::OsString,
+ fs::File,
+ io::Read as _,
+ os::fd::{AsFd, AsRawFd, FromRawFd},
time::Duration,
};
use anyhow::{anyhow, Context as _};
use async_task::Runnable;
-use calloop::channel::Channel;
-use calloop::{EventLoop, LoopHandle, LoopSignal};
-use flume::{Receiver, Sender};
+use calloop::{channel::Channel, LoopSignal};
use futures::{channel::oneshot, future::FutureExt};
-use parking_lot::Mutex;
-use util::ResultExt;
-
+use util::ResultExt as _;
#[cfg(any(feature = "wayland", feature = "x11"))]
use xkbcommon::xkb::{self, Keycode, Keysym, State};
-use crate::platform::NoopTextSystem;
use crate::{
px, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
- ForegroundExecutor, Keymap, Keystroke, LinuxDispatcher, Menu, MenuItem, Modifiers, OwnedMenu,
- PathPromptOptions, Pixels, Platform, PlatformDisplay, PlatformInputHandler, PlatformTextSystem,
- PlatformWindow, Point, PromptLevel, Result, ScreenCaptureSource, SemanticVersion, SharedString,
- Size, Task, WindowAppearance, WindowOptions, WindowParams,
+ ForegroundExecutor, Keymap, LinuxDispatcher, Menu, MenuItem, OwnedMenu, PathPromptOptions,
+ Pixels, Platform, PlatformDisplay, PlatformTextSystem, PlatformWindow, Point, Result,
+ ScreenCaptureSource, Task, WindowAppearance, WindowParams,
};
-
+#[cfg(any(feature = "wayland", feature = "x11"))]
pub(crate) const SCROLL_LINES: f32 = 3.0;
// Values match the defaults on GTK.
// Taken from https://github.com/GNOME/gtk/blob/main/gtk/gtksettings.c#L320
+#[cfg(any(feature = "wayland", feature = "x11"))]
pub(crate) const DOUBLE_CLICK_INTERVAL: Duration = Duration::from_millis(400);
pub(crate) const DOUBLE_CLICK_DISTANCE: Pixels = px(5.0);
pub(crate) const KEYRING_LABEL: &str = "zed-github-account";
+#[cfg(any(feature = "wayland", feature = "x11"))]
const FILE_PICKER_PORTAL_MISSING: &str =
"Couldn't open file picker due to missing xdg-desktop-portal implementation.";
@@ -54,8 +47,9 @@ pub trait LinuxClient {
fn compositor_name(&self) -> &'static str;
fn with_common<R>(&self, f: impl FnOnce(&mut LinuxCommon) -> R) -> R;
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>>;
- fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;
+ #[allow(unused)]
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>>;
+ fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;
fn open_window(
&self,
@@ -98,9 +92,9 @@ pub(crate) struct LinuxCommon {
impl LinuxCommon {
pub fn new(signal: LoopSignal) -> (Self, Channel<Runnable>) {
let (main_sender, main_receiver) = calloop::channel::channel::<Runnable>();
+
#[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());
@@ -218,7 +212,7 @@ impl<P: LinuxClient + 'static> Platform for P {
}
}
- fn activate(&self, ignoring_other_apps: bool) {
+ fn activate(&self, _ignoring_other_apps: bool) {
log::info!("activate is not implemented on Linux, ignoring the call")
}
@@ -281,7 +275,7 @@ impl<P: LinuxClient + 'static> Platform for P {
let (done_tx, done_rx) = oneshot::channel();
#[cfg(not(any(feature = "wayland", feature = "x11")))]
- done_tx.send(Ok(None));
+ let _ = (done_tx.send(Ok(None)), options);
#[cfg(any(feature = "wayland", feature = "x11"))]
self.foreground_executor()
@@ -306,7 +300,7 @@ impl<P: LinuxClient + 'static> Platform for P {
ashpd::Error::PortalNotFound(_) => anyhow!(FILE_PICKER_PORTAL_MISSING),
err => err.into(),
};
- done_tx.send(Err(result));
+ let _ = done_tx.send(Err(result));
return;
}
};
@@ -322,7 +316,7 @@ impl<P: LinuxClient + 'static> Platform for P {
Err(ashpd::Error::Response(_)) => Ok(None),
Err(e) => Err(e.into()),
};
- done_tx.send(result);
+ let _ = done_tx.send(result);
})
.detach();
done_rx
@@ -332,7 +326,7 @@ impl<P: LinuxClient + 'static> Platform for P {
let (done_tx, done_rx) = oneshot::channel();
#[cfg(not(any(feature = "wayland", feature = "x11")))]
- done_tx.send(Ok(None));
+ let _ = (done_tx.send(Ok(None)), directory);
#[cfg(any(feature = "wayland", feature = "x11"))]
self.foreground_executor()
@@ -356,7 +350,7 @@ impl<P: LinuxClient + 'static> Platform for P {
}
err => err.into(),
};
- done_tx.send(Err(result));
+ let _ = done_tx.send(Err(result));
return;
}
};
@@ -369,7 +363,7 @@ impl<P: LinuxClient + 'static> Platform for P {
Err(ashpd::Error::Response(_)) => Ok(None),
Err(e) => Err(e.into()),
};
- done_tx.send(result);
+ let _ = done_tx.send(result);
}
})
.detach();
@@ -426,7 +420,7 @@ impl<P: LinuxClient + 'static> Platform for P {
fn app_path(&self) -> Result<PathBuf> {
// get the path of the executable of the current process
- let exe_path = std::env::current_exe()?;
+ let exe_path = env::current_exe()?;
Ok(exe_path)
}
@@ -440,9 +434,9 @@ impl<P: LinuxClient + 'static> Platform for P {
self.with_common(|common| Some(common.menus.clone()))
}
- fn set_dock_menu(&self, menu: Vec<MenuItem>, keymap: &Keymap) {}
+ fn set_dock_menu(&self, _menu: Vec<MenuItem>, _keymap: &Keymap) {}
- fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
+ fn path_for_auxiliary_executable(&self, _name: &str) -> Result<PathBuf> {
Err(anyhow::Error::msg(
"Platform<LinuxPlatform>::path_for_auxiliary_executable is not implemented yet",
))
@@ -614,6 +608,7 @@ pub(super) fn reveal_path_internal(
.detach();
}
+#[allow(unused)]
pub(super) fn is_within_click_distance(a: Point<Pixels>, b: Point<Pixels>) -> bool {
let diff = a - b;
diff.x.abs() <= DOUBLE_CLICK_DISTANCE && diff.y.abs() <= DOUBLE_CLICK_DISTANCE
@@ -622,7 +617,7 @@ pub(super) fn is_within_click_distance(a: Point<Pixels>, b: Point<Pixels>) -> bo
#[cfg(any(feature = "wayland", feature = "x11"))]
pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::State> {
let mut locales = Vec::default();
- if let Some(locale) = std::env::var_os("LC_CTYPE") {
+ if let Some(locale) = env::var_os("LC_CTYPE") {
locales.push(locale);
}
locales.push(OsString::from("C"));
@@ -650,6 +645,7 @@ pub(super) unsafe fn read_fd(mut fd: filedescriptor::FileDescriptor) -> Result<V
}
impl CursorStyle {
+ #[allow(unused)]
pub(super) fn to_icon_name(&self) -> String {
// 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
@@ -682,10 +678,12 @@ impl CursorStyle {
}
#[cfg(any(feature = "wayland", feature = "x11"))]
-impl Keystroke {
- pub(super) fn from_xkb(state: &State, modifiers: Modifiers, keycode: Keycode) -> Self {
- let mut modifiers = modifiers;
-
+impl crate::Keystroke {
+ pub(super) fn from_xkb(
+ state: &State,
+ mut modifiers: crate::Modifiers,
+ keycode: Keycode,
+ ) -> Self {
let key_utf32 = state.key_get_utf32(keycode);
let key_utf8 = state.key_get_utf8(keycode);
let key_sym = state.key_get_one_sym(keycode);
@@ -759,7 +757,7 @@ impl Keystroke {
let key_char =
(key_utf32 >= 32 && key_utf32 != 127 && !key_utf8.is_empty()).then_some(key_utf8);
- Keystroke {
+ Self {
modifiers,
key,
key_char,
@@ -776,7 +774,6 @@ impl Keystroke {
Keysym::dead_acute => Some("Β΄".to_owned()),
Keysym::dead_circumflex => Some("^".to_owned()),
Keysym::dead_tilde => Some("~".to_owned()),
- Keysym::dead_perispomeni => Some("Ν".to_owned()),
Keysym::dead_macron => Some("Β―".to_owned()),
Keysym::dead_breve => Some("Λ".to_owned()),
Keysym::dead_abovedot => Some("Λ".to_owned()),
@@ -794,9 +791,7 @@ impl Keystroke {
Keysym::dead_horn => Some("Μ".to_owned()),
Keysym::dead_stroke => Some("ΜΆΜΆ".to_owned()),
Keysym::dead_abovecomma => Some("ΜΜ".to_owned()),
- Keysym::dead_psili => Some("αΎΏ".to_owned()),
Keysym::dead_abovereversedcomma => Some("Κ½".to_owned()),
- Keysym::dead_dasia => Some("αΏΎ".to_owned()),
Keysym::dead_doublegrave => Some("Μ".to_owned()),
Keysym::dead_belowring => Some("Λ³".to_owned()),
Keysym::dead_belowmacron => Some("Μ±".to_owned()),
@@ -830,7 +825,7 @@ impl Keystroke {
}
#[cfg(any(feature = "wayland", feature = "x11"))]
-impl Modifiers {
+impl crate::Modifiers {
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 alt = keymap_state.mod_name_is_active(xkb::MOD_NAME_ALT, xkb::STATE_MODS_EFFECTIVE);
@@ -838,7 +833,7 @@ impl Modifiers {
keymap_state.mod_name_is_active(xkb::MOD_NAME_CTRL, xkb::STATE_MODS_EFFECTIVE);
let platform =
keymap_state.mod_name_is_active(xkb::MOD_NAME_LOGO, xkb::STATE_MODS_EFFECTIVE);
- Modifiers {
+ Self {
shift,
alt,
control,
@@ -1,12 +1,16 @@
-use std::cell::{RefCell, RefMut};
-use std::hash::Hash;
-use std::os::fd::{AsRawFd, BorrowedFd};
-use std::path::PathBuf;
-use std::rc::{Rc, Weak};
-use std::time::{Duration, Instant};
-
-use calloop::timer::{TimeoutAction, Timer};
-use calloop::{EventLoop, LoopHandle};
+use std::{
+ cell::{RefCell, RefMut},
+ hash::Hash,
+ os::fd::{AsRawFd, BorrowedFd},
+ path::PathBuf,
+ rc::{Rc, Weak},
+ time::{Duration, Instant},
+};
+
+use calloop::{
+ timer::{TimeoutAction, Timer},
+ EventLoop, LoopHandle,
+};
use calloop_wayland_source::WaylandSource;
use collections::HashMap;
use filedescriptor::Pipe;
@@ -64,30 +68,28 @@ use xkbcommon::xkb::{self, Keycode, KEYMAP_COMPILE_NO_FLAGS};
use super::display::WaylandDisplay;
use super::window::{ImeInput, WaylandWindowStatePtr};
-use crate::platform::linux::wayland::clipboard::{
- Clipboard, DataOffer, FILE_LIST_MIME_TYPE, TEXT_MIME_TYPE,
-};
-use crate::platform::linux::wayland::cursor::Cursor;
-use crate::platform::linux::wayland::serial::{SerialKind, SerialTracker};
-use crate::platform::linux::wayland::window::WaylandWindow;
-use crate::platform::linux::xdg_desktop_portal::{Event as XDPEvent, XDPEventSource};
-use crate::platform::linux::LinuxClient;
+
use crate::platform::linux::{
get_xkb_compose_state, is_within_click_distance, open_uri_internal, read_fd,
reveal_path_internal,
+ wayland::{
+ clipboard::{Clipboard, DataOffer, FILE_LIST_MIME_TYPE, TEXT_MIME_TYPE},
+ cursor::Cursor,
+ serial::{SerialKind, SerialTracker},
+ window::WaylandWindow,
+ },
+ xdg_desktop_portal::{Event as XDPEvent, XDPEventSource},
+ LinuxClient,
};
-use crate::platform::PlatformWindow;
-use crate::{
- point, px, size, Bounds, DevicePixels, FileDropEvent, ForegroundExecutor, MouseExitEvent, Size,
- DOUBLE_CLICK_INTERVAL, SCROLL_LINES,
-};
+use crate::platform::{blade::BladeContext, PlatformWindow};
use crate::{
- AnyWindowHandle, CursorStyle, DisplayId, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers,
- ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
- NavigationDirection, Pixels, PlatformDisplay, PlatformInput, Point, ScaledPixels, ScrollDelta,
- ScrollWheelEvent, TouchPhase,
+ point, px, size, AnyWindowHandle, Bounds, CursorStyle, DevicePixels, DisplayId, FileDropEvent,
+ ForegroundExecutor, KeyDownEvent, KeyUpEvent, Keystroke, LinuxCommon, Modifiers,
+ ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent,
+ MouseUpEvent, NavigationDirection, Pixels, PlatformDisplay, PlatformInput, Point, ScaledPixels,
+ ScrollDelta, ScrollWheelEvent, Size, TouchPhase, WindowParams, DOUBLE_CLICK_INTERVAL,
+ SCROLL_LINES,
};
-use crate::{LinuxCommon, WindowParams};
/// Used to convert evdev scancode to xkb scancode
const MIN_KEYCODE: u32 = 8;
@@ -186,6 +188,7 @@ pub struct Output {
pub(crate) struct WaylandClientState {
serial_tracker: SerialTracker,
globals: Globals,
+ gpu_context: BladeContext,
wl_seat: wl_seat::WlSeat, // TODO: Multi seat support
wl_pointer: Option<wl_pointer::WlPointer>,
wl_keyboard: Option<wl_keyboard::WlKeyboard>,
@@ -459,6 +462,8 @@ impl WaylandClient {
})
.unwrap();
+ let gpu_context = BladeContext::new().expect("Unable to init GPU context");
+
let seat = seat.unwrap();
let globals = Globals::new(
globals,
@@ -512,6 +517,7 @@ impl WaylandClient {
let mut state = Rc::new(RefCell::new(WaylandClientState {
serial_tracker: SerialTracker::new(),
globals,
+ gpu_context,
wl_seat: seat,
wl_pointer: None,
wl_keyboard: None,
@@ -627,6 +633,7 @@ impl LinuxClient for WaylandClient {
let (window, surface_id) = WaylandWindow::new(
handle,
state.globals.clone(),
+ &state.gpu_context,
WaylandClientStatePtr(Rc::downgrade(&self.0)),
params,
state.common.appearance,
@@ -1,8 +1,10 @@
-use std::cell::{Ref, RefCell, RefMut};
-use std::ffi::c_void;
-use std::ptr::NonNull;
-use std::rc::Rc;
-use std::sync::Arc;
+use std::{
+ cell::{Ref, RefCell, RefMut},
+ ffi::c_void,
+ ptr::NonNull,
+ rc::Rc,
+ sync::Arc,
+};
use blade_graphics as gpu;
use collections::HashMap;
@@ -19,10 +21,11 @@ use wayland_protocols::xdg::shell::client::xdg_surface;
use wayland_protocols::xdg::shell::client::xdg_toplevel::{self};
use wayland_protocols_plasma::blur::client::org_kde_kwin_blur;
-use crate::platform::blade::{BladeRenderer, BladeSurfaceConfig};
-use crate::platform::linux::wayland::display::WaylandDisplay;
-use crate::platform::linux::wayland::serial::SerialKind;
-use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow};
+use crate::platform::{
+ blade::{BladeContext, BladeRenderer, BladeSurfaceConfig},
+ linux::wayland::{display::WaylandDisplay, serial::SerialKind},
+ PlatformAtlas, PlatformInputHandler, PlatformWindow,
+};
use crate::scene::Scene;
use crate::{
px, size, AnyWindowHandle, Bounds, Decorations, Globals, GpuSpecs, Modifiers, Output, Pixels,
@@ -123,37 +126,28 @@ impl WaylandWindowState {
viewport: Option<wp_viewport::WpViewport>,
client: WaylandClientStatePtr,
globals: Globals,
+ gpu_context: &BladeContext,
options: WindowParams,
) -> anyhow::Result<Self> {
- let raw = RawWindow {
- window: surface.id().as_ptr().cast::<c_void>(),
- display: surface
- .backend()
- .upgrade()
- .unwrap()
- .display_ptr()
- .cast::<c_void>(),
- };
- let gpu = Arc::new(
- unsafe {
- gpu::Context::init_windowed(
- &raw,
- gpu::ContextDesc {
- validation: false,
- capture: false,
- overlay: false,
- },
- )
- }
- .map_err(|e| anyhow::anyhow!("{:?}", e))?,
- );
- let config = BladeSurfaceConfig {
- size: gpu::Extent {
- width: options.bounds.size.width.0 as u32,
- height: options.bounds.size.height.0 as u32,
- depth: 1,
- },
- transparent: true,
+ let renderer = {
+ let raw_window = RawWindow {
+ window: surface.id().as_ptr().cast::<c_void>(),
+ display: surface
+ .backend()
+ .upgrade()
+ .unwrap()
+ .display_ptr()
+ .cast::<c_void>(),
+ };
+ let config = BladeSurfaceConfig {
+ size: gpu::Extent {
+ width: options.bounds.size.width.0 as u32,
+ height: options.bounds.size.height.0 as u32,
+ depth: 1,
+ },
+ transparent: true,
+ };
+ BladeRenderer::new(gpu_context, &raw_window, config)?
};
Ok(Self {
@@ -168,7 +162,7 @@ impl WaylandWindowState {
globals,
outputs: HashMap::default(),
display: None,
- renderer: BladeRenderer::new(gpu, config),
+ renderer,
bounds: options.bounds,
scale: 1.0,
input_handler: None,
@@ -266,6 +260,7 @@ impl WaylandWindow {
pub fn new(
handle: AnyWindowHandle,
globals: Globals,
+ gpu_context: &BladeContext,
client: WaylandClientStatePtr,
params: WindowParams,
appearance: WindowAppearance,
@@ -308,6 +303,7 @@ impl WaylandWindow {
viewport,
client,
globals,
+ gpu_context,
params,
)?)),
callbacks: Rc::new(RefCell::new(Callbacks::default())),
@@ -1,13 +1,17 @@
use core::str;
-use std::cell::RefCell;
-use std::collections::{BTreeMap, HashSet};
-use std::ops::Deref;
-use std::path::PathBuf;
-use std::rc::{Rc, Weak};
-use std::time::{Duration, Instant};
+use std::{
+ cell::RefCell,
+ collections::{BTreeMap, HashSet},
+ ops::Deref,
+ path::PathBuf,
+ rc::{Rc, Weak},
+ time::{Duration, Instant},
+};
-use calloop::generic::{FdWrapper, Generic};
-use calloop::{EventLoop, LoopHandle, RegistrationToken};
+use calloop::{
+ generic::{FdWrapper, Generic},
+ EventLoop, LoopHandle, RegistrationToken,
+};
use anyhow::Context as _;
use collections::HashMap;
@@ -15,44 +19,49 @@ use http_client::Url;
use smallvec::SmallVec;
use util::ResultExt;
-use x11rb::connection::{Connection, RequestConnection};
-use x11rb::cursor;
-use x11rb::errors::ConnectionError;
-use x11rb::protocol::randr::ConnectionExt as _;
-use x11rb::protocol::xinput::ConnectionExt;
-use x11rb::protocol::xkb::ConnectionExt as _;
-use x11rb::protocol::xproto::{
- AtomEnum, ChangeWindowAttributesAux, ClientMessageData, ClientMessageEvent, ConnectionExt as _,
- EventMask, KeyPressEvent,
+use x11rb::{
+ connection::{Connection, RequestConnection},
+ cursor,
+ errors::ConnectionError,
+ protocol::randr::ConnectionExt as _,
+ protocol::xinput::ConnectionExt,
+ protocol::xkb::ConnectionExt as _,
+ protocol::xproto::{
+ AtomEnum, ChangeWindowAttributesAux, ClientMessageData, ClientMessageEvent,
+ ConnectionExt as _, EventMask, KeyPressEvent,
+ },
+ protocol::{randr, render, xinput, xkb, xproto, Event},
+ resource_manager::Database,
+ wrapper::ConnectionExt as _,
+ xcb_ffi::XCBConnection,
};
-use x11rb::protocol::{randr, render, xinput, xkb, xproto, Event};
-use x11rb::resource_manager::Database;
-use x11rb::wrapper::ConnectionExt as _;
-use x11rb::xcb_ffi::XCBConnection;
-use xim::{x11rb::X11rbClient, Client};
-use xim::{AttributeName, InputStyle};
+use xim::{x11rb::X11rbClient, AttributeName, Client, InputStyle};
use xkbc::x11::ffi::{XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION};
use xkbcommon::xkb::{self as xkbc, LayoutIndex, ModMask};
-use crate::platform::linux::LinuxClient;
-use crate::platform::{LinuxCommon, PlatformWindow};
-use crate::{
- modifiers_from_xinput_info, point, px, AnyWindowHandle, Bounds, ClipboardItem, CursorStyle,
- DisplayId, FileDropEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, Pixels,
- Platform, PlatformDisplay, PlatformInput, Point, RequestFrameOptions, ScaledPixels,
- ScrollDelta, Size, TouchPhase, WindowParams, X11Window,
-};
-
use super::{
button_or_scroll_from_event_detail, get_valuator_axis_index, modifiers_from_state,
pressed_button_from_mask, ButtonOrScroll, ScrollDirection,
};
use super::{X11Display, X11WindowStatePtr, XcbAtoms};
use super::{XimCallbackEvent, XimHandler};
-use crate::platform::linux::platform::{DOUBLE_CLICK_INTERVAL, SCROLL_LINES};
-use crate::platform::linux::xdg_desktop_portal::{Event as XDPEvent, XDPEventSource};
-use crate::platform::linux::{
- get_xkb_compose_state, is_within_click_distance, open_uri_internal, reveal_path_internal,
+
+use crate::platform::{
+ blade::BladeContext,
+ linux::{
+ get_xkb_compose_state, is_within_click_distance, open_uri_internal,
+ platform::{DOUBLE_CLICK_INTERVAL, SCROLL_LINES},
+ reveal_path_internal,
+ xdg_desktop_portal::{Event as XDPEvent, XDPEventSource},
+ LinuxClient,
+ },
+ LinuxCommon, PlatformWindow,
+};
+use crate::{
+ modifiers_from_xinput_info, point, px, AnyWindowHandle, Bounds, ClipboardItem, CursorStyle,
+ DisplayId, FileDropEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, Pixels,
+ Platform, PlatformDisplay, PlatformInput, Point, RequestFrameOptions, ScaledPixels,
+ ScrollDelta, Size, TouchPhase, WindowParams, X11Window,
};
/// Value for DeviceId parameters which selects all devices.
@@ -158,6 +167,8 @@ pub struct X11ClientState {
pub(crate) last_location: Point<Pixels>,
pub(crate) current_count: usize,
+ gpu_context: BladeContext,
+
pub(crate) scale_factor: f32,
xkb_context: xkbc::Context,
@@ -360,6 +371,8 @@ impl X11Client {
let compose_state = get_xkb_compose_state(&xkb_context);
let resource_database = x11rb::resource_manager::new_from_default(&xcb_connection).unwrap();
+ let gpu_context = BladeContext::new().expect("Unable to init GPU context");
+
let scale_factor = resource_database
.get_value("Xft.dpi", "Xft.dpi")
.ok()
@@ -428,6 +441,7 @@ impl X11Client {
last_mouse_button: None,
last_location: Point::new(px(0.0), px(0.0)),
current_count: 0,
+ gpu_context,
scale_factor,
xkb_context,
@@ -1299,6 +1313,7 @@ impl LinuxClient for X11Client {
handle,
X11ClientStatePtr(Rc::downgrade(&self.0)),
state.common.foreground_executor.clone(),
+ &state.gpu_context,
params,
&state.xcb_connection,
state.client_side_decorations_supported,
@@ -1,7 +1,7 @@
use anyhow::{anyhow, Context};
+use crate::platform::blade::{BladeContext, BladeRenderer, BladeSurfaceConfig};
use crate::{
- platform::blade::{BladeRenderer, BladeSurfaceConfig},
px, size, AnyWindowHandle, Bounds, Decorations, DevicePixels, ForegroundExecutor, GpuSpecs,
Modifiers, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,
PlatformWindow, Point, PromptLevel, RequestFrameOptions, ResizeEdge, ScaledPixels, Scene, Size,
@@ -247,7 +247,6 @@ pub struct X11WindowState {
x_root_window: xproto::Window,
pub(crate) counter_id: sync::Counter,
pub(crate) last_sync_counter: Option<sync::Int64>,
- _raw: RawWindow,
bounds: Bounds<Pixels>,
scale_factor: f32,
renderer: BladeRenderer,
@@ -358,6 +357,7 @@ impl X11WindowState {
handle: AnyWindowHandle,
client: X11ClientStatePtr,
executor: ForegroundExecutor,
+ gpu_context: &BladeContext,
params: WindowParams,
xcb: &Rc<XCBConnection>,
client_side_decorations_supported: bool,
@@ -555,50 +555,39 @@ impl X11WindowState {
xcb.flush().with_context(|| "X11 Flush failed.")?;
- let raw = RawWindow {
- connection: as_raw_xcb_connection::AsRawXcbConnection::as_raw_xcb_connection(xcb)
- as *mut _,
- screen_id: x_screen_index,
- window_id: x_window,
- visual_id: visual.id,
+ let renderer = {
+ let raw_window = RawWindow {
+ connection: as_raw_xcb_connection::AsRawXcbConnection::as_raw_xcb_connection(
+ xcb,
+ ) as *mut _,
+ screen_id: x_screen_index,
+ window_id: x_window,
+ visual_id: visual.id,
+ };
+ let config = BladeSurfaceConfig {
+ // Note: this has to be done after the GPU init, or otherwise
+ // the sizes are immediately invalidated.
+ size: query_render_extent(xcb, x_window)?,
+ // We set it to transparent by default, even if we have client-side
+ // decorations, since those seem to work on X11 even without `true` here.
+ // If the window appearance changes, then the renderer will get updated
+ // too
+ transparent: false,
+ };
+ BladeRenderer::new(gpu_context, &raw_window, config)?
};
- let gpu = Arc::new(
- unsafe {
- gpu::Context::init_windowed(
- &raw,
- gpu::ContextDesc {
- validation: false,
- capture: false,
- overlay: false,
- },
- )
- }
- .map_err(|e| anyhow!("{:?}", e))?,
- );
- let config = BladeSurfaceConfig {
- // Note: this has to be done after the GPU init, or otherwise
- // the sizes are immediately invalidated.
- size: query_render_extent(xcb, x_window)?,
- // We set it to transparent by default, even if we have client-side
- // decorations, since those seem to work on X11 even without `true` here.
- // If the window appearance changes, then the renderer will get updated
- // too
- transparent: false,
- };
check_reply(|| "X11 MapWindow failed.", xcb.map_window(x_window))?;
-
let display = Rc::new(X11Display::new(xcb, scale_factor, x_screen_index)?);
Ok(Self {
client,
executor,
display,
- _raw: raw,
x_root_window: visual_set.root,
bounds: bounds.to_pixels(scale_factor),
scale_factor,
- renderer: BladeRenderer::new(gpu, config),
+ renderer,
atoms: *atoms,
input_handler: None,
active: false,
@@ -716,6 +705,7 @@ impl X11Window {
handle: AnyWindowHandle,
client: X11ClientStatePtr,
executor: ForegroundExecutor,
+ gpu_context: &BladeContext,
params: WindowParams,
xcb: &Rc<XCBConnection>,
client_side_decorations_supported: bool,
@@ -730,6 +720,7 @@ impl X11Window {
handle,
client,
executor,
+ gpu_context,
params,
xcb,
client_side_decorations_supported,
@@ -28,11 +28,12 @@ use windows::{
UI::ViewManagement::UISettings,
};
-use crate::*;
+use crate::{platform::blade::BladeContext, *};
pub(crate) struct WindowsPlatform {
state: RefCell<WindowsPlatformState>,
raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
+ gpu_context: BladeContext,
// The below members will never change throughout the entire lifecycle of the app.
icon: HICON,
main_receiver: flume::Receiver<Runnable>,
@@ -94,12 +95,14 @@ impl WindowsPlatform {
let icon = load_icon().unwrap_or_default();
let state = RefCell::new(WindowsPlatformState::new());
let raw_window_handles = RwLock::new(SmallVec::new());
+ let gpu_context = BladeContext::new().expect("Unable to init GPU context");
let windows_version = WindowsVersion::new().expect("Error retrieve windows version");
let validation_number = rand::random::<usize>();
Self {
state,
raw_window_handles,
+ gpu_context,
icon,
main_receiver,
dispatch_event,
@@ -344,7 +347,12 @@ impl Platform for WindowsPlatform {
handle: AnyWindowHandle,
options: WindowParams,
) -> Result<Box<dyn PlatformWindow>> {
- let window = WindowsWindow::new(handle, options, self.generate_creation_info())?;
+ let window = WindowsWindow::new(
+ handle,
+ options,
+ self.generate_creation_info(),
+ &self.gpu_context,
+ )?;
let handle = window.get_raw_handle();
self.raw_window_handles.write().push(handle);
@@ -27,7 +27,7 @@ use windows::{
},
};
-use crate::platform::blade::BladeRenderer;
+use crate::platform::blade::{BladeContext, BladeRenderer};
use crate::*;
pub(crate) struct WindowsWindow(pub Rc<WindowsWindowStatePtr>);
@@ -78,6 +78,7 @@ impl WindowsWindowState {
cs: &CREATESTRUCTW,
current_cursor: HCURSOR,
display: WindowsDisplay,
+ gpu_context: &BladeContext,
) -> Result<Self> {
let scale_factor = {
let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32;
@@ -94,7 +95,7 @@ impl WindowsWindowState {
};
let border_offset = WindowBorderOffset::default();
let is_minimized = None;
- let renderer = windows_renderer::windows_renderer(hwnd, transparent)?;
+ let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?;
let callbacks = Callbacks::default();
let input_handler = None;
let system_key_handled = false;
@@ -227,6 +228,7 @@ impl WindowsWindowStatePtr {
cs,
context.current_cursor,
context.display,
+ context.gpu_context,
)?);
Ok(Rc::new_cyclic(|this| Self {
@@ -340,7 +342,7 @@ pub(crate) struct Callbacks {
pub(crate) appearance_changed: Option<Box<dyn FnMut()>>,
}
-struct WindowCreateContext {
+struct WindowCreateContext<'a> {
inner: Option<Result<Rc<WindowsWindowStatePtr>>>,
handle: AnyWindowHandle,
hide_title_bar: bool,
@@ -352,6 +354,7 @@ struct WindowCreateContext {
windows_version: WindowsVersion,
validation_number: usize,
main_receiver: flume::Receiver<Runnable>,
+ gpu_context: &'a BladeContext,
}
impl WindowsWindow {
@@ -359,6 +362,7 @@ impl WindowsWindow {
handle: AnyWindowHandle,
params: WindowParams,
creation_info: WindowCreationInfo,
+ gpu_context: &BladeContext,
) -> Result<Self> {
let WindowCreationInfo {
icon,
@@ -410,6 +414,7 @@ impl WindowsWindow {
windows_version,
validation_number,
main_receiver,
+ gpu_context,
};
let lpparam = Some(&context as *const _ as *const _);
let creation_result = unsafe {
@@ -1236,38 +1241,24 @@ fn set_window_composition_attribute(hwnd: HWND, color: Option<Color>, state: u32
}
mod windows_renderer {
- use std::{num::NonZeroIsize, sync::Arc};
-
- use blade_graphics as gpu;
+ use crate::platform::blade::{BladeContext, BladeRenderer, BladeSurfaceConfig};
use raw_window_handle as rwh;
+ use std::num::NonZeroIsize;
use windows::Win32::{Foundation::HWND, UI::WindowsAndMessaging::GWLP_HINSTANCE};
- use crate::{
- get_window_long,
- platform::blade::{BladeRenderer, BladeSurfaceConfig},
- };
+ use crate::get_window_long;
- pub(super) fn windows_renderer(hwnd: HWND, transparent: bool) -> anyhow::Result<BladeRenderer> {
+ pub(super) fn init(
+ context: &BladeContext,
+ hwnd: HWND,
+ transparent: bool,
+ ) -> anyhow::Result<BladeRenderer> {
let raw = RawWindow { hwnd };
- let gpu: Arc<gpu::Context> = Arc::new(
- unsafe {
- gpu::Context::init_windowed(
- &raw,
- gpu::ContextDesc {
- validation: false,
- capture: false,
- overlay: false,
- },
- )
- }
- .map_err(|e| anyhow::anyhow!("{:?}", e))?,
- );
let config = BladeSurfaceConfig {
- size: gpu::Extent::default(),
+ size: Default::default(),
transparent,
};
-
- Ok(BladeRenderer::new(gpu, config))
+ BladeRenderer::new(context, &raw, config)
}
struct RawWindow {
@@ -19,7 +19,7 @@ anyhow.workspace = true
core-foundation.workspace = true
ctor.workspace = true
foreign-types = "0.5"
-metal = "0.29"
+metal.workspace = true
objc = "0.2"
[build-dependencies]