mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
better but still broken
This commit is contained in:
parent
5eac797a93
commit
a369fb8033
9 changed files with 294 additions and 236 deletions
|
@ -32,11 +32,12 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
for screen in cx.platform().screens() {
|
for screen in cx.platform().screens() {
|
||||||
let screen_size = screen.size();
|
let screen_bounds = screen.bounds();
|
||||||
let (window_id, _) = cx.add_window(
|
let (window_id, _) = cx.add_window(
|
||||||
WindowOptions {
|
WindowOptions {
|
||||||
bounds: WindowBounds::Fixed(RectF::new(
|
bounds: WindowBounds::Fixed(RectF::new(
|
||||||
vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
|
screen_bounds.upper_right()
|
||||||
|
- vec2f(PADDING + window_size.x(), PADDING),
|
||||||
window_size,
|
window_size,
|
||||||
)),
|
)),
|
||||||
titlebar: None,
|
titlebar: None,
|
||||||
|
|
|
@ -31,11 +31,11 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||||
let window_size = vec2f(theme.window_width, theme.window_height);
|
let window_size = vec2f(theme.window_width, theme.window_height);
|
||||||
|
|
||||||
for screen in cx.platform().screens() {
|
for screen in cx.platform().screens() {
|
||||||
let screen_size = screen.size();
|
let screen_bounds = screen.bounds();
|
||||||
let (window_id, _) = cx.add_window(
|
let (window_id, _) = cx.add_window(
|
||||||
WindowOptions {
|
WindowOptions {
|
||||||
bounds: WindowBounds::Fixed(RectF::new(
|
bounds: WindowBounds::Fixed(RectF::new(
|
||||||
vec2f(screen_size.x() - window_size.x() - PADDING, PADDING),
|
screen_bounds.upper_right() - vec2f(PADDING + window_size.x(), PADDING),
|
||||||
window_size,
|
window_size,
|
||||||
)),
|
)),
|
||||||
titlebar: None,
|
titlebar: None,
|
||||||
|
|
|
@ -123,7 +123,7 @@ pub trait InputHandler {
|
||||||
|
|
||||||
pub trait Screen: Debug {
|
pub trait Screen: Debug {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn size(&self) -> Vector2F;
|
fn bounds(&self) -> RectF;
|
||||||
fn display_uuid(&self) -> Uuid;
|
fn display_uuid(&self) -> Uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,15 @@ mod sprite_cache;
|
||||||
mod status_item;
|
mod status_item;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
use cocoa::base::{BOOL, NO, YES};
|
use cocoa::{
|
||||||
|
base::{id, nil, BOOL, NO, YES},
|
||||||
|
foundation::{NSAutoreleasePool, NSNotFound, NSString, NSUInteger},
|
||||||
|
};
|
||||||
pub use dispatcher::Dispatcher;
|
pub use dispatcher::Dispatcher;
|
||||||
pub use fonts::FontSystem;
|
pub use fonts::FontSystem;
|
||||||
use platform::{MacForegroundPlatform, MacPlatform};
|
use platform::{MacForegroundPlatform, MacPlatform};
|
||||||
pub use renderer::Surface;
|
pub use renderer::Surface;
|
||||||
use std::{rc::Rc, sync::Arc};
|
use std::{ops::Range, rc::Rc, sync::Arc};
|
||||||
use window::Window;
|
use window::Window;
|
||||||
|
|
||||||
pub(crate) fn platform() -> Arc<dyn super::Platform> {
|
pub(crate) fn platform() -> Arc<dyn super::Platform> {
|
||||||
|
@ -41,3 +44,57 @@ impl BoolExt for bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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()
|
||||||
|
}
|
||||||
|
|
|
@ -1,27 +1,99 @@
|
||||||
use cocoa::foundation::{NSPoint, NSRect, NSSize};
|
use cocoa::{
|
||||||
use pathfinder_geometry::{rect::RectF, vector::Vector2F};
|
appkit::NSWindow,
|
||||||
|
base::id,
|
||||||
|
foundation::{NSPoint, NSRect, NSSize},
|
||||||
|
};
|
||||||
|
use objc::{msg_send, sel, sel_impl};
|
||||||
|
use pathfinder_geometry::{
|
||||||
|
rect::RectF,
|
||||||
|
vector::{vec2f, Vector2F},
|
||||||
|
};
|
||||||
|
|
||||||
|
///! 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.
|
||||||
|
|
||||||
pub trait Vector2FExt {
|
pub trait Vector2FExt {
|
||||||
fn to_ns_point(&self) -> NSPoint;
|
/// Converts self to an NSPoint with y axis pointing up.
|
||||||
fn to_ns_size(&self) -> NSSize;
|
fn to_screen_ns_point(&self, native_window: id) -> NSPoint;
|
||||||
|
}
|
||||||
|
impl Vector2FExt for Vector2F {
|
||||||
|
fn to_screen_ns_point(&self, native_window: id) -> NSPoint {
|
||||||
|
unsafe {
|
||||||
|
let point = NSPoint::new(self.x() as f64, -self.y() as f64);
|
||||||
|
msg_send![native_window, convertPointToScreen: point]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RectFExt {
|
pub trait RectFExt {
|
||||||
|
/// Converts self to an NSRect with y axis pointing up.
|
||||||
|
/// The resulting NSRect will have an origin at the bottom left of the rectangle.
|
||||||
|
/// Also takes care of converting from window scaled coordinates to screen coordinates
|
||||||
|
fn to_screen_ns_rect(&self, native_window: id) -> NSRect;
|
||||||
|
|
||||||
|
/// Converts self to an NSRect with y axis point up.
|
||||||
|
/// The resulting NSRect will have an origin at the bottom left of the rectangle.
|
||||||
|
/// Unlike to_screen_ns_rect, coordinates are not converted and are assumed to already be in screen scale
|
||||||
fn to_ns_rect(&self) -> NSRect;
|
fn to_ns_rect(&self) -> NSRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vector2FExt for Vector2F {
|
|
||||||
fn to_ns_point(&self) -> NSPoint {
|
|
||||||
NSPoint::new(self.x() as f64, self.y() as f64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_ns_size(&self) -> NSSize {
|
|
||||||
NSSize::new(self.x() as f64, self.y() as f64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RectFExt for RectF {
|
impl RectFExt for RectF {
|
||||||
|
fn to_screen_ns_rect(&self, native_window: id) -> NSRect {
|
||||||
|
unsafe { native_window.convertRectToScreen_(self.to_ns_rect()) }
|
||||||
|
}
|
||||||
|
|
||||||
fn to_ns_rect(&self) -> NSRect {
|
fn to_ns_rect(&self) -> NSRect {
|
||||||
NSRect::new(self.origin().to_ns_point(), self.size().to_ns_size())
|
dbg!(&self);
|
||||||
|
NSRect::new(
|
||||||
|
NSPoint::new(
|
||||||
|
dbg!(self.origin_x() as f64),
|
||||||
|
dbg!(-(self.origin_y() - self.height()) as f64),
|
||||||
|
),
|
||||||
|
NSSize::new(self.width() as f64, self.height() as f64),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait NSPointExt {
|
||||||
|
/// Converts self to a Vector2F with y axis pointing down.
|
||||||
|
/// Also takes care of converting from window scaled coordinates to screen coordinates
|
||||||
|
fn to_window_vector2f(&self, native_window: id) -> Vector2F;
|
||||||
|
}
|
||||||
|
impl NSPointExt for NSPoint {
|
||||||
|
fn to_window_vector2f(&self, native_window: id) -> Vector2F {
|
||||||
|
unsafe {
|
||||||
|
let point: NSPoint = msg_send![native_window, convertPointFromScreen: self];
|
||||||
|
vec2f(point.x as f32, -point.y as f32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait NSRectExt {
|
||||||
|
/// Converts self to a RectF with y axis pointing down.
|
||||||
|
/// The resulting RectF will have an origin at the top left of the rectangle.
|
||||||
|
/// Also takes care of converting from screen scale coordinates to window coordinates
|
||||||
|
fn to_window_rectf(&self, native_window: id) -> RectF;
|
||||||
|
|
||||||
|
/// Converts self to a RectF with y axis pointing down.
|
||||||
|
/// The resulting RectF will have an origin at the top left of the rectangle.
|
||||||
|
/// Unlike to_screen_ns_rect, coordinates are not converted and are assumed to already be in screen scale
|
||||||
|
fn to_rectf(&self) -> RectF;
|
||||||
|
}
|
||||||
|
impl NSRectExt for NSRect {
|
||||||
|
fn to_window_rectf(&self, native_window: id) -> RectF {
|
||||||
|
unsafe {
|
||||||
|
dbg!(self.origin.x);
|
||||||
|
let rect: NSRect = native_window.convertRectFromScreen_(*self);
|
||||||
|
rect.to_rectf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_rectf(&self) -> RectF {
|
||||||
|
RectF::new(
|
||||||
|
vec2f(
|
||||||
|
dbg!(self.origin.x as f32),
|
||||||
|
dbg!(-(self.origin.y - self.size.height) as f32),
|
||||||
|
),
|
||||||
|
vec2f(self.size.width as f32, self.size.height as f32),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
use std::{any::Any, ffi::c_void};
|
use std::{any::Any, ffi::c_void};
|
||||||
|
|
||||||
use crate::{
|
use crate::platform;
|
||||||
geometry::vector::{vec2f, Vector2F},
|
|
||||||
platform,
|
|
||||||
};
|
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::NSScreen,
|
appkit::NSScreen,
|
||||||
base::{id, nil},
|
base::{id, nil},
|
||||||
foundation::{NSArray, NSDictionary, NSString},
|
foundation::{NSArray, NSDictionary},
|
||||||
};
|
};
|
||||||
use core_foundation::{
|
use core_foundation::{
|
||||||
number::{kCFNumberIntType, CFNumberGetValue, CFNumberRef},
|
number::{kCFNumberIntType, CFNumberGetValue, CFNumberRef},
|
||||||
uuid::{CFUUIDGetUUIDBytes, CFUUIDRef},
|
uuid::{CFUUIDGetUUIDBytes, CFUUIDRef},
|
||||||
};
|
};
|
||||||
use core_graphics::display::CGDirectDisplayID;
|
use core_graphics::display::CGDirectDisplayID;
|
||||||
|
use pathfinder_geometry::rect::RectF;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::{geometry::NSRectExt, ns_string};
|
||||||
|
|
||||||
#[link(name = "ApplicationServices", kind = "framework")]
|
#[link(name = "ApplicationServices", kind = "framework")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
|
pub fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
|
||||||
|
@ -58,13 +58,6 @@ impl platform::Screen for Screen {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> Vector2F {
|
|
||||||
unsafe {
|
|
||||||
let frame = self.native_screen.frame();
|
|
||||||
vec2f(frame.size.width as f32, frame.size.height as f32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn display_uuid(&self) -> uuid::Uuid {
|
fn display_uuid(&self) -> uuid::Uuid {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Screen ids are not stable. Further, the default device id is also unstable across restarts.
|
// Screen ids are not stable. Further, the default device id is also unstable across restarts.
|
||||||
|
@ -72,7 +65,7 @@ impl platform::Screen for Screen {
|
||||||
// This approach is similar to that which winit takes
|
// This approach is similar to that which winit takes
|
||||||
// https://github.com/rust-windowing/winit/blob/402cbd55f932e95dbfb4e8b5e8551c49e56ff9ac/src/platform_impl/macos/monitor.rs#L99
|
// https://github.com/rust-windowing/winit/blob/402cbd55f932e95dbfb4e8b5e8551c49e56ff9ac/src/platform_impl/macos/monitor.rs#L99
|
||||||
let device_description = self.native_screen.deviceDescription();
|
let device_description = self.native_screen.deviceDescription();
|
||||||
let key = NSString::alloc(nil).init_str("NSScreenNumber");
|
let key = ns_string("NSScreenNumber");
|
||||||
let device_id_obj = device_description.objectForKey_(key);
|
let device_id_obj = device_description.objectForKey_(key);
|
||||||
let mut device_id: u32 = 0;
|
let mut device_id: u32 = 0;
|
||||||
CFNumberGetValue(
|
CFNumberGetValue(
|
||||||
|
@ -102,4 +95,11 @@ impl platform::Screen for Screen {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounds(&self) -> RectF {
|
||||||
|
unsafe {
|
||||||
|
let frame = self.native_screen.frame();
|
||||||
|
frame.to_rectf()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,12 @@ use crate::{
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{
|
appkit::{
|
||||||
CGFloat, CGPoint, NSApplication, NSBackingStoreBuffered, NSScreen, NSView,
|
CGPoint, NSApplication, NSBackingStoreBuffered, NSScreen, NSView, NSViewHeightSizable,
|
||||||
NSViewHeightSizable, NSViewWidthSizable, NSWindow, NSWindowButton,
|
NSViewWidthSizable, NSWindow, NSWindowButton, NSWindowCollectionBehavior,
|
||||||
NSWindowCollectionBehavior, NSWindowStyleMask,
|
NSWindowStyleMask,
|
||||||
},
|
},
|
||||||
base::{id, nil},
|
base::{id, nil},
|
||||||
foundation::{
|
foundation::{NSAutoreleasePool, NSInteger, NSPoint, NSRect, NSSize, NSString, NSUInteger},
|
||||||
NSAutoreleasePool, NSInteger, NSNotFound, NSPoint, NSRect, NSSize, NSString, NSUInteger,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use core_graphics::display::CGRect;
|
use core_graphics::display::CGRect;
|
||||||
use ctor::ctor;
|
use ctor::ctor;
|
||||||
|
@ -52,6 +50,11 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
geometry::{NSRectExt, Vector2FExt},
|
||||||
|
ns_string, NSRange,
|
||||||
|
};
|
||||||
|
|
||||||
const WINDOW_STATE_IVAR: &str = "windowState";
|
const WINDOW_STATE_IVAR: &str = "windowState";
|
||||||
|
|
||||||
static mut WINDOW_CLASS: *const Class = ptr::null();
|
static mut WINDOW_CLASS: *const Class = ptr::null();
|
||||||
|
@ -76,56 +79,6 @@ const NSTrackingInVisibleRect: NSUInteger = 0x200;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const NSWindowAnimationBehaviorUtilityWindow: NSInteger = 4;
|
const NSWindowAnimationBehaviorUtilityWindow: NSInteger = 4;
|
||||||
|
|
||||||
#[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) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[ctor]
|
#[ctor]
|
||||||
unsafe fn build_classes() {
|
unsafe fn build_classes() {
|
||||||
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
|
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
|
||||||
|
@ -315,8 +268,6 @@ unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const C
|
||||||
decl.register()
|
decl.register()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Window(Rc<RefCell<WindowState>>);
|
|
||||||
|
|
||||||
///Used to track what the IME does when we send it a keystroke.
|
///Used to track what the IME does when we send it a keystroke.
|
||||||
///This is only used to handle the case where the IME mysteriously
|
///This is only used to handle the case where the IME mysteriously
|
||||||
///swallows certain keys.
|
///swallows certain keys.
|
||||||
|
@ -329,6 +280,11 @@ enum ImeState {
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InsertText {
|
||||||
|
replacement_range: Option<Range<usize>>,
|
||||||
|
text: String,
|
||||||
|
}
|
||||||
|
|
||||||
struct WindowState {
|
struct WindowState {
|
||||||
id: usize,
|
id: usize,
|
||||||
native_window: id,
|
native_window: id,
|
||||||
|
@ -357,10 +313,111 @@ struct WindowState {
|
||||||
ime_text: Option<String>,
|
ime_text: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InsertText {
|
impl WindowState {
|
||||||
replacement_range: Option<Range<usize>>,
|
fn move_traffic_light(&self) {
|
||||||
text: String,
|
if let Some(traffic_light_position) = self.traffic_light_position {
|
||||||
|
let titlebar_height = self.titlebar_height();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let close_button: id = msg_send![
|
||||||
|
self.native_window,
|
||||||
|
standardWindowButton: NSWindowButton::NSWindowCloseButton
|
||||||
|
];
|
||||||
|
let min_button: id = msg_send![
|
||||||
|
self.native_window,
|
||||||
|
standardWindowButton: NSWindowButton::NSWindowMiniaturizeButton
|
||||||
|
];
|
||||||
|
let zoom_button: id = msg_send![
|
||||||
|
self.native_window,
|
||||||
|
standardWindowButton: NSWindowButton::NSWindowZoomButton
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut close_button_frame: CGRect = msg_send![close_button, frame];
|
||||||
|
let mut min_button_frame: CGRect = msg_send![min_button, frame];
|
||||||
|
let mut zoom_button_frame: CGRect = msg_send![zoom_button, frame];
|
||||||
|
let mut origin = vec2f(
|
||||||
|
traffic_light_position.x(),
|
||||||
|
titlebar_height
|
||||||
|
- traffic_light_position.y()
|
||||||
|
- close_button_frame.size.height as f32,
|
||||||
|
);
|
||||||
|
let button_spacing =
|
||||||
|
(min_button_frame.origin.x - close_button_frame.origin.x) as f32;
|
||||||
|
|
||||||
|
close_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64);
|
||||||
|
let _: () = msg_send![close_button, setFrame: close_button_frame];
|
||||||
|
origin.set_x(origin.x() + button_spacing);
|
||||||
|
|
||||||
|
min_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64);
|
||||||
|
let _: () = msg_send![min_button, setFrame: min_button_frame];
|
||||||
|
origin.set_x(origin.x() + button_spacing);
|
||||||
|
|
||||||
|
zoom_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64);
|
||||||
|
let _: () = msg_send![zoom_button, setFrame: zoom_button_frame];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_fullscreen(&self) -> bool {
|
||||||
|
unsafe {
|
||||||
|
let style_mask = self.native_window.styleMask();
|
||||||
|
style_mask.contains(NSWindowStyleMask::NSFullScreenWindowMask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounds(&self) -> WindowBounds {
|
||||||
|
unsafe {
|
||||||
|
if self.is_fullscreen() {
|
||||||
|
return WindowBounds::Fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
let screen_frame = self
|
||||||
|
.native_window
|
||||||
|
.screen()
|
||||||
|
.visibleFrame()
|
||||||
|
.to_window_rectf(self.native_window);
|
||||||
|
let window_frame = self.frame();
|
||||||
|
|
||||||
|
if screen_frame == window_frame {
|
||||||
|
WindowBounds::Maximized
|
||||||
|
} else {
|
||||||
|
WindowBounds::Fixed(window_frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the window bounds in window coordinates
|
||||||
|
fn frame(&self) -> RectF {
|
||||||
|
unsafe { NSWindow::frame(self.native_window).to_window_rectf(self.native_window) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn content_size(&self) -> Vector2F {
|
||||||
|
let NSSize { width, height, .. } =
|
||||||
|
unsafe { NSView::frame(self.native_window.contentView()) }.size;
|
||||||
|
vec2f(width as f32, height as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale_factor(&self) -> f32 {
|
||||||
|
get_scale_factor(self.native_window)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn titlebar_height(&self) -> f32 {
|
||||||
|
unsafe {
|
||||||
|
let frame = NSWindow::frame(self.native_window);
|
||||||
|
let content_layout_rect: CGRect = msg_send![self.native_window, contentLayoutRect];
|
||||||
|
(frame.size.height - content_layout_rect.size.height) as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn present_scene(&mut self, scene: Scene) {
|
||||||
|
self.scene_to_render = Some(scene);
|
||||||
|
unsafe {
|
||||||
|
let _: () = msg_send![self.native_window.contentView(), setNeedsDisplay: YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Window(Rc<RefCell<WindowState>>);
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn open(
|
pub fn open(
|
||||||
|
@ -395,7 +452,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let native_window = native_window.initWithContentRect_styleMask_backing_defer_screen_(
|
let native_window = native_window.initWithContentRect_styleMask_backing_defer_screen_(
|
||||||
RectF::new(Default::default(), vec2f(1024., 768.)).to_ns_rect(),
|
NSRect::new(NSPoint::new(0., 0.), NSSize::new(1024., 768.)),
|
||||||
style_mask,
|
style_mask,
|
||||||
NSBackingStoreBuffered,
|
NSBackingStoreBuffered,
|
||||||
NO,
|
NO,
|
||||||
|
@ -416,20 +473,8 @@ impl Window {
|
||||||
WindowBounds::Maximized => {
|
WindowBounds::Maximized => {
|
||||||
native_window.setFrame_display_(screen.visibleFrame(), YES);
|
native_window.setFrame_display_(screen.visibleFrame(), YES);
|
||||||
}
|
}
|
||||||
WindowBounds::Fixed(top_left_bounds) => {
|
WindowBounds::Fixed(rect) => {
|
||||||
let frame = screen.visibleFrame();
|
native_window.setFrame_display_(rect.to_screen_ns_rect(native_window), YES);
|
||||||
let bottom_left_bounds = RectF::new(
|
|
||||||
dbg!(vec2f(
|
|
||||||
top_left_bounds.origin_x(),
|
|
||||||
frame.size.height as f32
|
|
||||||
- top_left_bounds.origin_y()
|
|
||||||
- top_left_bounds.height(),
|
|
||||||
)),
|
|
||||||
dbg!(top_left_bounds.size()),
|
|
||||||
)
|
|
||||||
.to_ns_rect();
|
|
||||||
let screen_rect = native_window.convertRectToScreen_(bottom_left_bounds);
|
|
||||||
native_window.setFrame_display_(screen_rect, YES);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,21 +821,16 @@ impl platform::Window for Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_topmost_for_position(&self, position: Vector2F) -> bool {
|
fn is_topmost_for_position(&self, position: Vector2F) -> bool {
|
||||||
let window_bounds = self.bounds();
|
|
||||||
let self_borrow = self.0.borrow();
|
let self_borrow = self.0.borrow();
|
||||||
let self_id = self_borrow.id;
|
let self_id = self_borrow.id;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let window_frame = self_borrow.frame();
|
||||||
let app = NSApplication::sharedApplication(nil);
|
let app = NSApplication::sharedApplication(nil);
|
||||||
|
|
||||||
// Convert back to bottom-left coordinates
|
// Convert back to screen coordinates
|
||||||
let point = NSPoint::new(
|
let screen_point =
|
||||||
position.x() as CGFloat,
|
(position + window_frame.origin()).to_screen_ns_point(self_borrow.native_window);
|
||||||
(window_bounds.height() - position.y()) as CGFloat,
|
|
||||||
);
|
|
||||||
|
|
||||||
let screen_point: NSPoint =
|
|
||||||
msg_send![self_borrow.native_window, convertPointToScreen: point];
|
|
||||||
let window_number: NSInteger = msg_send![class!(NSWindow), windowNumberAtPoint:screen_point belowWindowWithWindowNumber:0];
|
let window_number: NSInteger = msg_send![class!(NSWindow), windowNumberAtPoint:screen_point belowWindowWithWindowNumber:0];
|
||||||
let top_most_window: id = msg_send![app, windowWithWindowNumber: window_number];
|
let top_most_window: id = msg_send![app, windowWithWindowNumber: window_number];
|
||||||
|
|
||||||
|
@ -807,113 +847,6 @@ impl platform::Window for Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowState {
|
|
||||||
fn move_traffic_light(&self) {
|
|
||||||
if let Some(traffic_light_position) = self.traffic_light_position {
|
|
||||||
let titlebar_height = self.titlebar_height();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let close_button: id = msg_send![
|
|
||||||
self.native_window,
|
|
||||||
standardWindowButton: NSWindowButton::NSWindowCloseButton
|
|
||||||
];
|
|
||||||
let min_button: id = msg_send![
|
|
||||||
self.native_window,
|
|
||||||
standardWindowButton: NSWindowButton::NSWindowMiniaturizeButton
|
|
||||||
];
|
|
||||||
let zoom_button: id = msg_send![
|
|
||||||
self.native_window,
|
|
||||||
standardWindowButton: NSWindowButton::NSWindowZoomButton
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut close_button_frame: CGRect = msg_send![close_button, frame];
|
|
||||||
let mut min_button_frame: CGRect = msg_send![min_button, frame];
|
|
||||||
let mut zoom_button_frame: CGRect = msg_send![zoom_button, frame];
|
|
||||||
let mut origin = vec2f(
|
|
||||||
traffic_light_position.x(),
|
|
||||||
titlebar_height
|
|
||||||
- traffic_light_position.y()
|
|
||||||
- close_button_frame.size.height as f32,
|
|
||||||
);
|
|
||||||
let button_spacing =
|
|
||||||
(min_button_frame.origin.x - close_button_frame.origin.x) as f32;
|
|
||||||
|
|
||||||
close_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64);
|
|
||||||
let _: () = msg_send![close_button, setFrame: close_button_frame];
|
|
||||||
origin.set_x(origin.x() + button_spacing);
|
|
||||||
|
|
||||||
min_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64);
|
|
||||||
let _: () = msg_send![min_button, setFrame: min_button_frame];
|
|
||||||
origin.set_x(origin.x() + button_spacing);
|
|
||||||
|
|
||||||
zoom_button_frame.origin = CGPoint::new(origin.x() as f64, origin.y() as f64);
|
|
||||||
let _: () = msg_send![zoom_button, setFrame: zoom_button_frame];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_fullscreen(&self) -> bool {
|
|
||||||
unsafe {
|
|
||||||
let style_mask = self.native_window.styleMask();
|
|
||||||
style_mask.contains(NSWindowStyleMask::NSFullScreenWindowMask)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bounds(&self) -> WindowBounds {
|
|
||||||
unsafe {
|
|
||||||
if self.is_fullscreen() {
|
|
||||||
return WindowBounds::Fullscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
let screen_frame = self.native_window.screen().visibleFrame();
|
|
||||||
let window_frame = NSWindow::frame(self.native_window);
|
|
||||||
let origin = vec2f(
|
|
||||||
window_frame.origin.x as f32,
|
|
||||||
(screen_frame.size.height - window_frame.origin.y - window_frame.size.height)
|
|
||||||
as f32,
|
|
||||||
);
|
|
||||||
let size = vec2f(
|
|
||||||
window_frame.size.width as f32,
|
|
||||||
window_frame.size.height as f32,
|
|
||||||
);
|
|
||||||
|
|
||||||
if origin.is_zero()
|
|
||||||
&& size.x() == screen_frame.size.width as f32
|
|
||||||
&& size.y() == screen_frame.size.height as f32
|
|
||||||
{
|
|
||||||
WindowBounds::Maximized
|
|
||||||
} else {
|
|
||||||
WindowBounds::Fixed(RectF::new(origin, size))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn content_size(&self) -> Vector2F {
|
|
||||||
let NSSize { width, height, .. } =
|
|
||||||
unsafe { NSView::frame(self.native_window.contentView()) }.size;
|
|
||||||
vec2f(width as f32, height as f32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scale_factor(&self) -> f32 {
|
|
||||||
get_scale_factor(self.native_window)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn titlebar_height(&self) -> f32 {
|
|
||||||
unsafe {
|
|
||||||
let frame = NSWindow::frame(self.native_window);
|
|
||||||
let content_layout_rect: CGRect = msg_send![self.native_window, contentLayoutRect];
|
|
||||||
(frame.size.height - content_layout_rect.size.height) as f32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn present_scene(&mut self, scene: Scene) {
|
|
||||||
self.scene_to_render = Some(scene);
|
|
||||||
unsafe {
|
|
||||||
let _: () = msg_send![self.native_window.contentView(), setNeedsDisplay: YES];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_scale_factor(native_window: id) -> f32 {
|
fn get_scale_factor(native_window: id) -> f32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let screen: id = msg_send![native_window, screen];
|
let screen: id = msg_send![native_window, screen];
|
||||||
|
@ -1547,10 +1480,6 @@ async fn synthetic_drag(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn ns_string(string: &str) -> id {
|
|
||||||
NSString::alloc(nil).init_str(string).autorelease()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_input_handler<F, R>(window: &Object, f: F) -> Option<R>
|
fn with_input_handler<F, R>(window: &Object, f: F) -> Option<R>
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut dyn InputHandler) -> R,
|
F: FnOnce(&mut dyn InputHandler) -> R,
|
||||||
|
|
|
@ -234,8 +234,8 @@ impl super::Screen for Screen {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> Vector2F {
|
fn bounds(&self) -> RectF {
|
||||||
Vector2F::new(1920., 1080.)
|
RectF::new(Vector2F::zero(), Vector2F::new(1920., 1080.))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_uuid(&self) -> uuid::Uuid {
|
fn display_uuid(&self) -> uuid::Uuid {
|
||||||
|
|
|
@ -20,8 +20,7 @@ use gpui::{
|
||||||
},
|
},
|
||||||
impl_actions,
|
impl_actions,
|
||||||
platform::{WindowBounds, WindowOptions},
|
platform::{WindowBounds, WindowOptions},
|
||||||
AssetSource, AsyncAppContext, ClipboardItem, Platform, PromptLevel, TitlebarOptions,
|
AssetSource, AsyncAppContext, Platform, PromptLevel, TitlebarOptions, ViewContext, WindowKind,
|
||||||
ViewContext, WindowKind,
|
|
||||||
};
|
};
|
||||||
use language::Rope;
|
use language::Rope;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
Loading…
Reference in a new issue