linux: basic window, display, and atlas
This commit is contained in:
parent
b0376aaf8f
commit
e95bf24a1f
8 changed files with 582 additions and 84 deletions
|
@ -26,7 +26,7 @@ anyhow.workspace = true
|
|||
async-task = "4.7"
|
||||
backtrace = { version = "0.3", optional = true }
|
||||
bitflags = "2.4.0"
|
||||
blade-graphics = "0.3"
|
||||
blade = { package = "blade-graphics", version = "0.3" }
|
||||
blade-macros = "0.2"
|
||||
collections = { path = "../collections" }
|
||||
ctor.workspace = true
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
mod blade_atlas;
|
||||
mod blade_belt;
|
||||
mod dispatcher;
|
||||
mod display;
|
||||
mod platform;
|
||||
mod text_system;
|
||||
mod window;
|
||||
|
||||
pub(crate) use blade_atlas::*;
|
||||
pub(crate) use dispatcher::*;
|
||||
pub(crate) use display::*;
|
||||
pub(crate) use platform::*;
|
||||
pub(crate) use text_system::*;
|
||||
pub(crate) use window::*;
|
||||
|
||||
use blade_belt::*;
|
||||
|
|
258
crates/gpui/src/platform/linux/blade_atlas.rs
Normal file
258
crates/gpui/src/platform/linux/blade_atlas.rs
Normal file
|
@ -0,0 +1,258 @@
|
|||
use super::{BladeBelt, BladeBeltDescriptor};
|
||||
use crate::{
|
||||
AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
|
||||
Point, Size,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use collections::FxHashMap;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use etagere::BucketedAtlasAllocator;
|
||||
use parking_lot::Mutex;
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
pub(crate) struct BladeAtlas(Mutex<BladeAtlasState>);
|
||||
|
||||
struct BladeAtlasState {
|
||||
gpu: Arc<blade::Context>,
|
||||
gpu_encoder: blade::CommandEncoder,
|
||||
upload_belt: BladeBelt,
|
||||
monochrome_textures: Vec<BladeAtlasTexture>,
|
||||
polychrome_textures: Vec<BladeAtlasTexture>,
|
||||
path_textures: Vec<BladeAtlasTexture>,
|
||||
tiles_by_key: FxHashMap<AtlasKey, AtlasTile>,
|
||||
}
|
||||
|
||||
impl BladeAtlas {
|
||||
pub(crate) fn new(gpu: &Arc<blade::Context>) -> Self {
|
||||
BladeAtlas(Mutex::new(BladeAtlasState {
|
||||
gpu: Arc::clone(gpu),
|
||||
gpu_encoder: gpu.create_command_encoder(blade::CommandEncoderDesc {
|
||||
name: "atlas",
|
||||
buffer_count: 3,
|
||||
}),
|
||||
upload_belt: BladeBelt::new(BladeBeltDescriptor {
|
||||
memory: blade::Memory::Upload,
|
||||
min_chunk_size: 0x10000,
|
||||
}),
|
||||
monochrome_textures: Default::default(),
|
||||
polychrome_textures: Default::default(),
|
||||
path_textures: Default::default(),
|
||||
tiles_by_key: Default::default(),
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn clear_textures(&self, texture_kind: AtlasTextureKind) {
|
||||
let mut lock = self.0.lock();
|
||||
let textures = match texture_kind {
|
||||
AtlasTextureKind::Monochrome => &mut lock.monochrome_textures,
|
||||
AtlasTextureKind::Polychrome => &mut lock.polychrome_textures,
|
||||
AtlasTextureKind::Path => &mut lock.path_textures,
|
||||
};
|
||||
for texture in textures {
|
||||
texture.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_frame(&self) {
|
||||
let mut lock = self.0.lock();
|
||||
lock.gpu_encoder.start();
|
||||
}
|
||||
|
||||
pub fn finish_frame(&self) -> blade::SyncPoint {
|
||||
let mut lock = self.0.lock();
|
||||
let gpu = lock.gpu.clone();
|
||||
let sync_point = gpu.submit(&mut lock.gpu_encoder);
|
||||
lock.upload_belt.flush(&sync_point);
|
||||
sync_point
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformAtlas for BladeAtlas {
|
||||
fn get_or_insert_with<'a>(
|
||||
&self,
|
||||
key: &AtlasKey,
|
||||
build: &mut dyn FnMut() -> Result<(Size<DevicePixels>, Cow<'a, [u8]>)>,
|
||||
) -> Result<AtlasTile> {
|
||||
let mut lock = self.0.lock();
|
||||
if let Some(tile) = lock.tiles_by_key.get(key) {
|
||||
Ok(tile.clone())
|
||||
} else {
|
||||
let (size, bytes) = build()?;
|
||||
let tile = lock.allocate(size, key.texture_kind());
|
||||
lock.upload_texture(tile.texture_id, tile.bounds, &bytes);
|
||||
lock.tiles_by_key.insert(key.clone(), tile.clone());
|
||||
Ok(tile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BladeAtlasState {
|
||||
fn allocate(&mut self, size: Size<DevicePixels>, texture_kind: AtlasTextureKind) -> AtlasTile {
|
||||
let textures = match texture_kind {
|
||||
AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
|
||||
AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
|
||||
AtlasTextureKind::Path => &mut self.path_textures,
|
||||
};
|
||||
textures
|
||||
.iter_mut()
|
||||
.rev()
|
||||
.find_map(|texture| texture.allocate(size))
|
||||
.unwrap_or_else(|| {
|
||||
let texture = self.push_texture(size, texture_kind);
|
||||
texture.allocate(size).unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
fn push_texture(
|
||||
&mut self,
|
||||
min_size: Size<DevicePixels>,
|
||||
kind: AtlasTextureKind,
|
||||
) -> &mut BladeAtlasTexture {
|
||||
const DEFAULT_ATLAS_SIZE: Size<DevicePixels> = Size {
|
||||
width: DevicePixels(1024),
|
||||
height: DevicePixels(1024),
|
||||
};
|
||||
|
||||
let size = min_size.max(&DEFAULT_ATLAS_SIZE);
|
||||
let format;
|
||||
let usage;
|
||||
match kind {
|
||||
AtlasTextureKind::Monochrome => {
|
||||
format = blade::TextureFormat::R8Unorm;
|
||||
usage = blade::TextureUsage::COPY | blade::TextureUsage::RESOURCE;
|
||||
}
|
||||
AtlasTextureKind::Polychrome => {
|
||||
format = blade::TextureFormat::Bgra8Unorm;
|
||||
usage = blade::TextureUsage::COPY | blade::TextureUsage::RESOURCE;
|
||||
}
|
||||
AtlasTextureKind::Path => {
|
||||
format = blade::TextureFormat::R16Float;
|
||||
usage = blade::TextureUsage::COPY
|
||||
| blade::TextureUsage::RESOURCE
|
||||
| blade::TextureUsage::TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
let raw = self.gpu.create_texture(blade::TextureDesc {
|
||||
name: "",
|
||||
format,
|
||||
size: blade::Extent {
|
||||
width: size.width.into(),
|
||||
height: size.height.into(),
|
||||
depth: 1,
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
dimension: blade::TextureDimension::D2,
|
||||
usage,
|
||||
});
|
||||
|
||||
let textures = match kind {
|
||||
AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
|
||||
AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
|
||||
AtlasTextureKind::Path => &mut self.path_textures,
|
||||
};
|
||||
let atlas_texture = BladeAtlasTexture {
|
||||
id: AtlasTextureId {
|
||||
index: textures.len() as u32,
|
||||
kind,
|
||||
},
|
||||
allocator: etagere::BucketedAtlasAllocator::new(size.into()),
|
||||
format,
|
||||
raw,
|
||||
};
|
||||
textures.push(atlas_texture);
|
||||
textures.last_mut().unwrap()
|
||||
}
|
||||
|
||||
fn upload_texture(&mut self, id: AtlasTextureId, bounds: Bounds<DevicePixels>, bytes: &[u8]) {
|
||||
let textures = match id.kind {
|
||||
crate::AtlasTextureKind::Monochrome => &self.monochrome_textures,
|
||||
crate::AtlasTextureKind::Polychrome => &self.polychrome_textures,
|
||||
crate::AtlasTextureKind::Path => &self.path_textures,
|
||||
};
|
||||
let texture = &textures[id.index as usize];
|
||||
|
||||
let src_data = self.upload_belt.alloc_data(bytes, &self.gpu);
|
||||
|
||||
let mut transfers = self.gpu_encoder.transfer();
|
||||
transfers.copy_buffer_to_texture(
|
||||
src_data,
|
||||
bounds.size.width.to_bytes(texture.bytes_per_pixel()),
|
||||
blade::TexturePiece {
|
||||
texture: texture.raw,
|
||||
mip_level: 0,
|
||||
array_layer: 0,
|
||||
origin: [bounds.origin.x.into(), bounds.origin.y.into(), 0],
|
||||
},
|
||||
blade::Extent {
|
||||
width: bounds.size.width.into(),
|
||||
height: bounds.size.height.into(),
|
||||
depth: 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct BladeAtlasTexture {
|
||||
id: AtlasTextureId,
|
||||
allocator: BucketedAtlasAllocator,
|
||||
raw: blade::Texture,
|
||||
format: blade::TextureFormat,
|
||||
}
|
||||
|
||||
impl BladeAtlasTexture {
|
||||
fn clear(&mut self) {
|
||||
self.allocator.clear();
|
||||
}
|
||||
|
||||
fn allocate(&mut self, size: Size<DevicePixels>) -> Option<AtlasTile> {
|
||||
let allocation = self.allocator.allocate(size.into())?;
|
||||
let tile = AtlasTile {
|
||||
texture_id: self.id,
|
||||
tile_id: allocation.id.into(),
|
||||
bounds: Bounds {
|
||||
origin: allocation.rectangle.min.into(),
|
||||
size,
|
||||
},
|
||||
};
|
||||
Some(tile)
|
||||
}
|
||||
|
||||
fn bytes_per_pixel(&self) -> u8 {
|
||||
self.format.block_info().size
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Size<DevicePixels>> for etagere::Size {
|
||||
fn from(size: Size<DevicePixels>) -> Self {
|
||||
etagere::Size::new(size.width.into(), size.height.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<etagere::Point> for Point<DevicePixels> {
|
||||
fn from(value: etagere::Point) -> Self {
|
||||
Point {
|
||||
x: DevicePixels::from(value.x),
|
||||
y: DevicePixels::from(value.y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<etagere::Size> for Size<DevicePixels> {
|
||||
fn from(size: etagere::Size) -> Self {
|
||||
Size {
|
||||
width: DevicePixels::from(size.width),
|
||||
height: DevicePixels::from(size.height),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<etagere::Rectangle> for Bounds<DevicePixels> {
|
||||
fn from(rectangle: etagere::Rectangle) -> Self {
|
||||
Bounds {
|
||||
origin: rectangle.min.into(),
|
||||
size: rectangle.size().into(),
|
||||
}
|
||||
}
|
||||
}
|
84
crates/gpui/src/platform/linux/blade_belt.rs
Normal file
84
crates/gpui/src/platform/linux/blade_belt.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
struct ReusableBuffer {
|
||||
raw: blade::Buffer,
|
||||
size: u64,
|
||||
}
|
||||
|
||||
pub struct BladeBeltDescriptor {
|
||||
pub memory: blade::Memory,
|
||||
pub min_chunk_size: u64,
|
||||
}
|
||||
|
||||
/// A belt of buffers, used by the BladeAtlas to cheaply
|
||||
/// find staging space for uploads.
|
||||
pub struct BladeBelt {
|
||||
desc: BladeBeltDescriptor,
|
||||
buffers: Vec<(ReusableBuffer, blade::SyncPoint)>,
|
||||
active: Vec<(ReusableBuffer, u64)>,
|
||||
}
|
||||
|
||||
impl BladeBelt {
|
||||
pub fn new(desc: BladeBeltDescriptor) -> Self {
|
||||
Self {
|
||||
desc,
|
||||
buffers: Vec::new(),
|
||||
active: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy(&mut self, gpu: &blade::Context) {
|
||||
for (buffer, _) in self.buffers.drain(..) {
|
||||
gpu.destroy_buffer(buffer.raw);
|
||||
}
|
||||
for (buffer, _) in self.active.drain(..) {
|
||||
gpu.destroy_buffer(buffer.raw);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc(&mut self, size: u64, gpu: &blade::Context) -> blade::BufferPiece {
|
||||
for &mut (ref rb, ref mut offset) in self.active.iter_mut() {
|
||||
if *offset + size <= rb.size {
|
||||
let piece = rb.raw.at(*offset);
|
||||
*offset += size;
|
||||
return piece;
|
||||
}
|
||||
}
|
||||
|
||||
let index_maybe = self
|
||||
.buffers
|
||||
.iter()
|
||||
.position(|&(ref rb, ref sp)| size <= rb.size && gpu.wait_for(sp, 0));
|
||||
if let Some(index) = index_maybe {
|
||||
let (rb, _) = self.buffers.remove(index);
|
||||
let piece = rb.raw.into();
|
||||
self.active.push((rb, size));
|
||||
return piece;
|
||||
}
|
||||
|
||||
let chunk_index = self.buffers.len() + self.active.len();
|
||||
let chunk_size = size.max(self.desc.min_chunk_size);
|
||||
let chunk = gpu.create_buffer(blade::BufferDesc {
|
||||
name: &format!("chunk-{}", chunk_index),
|
||||
size: chunk_size,
|
||||
memory: self.desc.memory,
|
||||
});
|
||||
let rb = ReusableBuffer {
|
||||
raw: chunk,
|
||||
size: chunk_size,
|
||||
};
|
||||
self.active.push((rb, size));
|
||||
chunk.into()
|
||||
}
|
||||
|
||||
pub fn alloc_data(&mut self, data: &[u8], gpu: &blade::Context) -> blade::BufferPiece {
|
||||
let bp = self.alloc(data.len() as u64, gpu);
|
||||
unsafe {
|
||||
std::ptr::copy_nonoverlapping(data.as_ptr(), bp.data(), data.len());
|
||||
}
|
||||
bp
|
||||
}
|
||||
|
||||
pub fn flush(&mut self, sp: &blade::SyncPoint) {
|
||||
self.buffers
|
||||
.extend(self.active.drain(..).map(|(rb, _)| (rb, sp.clone())));
|
||||
}
|
||||
}
|
23
crates/gpui/src/platform/linux/display.rs
Normal file
23
crates/gpui/src/platform/linux/display.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use crate::{point, size, Bounds, DisplayId, GlobalPixels, PlatformDisplay};
|
||||
use anyhow::Result;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct LinuxDisplay;
|
||||
|
||||
impl PlatformDisplay for LinuxDisplay {
|
||||
fn id(&self) -> DisplayId {
|
||||
DisplayId(0)
|
||||
}
|
||||
|
||||
fn uuid(&self) -> Result<Uuid> {
|
||||
Ok(Uuid::from_bytes([0; 16]))
|
||||
}
|
||||
|
||||
fn bounds(&self) -> Bounds<GlobalPixels> {
|
||||
Bounds {
|
||||
origin: point(GlobalPixels(0.0), GlobalPixels(0.0)),
|
||||
size: size(GlobalPixels(100.0), GlobalPixels(100.0)),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
use crate::{
|
||||
Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
|
||||
ForegroundExecutor, Keymap, LinuxDispatcher, LinuxTextSystem, Menu, PathPromptOptions,
|
||||
Platform, PlatformDisplay, PlatformInput, PlatformTextSystem, PlatformWindow, Result,
|
||||
SemanticVersion, Task, WindowOptions,
|
||||
ForegroundExecutor, Keymap, LinuxDispatcher, LinuxDisplay, LinuxTextSystem, LinuxWindow, Menu,
|
||||
PathPromptOptions, Platform, PlatformDisplay, PlatformInput, PlatformTextSystem,
|
||||
PlatformWindow, Result, SemanticVersion, Task, WindowOptions,
|
||||
};
|
||||
|
||||
use futures::channel::oneshot;
|
||||
|
@ -21,6 +21,7 @@ use time::UtcOffset;
|
|||
pub(crate) struct LinuxPlatform(Mutex<LinuxPlatformState>);
|
||||
|
||||
pub(crate) struct LinuxPlatformState {
|
||||
gpu: Arc<blade::Context>,
|
||||
background_executor: BackgroundExecutor,
|
||||
foreground_executor: ForegroundExecutor,
|
||||
text_system: Arc<LinuxTextSystem>,
|
||||
|
@ -35,7 +36,17 @@ impl Default for LinuxPlatform {
|
|||
impl LinuxPlatform {
|
||||
pub(crate) fn new() -> Self {
|
||||
let dispatcher = Arc::new(LinuxDispatcher::new());
|
||||
let gpu = Arc::new(
|
||||
unsafe {
|
||||
blade::Context::init(blade::ContextDesc {
|
||||
validation: true, //FIXME
|
||||
capture: false,
|
||||
})
|
||||
}
|
||||
.unwrap(),
|
||||
);
|
||||
Self(Mutex::new(LinuxPlatformState {
|
||||
gpu,
|
||||
background_executor: BackgroundExecutor::new(dispatcher.clone()),
|
||||
foreground_executor: ForegroundExecutor::new(dispatcher),
|
||||
text_system: Arc::new(LinuxTextSystem::new()),
|
||||
|
@ -57,43 +68,31 @@ impl Platform for LinuxPlatform {
|
|||
}
|
||||
|
||||
fn run(&self, on_finish_launching: Box<dyn FnOnce()>) {
|
||||
unimplemented!()
|
||||
on_finish_launching()
|
||||
}
|
||||
|
||||
fn quit(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn quit(&self) {}
|
||||
|
||||
fn restart(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn restart(&self) {}
|
||||
|
||||
fn activate(&self, ignoring_other_apps: bool) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn activate(&self, ignoring_other_apps: bool) {}
|
||||
|
||||
fn hide(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn hide(&self) {}
|
||||
|
||||
fn hide_other_apps(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn hide_other_apps(&self) {}
|
||||
|
||||
fn unhide_other_apps(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn unhide_other_apps(&self) {}
|
||||
|
||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
|
||||
unimplemented!()
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
|
||||
unimplemented!()
|
||||
None
|
||||
}
|
||||
|
||||
fn active_window(&self) -> Option<AnyWindowHandle> {
|
||||
unimplemented!()
|
||||
None
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
|
@ -101,7 +100,13 @@ impl Platform for LinuxPlatform {
|
|||
handle: AnyWindowHandle,
|
||||
options: WindowOptions,
|
||||
) -> Box<dyn PlatformWindow> {
|
||||
unimplemented!()
|
||||
let lock = self.0.lock();
|
||||
Box::new(LinuxWindow::new(
|
||||
options,
|
||||
handle,
|
||||
Rc::new(LinuxDisplay),
|
||||
&lock.gpu,
|
||||
))
|
||||
}
|
||||
|
||||
fn set_display_link_output_callback(
|
||||
|
@ -112,21 +117,13 @@ impl Platform for LinuxPlatform {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn start_display_link(&self, display_id: DisplayId) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn start_display_link(&self, display_id: DisplayId) {}
|
||||
|
||||
fn stop_display_link(&self, display_id: DisplayId) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn stop_display_link(&self, display_id: DisplayId) {}
|
||||
|
||||
fn open_url(&self, url: &str) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn open_url(&self, url: &str) {}
|
||||
|
||||
fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {}
|
||||
|
||||
fn prompt_for_paths(
|
||||
&self,
|
||||
|
@ -139,88 +136,72 @@ impl Platform for LinuxPlatform {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
fn reveal_path(&self, path: &Path) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn reveal_path(&self, path: &Path) {}
|
||||
|
||||
fn on_become_active(&self, callback: Box<dyn FnMut()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_become_active(&self, callback: Box<dyn FnMut()>) {}
|
||||
|
||||
fn on_resign_active(&self, callback: Box<dyn FnMut()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_resign_active(&self, callback: Box<dyn FnMut()>) {}
|
||||
|
||||
fn on_quit(&self, callback: Box<dyn FnMut()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_quit(&self, callback: Box<dyn FnMut()>) {}
|
||||
|
||||
fn on_reopen(&self, callback: Box<dyn FnMut()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_reopen(&self, callback: Box<dyn FnMut()>) {}
|
||||
|
||||
fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_event(&self, callback: Box<dyn FnMut(PlatformInput) -> bool>) {}
|
||||
|
||||
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>) {}
|
||||
|
||||
fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>) {}
|
||||
|
||||
fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {}
|
||||
|
||||
fn os_name(&self) -> &'static str {
|
||||
"Linux"
|
||||
}
|
||||
|
||||
fn double_click_interval(&self) -> Duration {
|
||||
unimplemented!()
|
||||
Duration::default()
|
||||
}
|
||||
|
||||
fn os_version(&self) -> Result<SemanticVersion> {
|
||||
unimplemented!()
|
||||
Ok(SemanticVersion {
|
||||
major: 1,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn app_version(&self) -> Result<SemanticVersion> {
|
||||
unimplemented!()
|
||||
Ok(SemanticVersion {
|
||||
major: 1,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn app_path(&self) -> Result<PathBuf> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn set_menus(&self, menus: Vec<Menu>, keymap: &Keymap) {}
|
||||
|
||||
fn local_timezone(&self) -> UtcOffset {
|
||||
unimplemented!()
|
||||
UtcOffset::UTC
|
||||
}
|
||||
|
||||
fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_cursor_style(&self, style: CursorStyle) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn set_cursor_style(&self, style: CursorStyle) {}
|
||||
|
||||
fn should_auto_hide_scrollbars(&self) -> bool {
|
||||
unimplemented!()
|
||||
false
|
||||
}
|
||||
|
||||
fn write_to_clipboard(&self, item: ClipboardItem) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn write_to_clipboard(&self, item: ClipboardItem) {}
|
||||
|
||||
fn read_from_clipboard(&self) -> Option<ClipboardItem> {
|
||||
unimplemented!()
|
||||
None
|
||||
}
|
||||
|
||||
fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task<Result<()>> {
|
||||
|
|
|
@ -55,13 +55,13 @@ impl Default for LinuxTextSystem {
|
|||
#[allow(unused)]
|
||||
impl PlatformTextSystem for LinuxTextSystem {
|
||||
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> Result<()> {
|
||||
unimplemented!()
|
||||
Ok(()) //TODO
|
||||
}
|
||||
fn all_font_names(&self) -> Vec<String> {
|
||||
unimplemented!()
|
||||
Vec::new()
|
||||
}
|
||||
fn all_font_families(&self) -> Vec<String> {
|
||||
unimplemented!()
|
||||
Vec::new()
|
||||
}
|
||||
fn font_id(&self, descriptor: &Font) -> Result<FontId> {
|
||||
unimplemented!()
|
||||
|
|
143
crates/gpui/src/platform/linux/window.rs
Normal file
143
crates/gpui/src/platform/linux/window.rs
Normal file
|
@ -0,0 +1,143 @@
|
|||
use crate::{
|
||||
px, AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, BladeAtlas, Bounds, KeyDownEvent,
|
||||
Keystroke, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler,
|
||||
PlatformWindow, Point, Size, TileId, WindowAppearance, WindowBounds, WindowOptions,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
rc::{Rc, Weak},
|
||||
sync::{self, Arc},
|
||||
};
|
||||
|
||||
pub(crate) struct LinuxWindowState {
|
||||
display: Rc<dyn crate::PlatformDisplay>,
|
||||
sprite_atlas: Arc<BladeAtlas>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct LinuxWindow(pub(crate) Arc<Mutex<LinuxWindowState>>);
|
||||
|
||||
impl LinuxWindow {
|
||||
pub fn new(
|
||||
options: WindowOptions,
|
||||
handle: AnyWindowHandle,
|
||||
display: Rc<dyn PlatformDisplay>,
|
||||
gpu: &Arc<blade::Context>,
|
||||
) -> Self {
|
||||
Self(Arc::new(Mutex::new(LinuxWindowState {
|
||||
display,
|
||||
sprite_atlas: Arc::new(BladeAtlas::new(gpu)),
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformWindow for LinuxWindow {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
fn titlebar_height(&self) -> Pixels {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn appearance(&self) -> WindowAppearance {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn display(&self) -> Rc<dyn crate::PlatformDisplay> {
|
||||
Rc::clone(&self.0.lock().display)
|
||||
}
|
||||
|
||||
fn mouse_position(&self) -> Point<Pixels> {
|
||||
Point::default()
|
||||
}
|
||||
|
||||
fn modifiers(&self) -> crate::Modifiers {
|
||||
crate::Modifiers::default()
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {}
|
||||
|
||||
fn take_input_handler(&mut self) -> Option<PlatformInputHandler> {
|
||||
None
|
||||
}
|
||||
|
||||
fn prompt(
|
||||
&self,
|
||||
_level: crate::PromptLevel,
|
||||
_msg: &str,
|
||||
_detail: Option<&str>,
|
||||
_answers: &[&str],
|
||||
) -> futures::channel::oneshot::Receiver<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn activate(&self) {}
|
||||
|
||||
fn set_title(&mut self, title: &str) {}
|
||||
|
||||
fn set_edited(&mut self, edited: bool) {}
|
||||
|
||||
fn show_character_palette(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn minimize(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn zoom(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn toggle_full_screen(&self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn on_request_frame(&self, _callback: Box<dyn FnMut()>) {}
|
||||
|
||||
fn on_input(&self, callback: Box<dyn FnMut(crate::PlatformInput) -> bool>) {}
|
||||
|
||||
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {}
|
||||
|
||||
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {}
|
||||
|
||||
fn on_fullscreen(&self, _callback: Box<dyn FnMut(bool)>) {}
|
||||
|
||||
fn on_moved(&self, callback: Box<dyn FnMut()>) {}
|
||||
|
||||
fn on_should_close(&self, callback: Box<dyn FnMut() -> bool>) {}
|
||||
|
||||
fn on_close(&self, _callback: Box<dyn FnOnce()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn on_appearance_changed(&self, _callback: Box<dyn FnMut()>) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn is_topmost_for_position(&self, _position: crate::Point<Pixels>) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn invalidate(&self) {}
|
||||
|
||||
fn draw(&self, _scene: &crate::Scene) {}
|
||||
|
||||
fn sprite_atlas(&self) -> sync::Arc<dyn crate::PlatformAtlas> {
|
||||
self.0.lock().sprite_atlas.clone()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue