Files
oak-gpui/crates/gpui/src/platform/mac.rs
T
Dzmitry MalyshauandMikayla 9ad1862f2f Enable Blade on MacOS via "macos-blade" feature (#7669)
Depends on https://github.com/zed-industries/font-kit/pull/2 and
https://github.com/kvark/blade/pull/77

This change enables Blade to be also used on MacOS. It will also make it
easier to use it on Windows.

What works: most of the things. Zed loads as fast and appears equally
responsive to the current renderer.
<img width="306" alt="Screenshot 2024-02-11 at 12 09 15 AM"
src="https://github.com/zed-industries/zed/assets/107301/66d82f45-5ea2-4e2b-86c6-5b3ed333c827">

Things missing:
- [x] video streaming. ~~Requires a bit of plumbing on both Blade and
Zed sides, but all fairly straightforward.~~
  -  verified with a local setup
- [x] resize. ~~Not sure where exactly to hook up the reaction on the
window size change. Once we know where, the fix is one line.~~
- [ ] fine-tune CA Layer
- this isn't a blocker for merging the PR, but it would be a blocker if
we wanted to switch to the new path by default
- [ ] rebase on latest, get the dependency merged (need review/merge of
https://github.com/zed-industries/font-kit/pull/2!)

Update: I implemented resize support as well as "surface" rendering on
the Blade path (which will be useful on Linux/Windows later on). I
haven't tested the latter though - not sure how to get something
streaming. Would appreciate some help! I don't think this should be a
blocker to this PR, anyway.

The only little piece that's missing for the Blade on MacOS path to be
full-featured is fine-tuning the CALayer configuration. Zed does a lot
of careful logic in configuring the layer, such as switching the
"present with transaction" on/off intermittently, which Blade path
doesn't have yet.

Release Notes:
- N/A

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
2024-02-16 13:39:40 -08:00

131 lines
2.8 KiB
Rust

//! Macos screen have a y axis that goings up from the bottom of the screen and
//! an origin at the bottom left of the main display.
mod dispatcher;
mod display;
mod display_link;
mod events;
#[cfg(not(feature = "macos-blade"))]
mod metal_atlas;
#[cfg(not(feature = "macos-blade"))]
pub mod metal_renderer;
#[cfg(not(feature = "macos-blade"))]
use metal_renderer as renderer;
#[cfg(feature = "macos-blade")]
use crate::platform::blade as renderer;
mod open_type;
mod platform;
mod text_system;
mod window;
mod window_appearance;
use crate::{px, size, GlobalPixels, Pixels, Size};
use cocoa::{
base::{id, nil},
foundation::{NSAutoreleasePool, NSNotFound, NSRect, NSSize, NSString, NSUInteger},
};
use objc::runtime::{BOOL, NO, YES};
use std::ops::Range;
pub(crate) use dispatcher::*;
pub(crate) use display::*;
pub(crate) use display_link::*;
pub(crate) use platform::*;
pub(crate) use text_system::*;
pub(crate) use window::*;
trait BoolExt {
fn to_objc(self) -> BOOL;
}
impl BoolExt for bool {
fn to_objc(self) -> BOOL {
if self {
YES
} else {
NO
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
struct NSRange {
pub location: NSUInteger,
pub length: NSUInteger,
}
impl NSRange {
fn invalid() -> Self {
Self {
location: NSNotFound as NSUInteger,
length: 0,
}
}
fn is_valid(&self) -> bool {
self.location != NSNotFound as NSUInteger
}
fn to_range(self) -> Option<Range<usize>> {
if self.is_valid() {
let start = self.location as usize;
let end = start + self.length as usize;
Some(start..end)
} else {
None
}
}
}
impl From<Range<usize>> for NSRange {
fn from(range: Range<usize>) -> Self {
NSRange {
location: range.start as NSUInteger,
length: range.len() as NSUInteger,
}
}
}
unsafe impl objc::Encode for NSRange {
fn encode() -> objc::Encoding {
let encoding = format!(
"{{NSRange={}{}}}",
NSUInteger::encode().as_str(),
NSUInteger::encode().as_str()
);
unsafe { objc::Encoding::from_str(&encoding) }
}
}
unsafe fn ns_string(string: &str) -> id {
NSString::alloc(nil).init_str(string).autorelease()
}
impl From<NSSize> for Size<Pixels> {
fn from(value: NSSize) -> Self {
Size {
width: px(value.width as f32),
height: px(value.height as f32),
}
}
}
impl From<NSRect> for Size<Pixels> {
fn from(rect: NSRect) -> Self {
let NSSize { width, height } = rect.size;
size(width.into(), height.into())
}
}
impl From<NSRect> for Size<GlobalPixels> {
fn from(rect: NSRect) -> Self {
let NSSize { width, height } = rect.size;
size(width.into(), height.into())
}
}