chore: Prepare for Rust edition bump to 2024 (without autofix) (#27791)

Successor to #27779 - in this PR I've applied changes manually, without
futzing with if let lifetimes at all.

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2025-03-31 20:10:36 +02:00 committed by GitHub
parent d51aa2ffb0
commit 0729d24d77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
162 changed files with 2333 additions and 1937 deletions

View file

@ -226,7 +226,7 @@ embed-resource = "3.0"
naga.workspace = true
[target.'cfg(target_os = "macos")'.build-dependencies]
bindgen = "0.70.0"
bindgen = "0.71"
cbindgen = { version = "0.28.0", default-features = false }
naga.workspace = true

View file

@ -68,7 +68,7 @@ pub trait Action: 'static + Send {
/// Optional JSON schema for the action's input data.
fn action_json_schema(
_: &mut schemars::gen::SchemaGenerator,
_: &mut schemars::r#gen::SchemaGenerator,
) -> Option<schemars::schema::Schema>
where
Self: Sized,
@ -167,7 +167,7 @@ impl Default for ActionRegistry {
struct ActionData {
pub build: ActionBuilder,
pub json_schema: fn(&mut schemars::gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
pub json_schema: fn(&mut schemars::r#gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
}
/// This type must be public so that our macros can build it in other crates.
@ -183,7 +183,7 @@ pub struct MacroActionData {
pub aliases: &'static [&'static str],
pub type_id: TypeId,
pub build: ActionBuilder,
pub json_schema: fn(&mut schemars::gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
pub json_schema: fn(&mut schemars::r#gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
}
inventory::collect!(MacroActionBuilder);
@ -271,7 +271,7 @@ impl ActionRegistry {
pub fn action_schemas(
&self,
generator: &mut schemars::gen::SchemaGenerator,
generator: &mut schemars::r#gen::SchemaGenerator,
) -> Vec<(SharedString, Option<schemars::schema::Schema>)> {
// Use the order from all_names so that the resulting schema has sensible order.
self.all_names
@ -310,7 +310,7 @@ macro_rules! actions {
Ok(Box::new(Self))
},
fn action_json_schema(
_: &mut gpui::private::schemars::gen::SchemaGenerator,
_: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
}
@ -347,7 +347,7 @@ macro_rules! action_as {
Ok(Box::new(Self))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
}
@ -381,7 +381,7 @@ macro_rules! action_with_deprecated_aliases {
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
},
@ -412,7 +412,7 @@ macro_rules! impl_action_with_deprecated_aliases {
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
Some(<Self as gpui::private::schemars::JsonSchema>::json_schema(
generator,
@ -446,7 +446,7 @@ macro_rules! impl_actions {
Ok(std::boxed::Box::new(gpui::private::serde_json::from_value::<Self>(value)?))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
Some(<Self as gpui::private::schemars::JsonSchema>::json_schema(
generator,
@ -479,7 +479,7 @@ macro_rules! impl_internal_actions {
)))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
}
@ -509,7 +509,7 @@ macro_rules! impl_action_as {
))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
Some(<Self as gpui::private::schemars::JsonSchema>::json_schema(
generator,

View file

@ -1347,7 +1347,7 @@ impl App {
/// Get all non-internal actions that have been registered, along with their schemas.
pub fn action_schemas(
&self,
generator: &mut schemars::gen::SchemaGenerator,
generator: &mut schemars::r#gen::SchemaGenerator,
) -> Vec<(SharedString, Option<schemars::schema::Schema>)> {
self.actions.action_schemas(generator)
}

View file

@ -234,11 +234,11 @@ impl AsyncApp {
}
/// Run something using this entity and cx, when the returned struct is dropped
pub fn on_drop<T: 'static>(
pub fn on_drop<T: 'static, Callback: FnOnce(&mut T, &mut Context<T>) + 'static>(
&self,
entity: &WeakEntity<T>,
f: impl FnOnce(&mut T, &mut Context<T>) + 'static,
) -> util::Deferred<impl FnOnce()> {
f: Callback,
) -> util::Deferred<impl FnOnce() + use<T, Callback>> {
let entity = entity.clone();
let mut cx = self.clone();
util::defer(move || {

View file

@ -448,7 +448,10 @@ impl TestAppContext {
}
/// Returns a stream of notifications whenever the Entity is updated.
pub fn notifications<T: 'static>(&mut self, entity: &Entity<T>) -> impl Stream<Item = ()> {
pub fn notifications<T: 'static>(
&mut self,
entity: &Entity<T>,
) -> impl Stream<Item = ()> + use<T> {
let (tx, rx) = futures::channel::mpsc::unbounded();
self.update(|cx| {
cx.observe(entity, {

View file

@ -66,11 +66,15 @@ impl Arena {
where
F: FnOnce() -> T,
{
ptr::write(ptr, f());
unsafe {
ptr::write(ptr, f());
}
}
unsafe fn drop<T>(ptr: *mut u8) {
std::ptr::drop_in_place(ptr.cast::<T>());
unsafe {
std::ptr::drop_in_place(ptr.cast::<T>());
}
}
unsafe {

View file

@ -196,12 +196,12 @@ impl BackgroundExecutor {
}
#[cfg(not(any(test, feature = "test-support")))]
pub(crate) fn block_internal<R>(
pub(crate) fn block_internal<Fut: Future>(
&self,
_background_only: bool,
future: impl Future<Output = R>,
future: Fut,
timeout: Option<Duration>,
) -> Result<R, impl Future<Output = R>> {
) -> Result<Fut::Output, impl Future<Output = Fut::Output> + use<Fut>> {
use std::time::Instant;
let mut future = Box::pin(future);
@ -234,12 +234,12 @@ impl BackgroundExecutor {
#[cfg(any(test, feature = "test-support"))]
#[track_caller]
pub(crate) fn block_internal<R>(
pub(crate) fn block_internal<Fut: Future>(
&self,
background_only: bool,
future: impl Future<Output = R>,
future: Fut,
timeout: Option<Duration>,
) -> Result<R, impl Future<Output = R>> {
) -> Result<Fut::Output, impl Future<Output = Fut::Output> + use<Fut>> {
use std::sync::atomic::AtomicBool;
let mut future = Box::pin(future);
@ -291,8 +291,8 @@ impl BackgroundExecutor {
waiting_message = format!("\n waiting on: {}\n", waiting_hint);
}
panic!(
"parked with nothing left to run{waiting_message}{backtrace_message}",
)
"parked with nothing left to run{waiting_message}{backtrace_message}",
)
}
self.dispatcher.park(None);
}
@ -303,11 +303,11 @@ impl BackgroundExecutor {
/// Block the current thread until the given future resolves
/// or `duration` has elapsed.
pub fn block_with_timeout<R>(
pub fn block_with_timeout<Fut: Future>(
&self,
duration: Duration,
future: impl Future<Output = R>,
) -> Result<R, impl Future<Output = R>> {
future: Fut,
) -> Result<Fut::Output, impl Future<Output = Fut::Output> + use<Fut>> {
self.block_internal(true, future, Some(duration))
}
@ -365,7 +365,7 @@ impl BackgroundExecutor {
/// in tests, run an arbitrary number of tasks (determined by the SEED environment variable)
#[cfg(any(test, feature = "test-support"))]
pub fn simulate_random_delay(&self) -> impl Future<Output = ()> {
pub fn simulate_random_delay(&self) -> impl Future<Output = ()> + use<> {
self.dispatcher.as_test().unwrap().simulate_random_delay()
}

View file

@ -438,14 +438,8 @@ mod tests {
actions!(
test,
[
A,
B,
C,
D,
E,
F,
G, // Don't wrap, test the trailing comma
]
A, B, C, D, E, F, G, // Don't wrap, test the trailing comma
]
);
}
}

View file

@ -398,8 +398,12 @@ impl BladeRenderer {
log::error!("GPU hung");
#[cfg(target_os = "linux")]
if self.gpu.device_information().driver_name == "radv" {
log::error!("there's a known bug with amdgpu/radv, try setting ZED_PATH_SAMPLE_COUNT=0 as a workaround");
log::error!("if that helps you're running into https://github.com/zed-industries/zed/issues/26143");
log::error!(
"there's a known bug with amdgpu/radv, try setting ZED_PATH_SAMPLE_COUNT=0 as a workaround"
);
log::error!(
"if that helps you're running into https://github.com/zed-industries/zed/issues/26143"
);
}
log::error!(
"your device information is: {:?}",

View file

@ -632,7 +632,7 @@ pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::S
#[cfg(any(feature = "wayland", feature = "x11"))]
pub(super) unsafe fn read_fd(mut fd: filedescriptor::FileDescriptor) -> Result<Vec<u8>> {
let mut file = File::from_raw_fd(fd.as_raw_fd());
let mut file = unsafe { File::from_raw_fd(fd.as_raw_fd()) };
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)

View file

@ -256,7 +256,7 @@ impl Clipboard {
}
Ok(n) => written += n,
Err(err) if err.kind() == ErrorKind::WouldBlock => {
break Ok(PostAction::Continue)
break Ok(PostAction::Continue);
}
Err(_) => break Ok(PostAction::Remove),
}

View file

@ -186,12 +186,15 @@ fn find_visuals(xcb: &XCBConnection, screen_index: usize) -> VisualSet {
colormap: 0,
depth: depth_info.depth,
};
log::debug!("Visual id: {}, class: {:?}, depth: {}, bits_per_value: {}, masks: 0x{:x} 0x{:x} 0x{:x}",
log::debug!(
"Visual id: {}, class: {:?}, depth: {}, bits_per_value: {}, masks: 0x{:x} 0x{:x} 0x{:x}",
visual_type.visual_id,
visual_type.class,
depth_info.depth,
visual_type.bits_per_rgb_value,
visual_type.red_mask, visual_type.green_mask, visual_type.blue_mask,
visual_type.red_mask,
visual_type.green_mask,
visual_type.blue_mask,
);
if (
@ -409,15 +412,27 @@ impl X11WindowState {
let mut bounds = params.bounds.to_device_pixels(scale_factor);
if bounds.size.width.0 == 0 || bounds.size.height.0 == 0 {
log::warn!("Window bounds contain a zero value. height={}, width={}. Falling back to defaults.", bounds.size.height.0, bounds.size.width.0);
log::warn!(
"Window bounds contain a zero value. height={}, width={}. Falling back to defaults.",
bounds.size.height.0,
bounds.size.width.0
);
bounds.size.width = 800.into();
bounds.size.height = 600.into();
}
check_reply(
|| {
format!("X11 CreateWindow failed. depth: {}, x_window: {}, visual_set.root: {}, bounds.origin.x.0: {}, bounds.origin.y.0: {}, bounds.size.width.0: {}, bounds.size.height.0: {}",
visual.depth, x_window, visual_set.root, bounds.origin.x.0 + 2, bounds.origin.y.0, bounds.size.width.0, bounds.size.height.0)
format!(
"X11 CreateWindow failed. depth: {}, x_window: {}, visual_set.root: {}, bounds.origin.x.0: {}, bounds.origin.y.0: {}, bounds.size.width.0: {}, bounds.size.height.0: {}",
visual.depth,
x_window,
visual_set.root,
bounds.origin.x.0 + 2,
bounds.origin.y.0,
bounds.size.width.0,
bounds.size.height.0
)
},
xcb.create_window(
visual.depth,

View file

@ -74,11 +74,13 @@ trait NSStringExt {
impl NSStringExt for id {
unsafe fn to_str(&self) -> &str {
let cstr = self.UTF8String();
if cstr.is_null() {
""
} else {
CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
unsafe {
let cstr = self.UTF8String();
if cstr.is_null() {
""
} else {
CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
}
}
}
}
@ -134,7 +136,7 @@ unsafe impl objc::Encode for NSRange {
}
unsafe fn ns_string(string: &str) -> id {
NSString::alloc(nil).init_str(string).autorelease()
unsafe { NSString::alloc(nil).init_str(string).autorelease() }
}
impl From<NSSize> for Size<Pixels> {

View file

@ -65,7 +65,7 @@ impl MacDisplay {
}
#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
unsafe extern "C" {
fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
}

View file

@ -30,9 +30,11 @@ impl DisplayLink {
_flags_out: *mut i64,
frame_requests: *mut c_void,
) -> i32 {
let frame_requests = frame_requests as dispatch_source_t;
dispatch_source_merge_data(frame_requests, 1);
0
unsafe {
let frame_requests = frame_requests as dispatch_source_t;
dispatch_source_merge_data(frame_requests, 1);
0
}
}
unsafe {
@ -202,7 +204,7 @@ mod sys {
#[link(name = "CoreFoundation", kind = "framework")]
#[link(name = "CoreVideo", kind = "framework")]
#[allow(improper_ctypes, unknown_lints, clippy::duplicated_attributes)]
extern "C" {
unsafe extern "C" {
pub fn CVDisplayLinkCreateWithActiveCGDisplays(
display_link_out: *mut *mut CVDisplayLink,
) -> i32;
@ -228,40 +230,46 @@ mod sys {
callback: CVDisplayLinkOutputCallback,
user_info: *mut c_void,
) -> Result<Self> {
let mut display_link: *mut CVDisplayLink = 0 as _;
unsafe {
let mut display_link: *mut CVDisplayLink = 0 as _;
let code = CVDisplayLinkCreateWithActiveCGDisplays(&mut display_link);
anyhow::ensure!(code == 0, "could not create display link, code: {}", code);
let code = CVDisplayLinkCreateWithActiveCGDisplays(&mut display_link);
anyhow::ensure!(code == 0, "could not create display link, code: {}", code);
let mut display_link = DisplayLink::from_ptr(display_link);
let mut display_link = DisplayLink::from_ptr(display_link);
let code = CVDisplayLinkSetOutputCallback(&mut display_link, callback, user_info);
anyhow::ensure!(code == 0, "could not set output callback, code: {}", code);
let code = CVDisplayLinkSetOutputCallback(&mut display_link, callback, user_info);
anyhow::ensure!(code == 0, "could not set output callback, code: {}", code);
let code = CVDisplayLinkSetCurrentCGDisplay(&mut display_link, display_id);
anyhow::ensure!(
code == 0,
"could not assign display to display link, code: {}",
code
);
let code = CVDisplayLinkSetCurrentCGDisplay(&mut display_link, display_id);
anyhow::ensure!(
code == 0,
"could not assign display to display link, code: {}",
code
);
Ok(display_link)
Ok(display_link)
}
}
}
impl DisplayLinkRef {
/// Apple docs: [CVDisplayLinkStart](https://developer.apple.com/documentation/corevideo/1457193-cvdisplaylinkstart?language=objc)
pub unsafe fn start(&mut self) -> Result<()> {
let code = CVDisplayLinkStart(self);
anyhow::ensure!(code == 0, "could not start display link, code: {}", code);
Ok(())
unsafe {
let code = CVDisplayLinkStart(self);
anyhow::ensure!(code == 0, "could not start display link, code: {}", code);
Ok(())
}
}
/// Apple docs: [CVDisplayLinkStop](https://developer.apple.com/documentation/corevideo/1457281-cvdisplaylinkstop?language=objc)
pub unsafe fn stop(&mut self) -> Result<()> {
let code = CVDisplayLinkStop(self);
anyhow::ensure!(code == 0, "could not stop display link, code: {}", code);
Ok(())
unsafe {
let code = CVDisplayLinkStop(self);
anyhow::ensure!(code == 0, "could not stop display link, code: {}", code);
Ok(())
}
}
}
}

View file

@ -80,19 +80,21 @@ pub fn key_to_native(key: &str) -> Cow<str> {
}
unsafe fn read_modifiers(native_event: id) -> Modifiers {
let modifiers = native_event.modifierFlags();
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask);
unsafe {
let modifiers = native_event.modifierFlags();
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask);
Modifiers {
control,
alt,
shift,
platform: command,
function,
Modifiers {
control,
alt,
shift,
platform: command,
function,
}
}
}
@ -101,344 +103,351 @@ impl PlatformInput {
native_event: id,
window_height: Option<Pixels>,
) -> Option<Self> {
let event_type = native_event.eventType();
unsafe {
let event_type = native_event.eventType();
// Filter out event types that aren't in the NSEventType enum.
// See https://github.com/servo/cocoa-rs/issues/155#issuecomment-323482792 for details.
match event_type as u64 {
0 | 21 | 32 | 33 | 35 | 36 | 37 => {
return None;
// Filter out event types that aren't in the NSEventType enum.
// See https://github.com/servo/cocoa-rs/issues/155#issuecomment-323482792 for details.
match event_type as u64 {
0 | 21 | 32 | 33 | 35 | 36 | 37 => {
return None;
}
_ => {}
}
_ => {}
}
match event_type {
NSEventType::NSFlagsChanged => Some(Self::ModifiersChanged(ModifiersChangedEvent {
modifiers: read_modifiers(native_event),
})),
NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
keystroke: parse_keystroke(native_event),
is_held: native_event.isARepeat() == YES,
})),
NSEventType::NSKeyUp => Some(Self::KeyUp(KeyUpEvent {
keystroke: parse_keystroke(native_event),
})),
NSEventType::NSLeftMouseDown
| NSEventType::NSRightMouseDown
| NSEventType::NSOtherMouseDown => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseDown(MouseDownEvent {
button,
position: point(
px(native_event.locationInWindow().x as f32),
// MacOS screen coordinates are relative to bottom left
window_height - px(native_event.locationInWindow().y as f32),
),
match event_type {
NSEventType::NSFlagsChanged => {
Some(Self::ModifiersChanged(ModifiersChangedEvent {
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
first_mouse: false,
})
})
}
NSEventType::NSLeftMouseUp
| NSEventType::NSRightMouseUp
| NSEventType::NSOtherMouseUp => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseUp(MouseUpEvent {
button,
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
})
})
}
// Some mice (like Logitech MX Master) send navigation buttons as swipe events
NSEventType::NSEventTypeSwipe => {
let navigation_direction = match native_event.phase() {
NSEventPhase::NSEventPhaseEnded => match native_event.deltaX() {
x if x > 0.0 => Some(NavigationDirection::Back),
x if x < 0.0 => Some(NavigationDirection::Forward),
}))
}
NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
keystroke: parse_keystroke(native_event),
is_held: native_event.isARepeat() == YES,
})),
NSEventType::NSKeyUp => Some(Self::KeyUp(KeyUpEvent {
keystroke: parse_keystroke(native_event),
})),
NSEventType::NSLeftMouseDown
| NSEventType::NSRightMouseDown
| NSEventType::NSOtherMouseDown => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
},
_ => return None,
};
match navigation_direction {
Some(direction) => window_height.map(|window_height| {
};
window_height.map(|window_height| {
Self::MouseDown(MouseDownEvent {
button: MouseButton::Navigate(direction),
button,
position: point(
px(native_event.locationInWindow().x as f32),
// MacOS screen coordinates are relative to bottom left
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
first_mouse: false,
})
})
}
NSEventType::NSLeftMouseUp
| NSEventType::NSRightMouseUp
| NSEventType::NSOtherMouseUp => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseUp(MouseUpEvent {
button,
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: 1,
first_mouse: false,
click_count: native_event.clickCount() as usize,
})
}),
_ => None,
})
}
}
NSEventType::NSScrollWheel => window_height.map(|window_height| {
let phase = match native_event.phase() {
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
TouchPhase::Started
// Some mice (like Logitech MX Master) send navigation buttons as swipe events
NSEventType::NSEventTypeSwipe => {
let navigation_direction = match native_event.phase() {
NSEventPhase::NSEventPhaseEnded => match native_event.deltaX() {
x if x > 0.0 => Some(NavigationDirection::Back),
x if x < 0.0 => Some(NavigationDirection::Forward),
_ => return None,
},
_ => return None,
};
match navigation_direction {
Some(direction) => window_height.map(|window_height| {
Self::MouseDown(MouseDownEvent {
button: MouseButton::Navigate(direction),
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: 1,
first_mouse: false,
})
}),
_ => None,
}
NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
_ => TouchPhase::Moved,
};
}
NSEventType::NSScrollWheel => window_height.map(|window_height| {
let phase = match native_event.phase() {
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
TouchPhase::Started
}
NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
_ => TouchPhase::Moved,
};
let raw_data = point(
native_event.scrollingDeltaX() as f32,
native_event.scrollingDeltaY() as f32,
);
let raw_data = point(
native_event.scrollingDeltaX() as f32,
native_event.scrollingDeltaY() as f32,
);
let delta = if native_event.hasPreciseScrollingDeltas() == YES {
ScrollDelta::Pixels(raw_data.map(px))
} else {
ScrollDelta::Lines(raw_data)
};
let delta = if native_event.hasPreciseScrollingDeltas() == YES {
ScrollDelta::Pixels(raw_data.map(px))
} else {
ScrollDelta::Lines(raw_data)
};
Self::ScrollWheel(ScrollWheelEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
delta,
touch_phase: phase,
modifiers: read_modifiers(native_event),
})
}),
NSEventType::NSLeftMouseDragged
| NSEventType::NSRightMouseDragged
| NSEventType::NSOtherMouseDragged => {
let pressed_button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
pressed_button: Some(pressed_button),
Self::ScrollWheel(ScrollWheelEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
delta,
touch_phase: phase,
modifiers: read_modifiers(native_event),
})
})
}
NSEventType::NSMouseMoved => window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
NSEventType::NSMouseExited => window_height.map(|window_height| {
Self::MouseExited(MouseExitEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
}),
NSEventType::NSLeftMouseDragged
| NSEventType::NSRightMouseDragged
| NSEventType::NSOtherMouseDragged => {
let pressed_button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
_ => None,
window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
pressed_button: Some(pressed_button),
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
})
})
}
NSEventType::NSMouseMoved => window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
NSEventType::NSMouseExited => window_height.map(|window_height| {
Self::MouseExited(MouseExitEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
_ => None,
}
}
}
}
unsafe fn parse_keystroke(native_event: id) -> Keystroke {
use cocoa::appkit::*;
unsafe {
use cocoa::appkit::*;
let mut characters = native_event
.charactersIgnoringModifiers()
.to_str()
.to_string();
let mut key_char = None;
let first_char = characters.chars().next().map(|ch| ch as u16);
let modifiers = native_event.modifierFlags();
let mut characters = native_event
.charactersIgnoringModifiers()
.to_str()
.to_string();
let mut key_char = None;
let first_char = characters.chars().next().map(|ch| ch as u16);
let modifiers = native_event.modifierFlags();
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let mut shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask)
&& first_char.map_or(true, |ch| {
!(NSUpArrowFunctionKey..=NSModeSwitchFunctionKey).contains(&ch)
});
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let mut shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask)
&& first_char.map_or(true, |ch| {
!(NSUpArrowFunctionKey..=NSModeSwitchFunctionKey).contains(&ch)
});
#[allow(non_upper_case_globals)]
let key = match first_char {
Some(SPACE_KEY) => {
key_char = Some(" ".to_string());
"space".to_string()
}
Some(TAB_KEY) => {
key_char = Some("\t".to_string());
"tab".to_string()
}
Some(ENTER_KEY) | Some(NUMPAD_ENTER_KEY) => {
key_char = Some("\n".to_string());
"enter".to_string()
}
Some(BACKSPACE_KEY) => "backspace".to_string(),
Some(ESCAPE_KEY) => "escape".to_string(),
Some(SHIFT_TAB_KEY) => "tab".to_string(),
Some(NSUpArrowFunctionKey) => "up".to_string(),
Some(NSDownArrowFunctionKey) => "down".to_string(),
Some(NSLeftArrowFunctionKey) => "left".to_string(),
Some(NSRightArrowFunctionKey) => "right".to_string(),
Some(NSPageUpFunctionKey) => "pageup".to_string(),
Some(NSPageDownFunctionKey) => "pagedown".to_string(),
Some(NSHomeFunctionKey) => "home".to_string(),
Some(NSEndFunctionKey) => "end".to_string(),
Some(NSDeleteFunctionKey) => "delete".to_string(),
// Observed Insert==NSHelpFunctionKey not NSInsertFunctionKey.
Some(NSHelpFunctionKey) => "insert".to_string(),
Some(NSF1FunctionKey) => "f1".to_string(),
Some(NSF2FunctionKey) => "f2".to_string(),
Some(NSF3FunctionKey) => "f3".to_string(),
Some(NSF4FunctionKey) => "f4".to_string(),
Some(NSF5FunctionKey) => "f5".to_string(),
Some(NSF6FunctionKey) => "f6".to_string(),
Some(NSF7FunctionKey) => "f7".to_string(),
Some(NSF8FunctionKey) => "f8".to_string(),
Some(NSF9FunctionKey) => "f9".to_string(),
Some(NSF10FunctionKey) => "f10".to_string(),
Some(NSF11FunctionKey) => "f11".to_string(),
Some(NSF12FunctionKey) => "f12".to_string(),
Some(NSF13FunctionKey) => "f13".to_string(),
Some(NSF14FunctionKey) => "f14".to_string(),
Some(NSF15FunctionKey) => "f15".to_string(),
Some(NSF16FunctionKey) => "f16".to_string(),
Some(NSF17FunctionKey) => "f17".to_string(),
Some(NSF18FunctionKey) => "f18".to_string(),
Some(NSF19FunctionKey) => "f19".to_string(),
Some(NSF20FunctionKey) => "f20".to_string(),
Some(NSF21FunctionKey) => "f21".to_string(),
Some(NSF22FunctionKey) => "f22".to_string(),
Some(NSF23FunctionKey) => "f23".to_string(),
Some(NSF24FunctionKey) => "f24".to_string(),
Some(NSF25FunctionKey) => "f25".to_string(),
Some(NSF26FunctionKey) => "f26".to_string(),
Some(NSF27FunctionKey) => "f27".to_string(),
Some(NSF28FunctionKey) => "f28".to_string(),
Some(NSF29FunctionKey) => "f29".to_string(),
Some(NSF30FunctionKey) => "f30".to_string(),
Some(NSF31FunctionKey) => "f31".to_string(),
Some(NSF32FunctionKey) => "f32".to_string(),
Some(NSF33FunctionKey) => "f33".to_string(),
Some(NSF34FunctionKey) => "f34".to_string(),
Some(NSF35FunctionKey) => "f35".to_string(),
_ => {
// Cases to test when modifying this:
//
// qwerty key | none | cmd | cmd-shift
// * Armenian s | ս | cmd-s | cmd-shift-s (layout is non-ASCII, so we use cmd layout)
// * Dvorak+QWERTY s | o | cmd-s | cmd-shift-s (layout switches on cmd)
// * Ukrainian+QWERTY s | с | cmd-s | cmd-shift-s (macOS reports cmd-s instead of cmd-S)
// * Czech 7 | ý | cmd-ý | cmd-7 (layout has shifted numbers)
// * Norwegian 7 | 7 | cmd-7 | cmd-/ (macOS reports cmd-shift-7 instead of cmd-/)
// * Russian 7 | 7 | cmd-7 | cmd-& (shift-7 is . but when cmd is down, should use cmd layout)
// * German QWERTZ ; | ö | cmd-ö | cmd-Ö (Zed's shift special case only applies to a-z)
//
let mut chars_ignoring_modifiers =
chars_for_modified_key(native_event.keyCode(), NO_MOD);
let mut chars_with_shift = chars_for_modified_key(native_event.keyCode(), SHIFT_MOD);
let always_use_cmd_layout = always_use_command_layout();
// Handle Dvorak+QWERTY / Russian / Armenian
if command || always_use_cmd_layout {
let chars_with_cmd = chars_for_modified_key(native_event.keyCode(), CMD_MOD);
let chars_with_both =
chars_for_modified_key(native_event.keyCode(), CMD_MOD | SHIFT_MOD);
// We don't do this in the case that the shifted command key generates
// the same character as the unshifted command key (Norwegian, e.g.)
if chars_with_both != chars_with_cmd {
chars_with_shift = chars_with_both;
// Handle edge-case where cmd-shift-s reports cmd-s instead of
// cmd-shift-s (Ukrainian, etc.)
} else if chars_with_cmd.to_ascii_uppercase() != chars_with_cmd {
chars_with_shift = chars_with_cmd.to_ascii_uppercase();
}
chars_ignoring_modifiers = chars_with_cmd;
#[allow(non_upper_case_globals)]
let key = match first_char {
Some(SPACE_KEY) => {
key_char = Some(" ".to_string());
"space".to_string()
}
if !control && !command && !function {
let mut mods = NO_MOD;
if shift {
mods |= SHIFT_MOD;
}
if alt {
mods |= OPTION_MOD;
}
key_char = Some(chars_for_modified_key(native_event.keyCode(), mods));
Some(TAB_KEY) => {
key_char = Some("\t".to_string());
"tab".to_string()
}
Some(ENTER_KEY) | Some(NUMPAD_ENTER_KEY) => {
key_char = Some("\n".to_string());
"enter".to_string()
}
Some(BACKSPACE_KEY) => "backspace".to_string(),
Some(ESCAPE_KEY) => "escape".to_string(),
Some(SHIFT_TAB_KEY) => "tab".to_string(),
Some(NSUpArrowFunctionKey) => "up".to_string(),
Some(NSDownArrowFunctionKey) => "down".to_string(),
Some(NSLeftArrowFunctionKey) => "left".to_string(),
Some(NSRightArrowFunctionKey) => "right".to_string(),
Some(NSPageUpFunctionKey) => "pageup".to_string(),
Some(NSPageDownFunctionKey) => "pagedown".to_string(),
Some(NSHomeFunctionKey) => "home".to_string(),
Some(NSEndFunctionKey) => "end".to_string(),
Some(NSDeleteFunctionKey) => "delete".to_string(),
// Observed Insert==NSHelpFunctionKey not NSInsertFunctionKey.
Some(NSHelpFunctionKey) => "insert".to_string(),
Some(NSF1FunctionKey) => "f1".to_string(),
Some(NSF2FunctionKey) => "f2".to_string(),
Some(NSF3FunctionKey) => "f3".to_string(),
Some(NSF4FunctionKey) => "f4".to_string(),
Some(NSF5FunctionKey) => "f5".to_string(),
Some(NSF6FunctionKey) => "f6".to_string(),
Some(NSF7FunctionKey) => "f7".to_string(),
Some(NSF8FunctionKey) => "f8".to_string(),
Some(NSF9FunctionKey) => "f9".to_string(),
Some(NSF10FunctionKey) => "f10".to_string(),
Some(NSF11FunctionKey) => "f11".to_string(),
Some(NSF12FunctionKey) => "f12".to_string(),
Some(NSF13FunctionKey) => "f13".to_string(),
Some(NSF14FunctionKey) => "f14".to_string(),
Some(NSF15FunctionKey) => "f15".to_string(),
Some(NSF16FunctionKey) => "f16".to_string(),
Some(NSF17FunctionKey) => "f17".to_string(),
Some(NSF18FunctionKey) => "f18".to_string(),
Some(NSF19FunctionKey) => "f19".to_string(),
Some(NSF20FunctionKey) => "f20".to_string(),
Some(NSF21FunctionKey) => "f21".to_string(),
Some(NSF22FunctionKey) => "f22".to_string(),
Some(NSF23FunctionKey) => "f23".to_string(),
Some(NSF24FunctionKey) => "f24".to_string(),
Some(NSF25FunctionKey) => "f25".to_string(),
Some(NSF26FunctionKey) => "f26".to_string(),
Some(NSF27FunctionKey) => "f27".to_string(),
Some(NSF28FunctionKey) => "f28".to_string(),
Some(NSF29FunctionKey) => "f29".to_string(),
Some(NSF30FunctionKey) => "f30".to_string(),
Some(NSF31FunctionKey) => "f31".to_string(),
Some(NSF32FunctionKey) => "f32".to_string(),
Some(NSF33FunctionKey) => "f33".to_string(),
Some(NSF34FunctionKey) => "f34".to_string(),
Some(NSF35FunctionKey) => "f35".to_string(),
_ => {
// Cases to test when modifying this:
//
// qwerty key | none | cmd | cmd-shift
// * Armenian s | ս | cmd-s | cmd-shift-s (layout is non-ASCII, so we use cmd layout)
// * Dvorak+QWERTY s | o | cmd-s | cmd-shift-s (layout switches on cmd)
// * Ukrainian+QWERTY s | с | cmd-s | cmd-shift-s (macOS reports cmd-s instead of cmd-S)
// * Czech 7 | ý | cmd-ý | cmd-7 (layout has shifted numbers)
// * Norwegian 7 | 7 | cmd-7 | cmd-/ (macOS reports cmd-shift-7 instead of cmd-/)
// * Russian 7 | 7 | cmd-7 | cmd-& (shift-7 is . but when cmd is down, should use cmd layout)
// * German QWERTZ ; | ö | cmd-ö | cmd-Ö (Zed's shift special case only applies to a-z)
//
let mut chars_ignoring_modifiers =
chars_for_modified_key(native_event.keyCode(), NO_MOD);
let mut chars_with_shift =
chars_for_modified_key(native_event.keyCode(), SHIFT_MOD);
let always_use_cmd_layout = always_use_command_layout();
let mut key = if shift
&& chars_ignoring_modifiers
.chars()
.all(|c| c.is_ascii_lowercase())
{
chars_ignoring_modifiers
} else if shift {
shift = false;
chars_with_shift
} else {
chars_ignoring_modifiers
};
// Handle Dvorak+QWERTY / Russian / Armenian
if command || always_use_cmd_layout {
let chars_with_cmd = chars_for_modified_key(native_event.keyCode(), CMD_MOD);
let chars_with_both =
chars_for_modified_key(native_event.keyCode(), CMD_MOD | SHIFT_MOD);
key
// We don't do this in the case that the shifted command key generates
// the same character as the unshifted command key (Norwegian, e.g.)
if chars_with_both != chars_with_cmd {
chars_with_shift = chars_with_both;
// Handle edge-case where cmd-shift-s reports cmd-s instead of
// cmd-shift-s (Ukrainian, etc.)
} else if chars_with_cmd.to_ascii_uppercase() != chars_with_cmd {
chars_with_shift = chars_with_cmd.to_ascii_uppercase();
}
chars_ignoring_modifiers = chars_with_cmd;
}
if !control && !command && !function {
let mut mods = NO_MOD;
if shift {
mods |= SHIFT_MOD;
}
if alt {
mods |= OPTION_MOD;
}
key_char = Some(chars_for_modified_key(native_event.keyCode(), mods));
}
let mut key = if shift
&& chars_ignoring_modifiers
.chars()
.all(|c| c.is_ascii_lowercase())
{
chars_ignoring_modifiers
} else if shift {
shift = false;
chars_with_shift
} else {
chars_ignoring_modifiers
};
key
}
};
Keystroke {
modifiers: Modifiers {
control,
alt,
shift,
platform: command,
function,
},
key,
key_char,
}
};
Keystroke {
modifiers: Modifiers {
control,
alt,
shift,
platform: command,
function,
},
key,
key_char,
}
}

View file

@ -471,7 +471,8 @@ impl MetalRenderer {
if !ok {
command_encoder.end_encoding();
return Err(anyhow!("scene too large: {} paths, {} shadows, {} quads, {} underlines, {} mono, {} poly, {} surfaces",
return Err(anyhow!(
"scene too large: {} paths, {} shadows, {} quads, {} underlines, {} mono, {} poly, {} surfaces",
scene.paths.len(),
scene.shadows.len(),
scene.quads.len(),

View file

@ -132,7 +132,7 @@ fn append_system_fallbacks(fallback_array: CFMutableArrayRef, font_ref: CTFontRe
}
#[link(name = "CoreText", kind = "framework")]
extern "C" {
unsafe extern "C" {
static kCTFontOpenTypeFeatureTag: CFStringRef;
static kCTFontOpenTypeFeatureValue: CFStringRef;

View file

@ -68,79 +68,82 @@ static mut APP_DELEGATE_CLASS: *const Class = ptr::null();
#[ctor]
unsafe fn build_classes() {
APP_CLASS = {
let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.register()
unsafe {
APP_CLASS = {
let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.register()
}
};
unsafe {
APP_DELEGATE_CLASS = unsafe {
let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.add_method(
sel!(applicationDidFinishLaunching:),
did_finish_launching as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
should_handle_reopen as extern "C" fn(&mut Object, Sel, id, bool),
);
decl.add_method(
sel!(applicationWillTerminate:),
will_terminate as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(handleGPUIMenuItem:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
// Add menu item handlers so that OS save panels have the correct key commands
decl.add_method(
sel!(cut:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(copy:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(paste:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(selectAll:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(undo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(redo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(validateMenuItem:),
validate_menu_item as extern "C" fn(&mut Object, Sel, id) -> bool,
);
decl.add_method(
sel!(menuWillOpen:),
menu_will_open as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationDockMenu:),
handle_dock_menu as extern "C" fn(&mut Object, Sel, id) -> id,
);
decl.add_method(
sel!(application:openURLs:),
open_urls as extern "C" fn(&mut Object, Sel, id, id),
);
APP_DELEGATE_CLASS = {
let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.add_method(
sel!(applicationDidFinishLaunching:),
did_finish_launching as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
should_handle_reopen as extern "C" fn(&mut Object, Sel, id, bool),
);
decl.add_method(
sel!(applicationWillTerminate:),
will_terminate as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(handleGPUIMenuItem:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
// Add menu item handlers so that OS save panels have the correct key commands
decl.add_method(
sel!(cut:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(copy:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(paste:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(selectAll:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(undo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(redo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(validateMenuItem:),
validate_menu_item as extern "C" fn(&mut Object, Sel, id) -> bool,
);
decl.add_method(
sel!(menuWillOpen:),
menu_will_open as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationDockMenu:),
handle_dock_menu as extern "C" fn(&mut Object, Sel, id) -> id,
);
decl.add_method(
sel!(application:openURLs:),
open_urls as extern "C" fn(&mut Object, Sel, id, id),
);
decl.add_method(
sel!(onKeyboardLayoutChange:),
on_keyboard_layout_change as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(onKeyboardLayoutChange:),
on_keyboard_layout_change as extern "C" fn(&mut Object, Sel, id),
);
decl.register()
decl.register()
}
}
}
@ -206,14 +209,16 @@ impl MacPlatform {
}
unsafe fn read_from_pasteboard(&self, pasteboard: *mut Object, kind: id) -> Option<&[u8]> {
let data = pasteboard.dataForType(kind);
if data == nil {
None
} else {
Some(slice::from_raw_parts(
data.bytes() as *mut u8,
data.length() as usize,
))
unsafe {
let data = pasteboard.dataForType(kind);
if data == nil {
None
} else {
Some(slice::from_raw_parts(
data.bytes() as *mut u8,
data.length() as usize,
))
}
}
}
@ -224,36 +229,38 @@ impl MacPlatform {
actions: &mut Vec<Box<dyn Action>>,
keymap: &Keymap,
) -> id {
let application_menu = NSMenu::new(nil).autorelease();
application_menu.setDelegate_(delegate);
unsafe {
let application_menu = NSMenu::new(nil).autorelease();
application_menu.setDelegate_(delegate);
for menu_config in menus {
let menu = NSMenu::new(nil).autorelease();
let menu_title = ns_string(&menu_config.name);
menu.setTitle_(menu_title);
menu.setDelegate_(delegate);
for menu_config in menus {
let menu = NSMenu::new(nil).autorelease();
let menu_title = ns_string(&menu_config.name);
menu.setTitle_(menu_title);
menu.setDelegate_(delegate);
for item_config in menu_config.items {
menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
for item_config in menu_config.items {
menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
}
let menu_item = NSMenuItem::new(nil).autorelease();
menu_item.setTitle_(menu_title);
menu_item.setSubmenu_(menu);
application_menu.addItem_(menu_item);
if menu_config.name == "Window" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setWindowsMenu_(menu);
}
}
let menu_item = NSMenuItem::new(nil).autorelease();
menu_item.setTitle_(menu_title);
menu_item.setSubmenu_(menu);
application_menu.addItem_(menu_item);
if menu_config.name == "Window" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setWindowsMenu_(menu);
}
application_menu
}
application_menu
}
unsafe fn create_dock_menu(
@ -263,18 +270,20 @@ impl MacPlatform {
actions: &mut Vec<Box<dyn Action>>,
keymap: &Keymap,
) -> id {
let dock_menu = NSMenu::new(nil);
dock_menu.setDelegate_(delegate);
for item_config in menu_items {
dock_menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
}
unsafe {
let dock_menu = NSMenu::new(nil);
dock_menu.setDelegate_(delegate);
for item_config in menu_items {
dock_menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
}
dock_menu
dock_menu
}
}
unsafe fn create_menu_item(
@ -283,70 +292,80 @@ impl MacPlatform {
actions: &mut Vec<Box<dyn Action>>,
keymap: &Keymap,
) -> id {
match item {
MenuItem::Separator => NSMenuItem::separatorItem(nil),
MenuItem::Action {
name,
action,
os_action,
} => {
let keystrokes = crate::Keymap::binding_to_display_from_bindings_iterator(
keymap.bindings_for_action(action.as_ref()),
)
.map(|binding| binding.keystrokes());
unsafe {
match item {
MenuItem::Separator => NSMenuItem::separatorItem(nil),
MenuItem::Action {
name,
action,
os_action,
} => {
let keystrokes = crate::Keymap::binding_to_display_from_bindings_iterator(
keymap.bindings_for_action(action.as_ref()),
)
.map(|binding| binding.keystrokes());
let selector = match os_action {
Some(crate::OsAction::Cut) => selector("cut:"),
Some(crate::OsAction::Copy) => selector("copy:"),
Some(crate::OsAction::Paste) => selector("paste:"),
Some(crate::OsAction::SelectAll) => selector("selectAll:"),
// "undo:" and "redo:" are always disabled in our case, as
// we don't have a NSTextView/NSTextField to enable them on.
Some(crate::OsAction::Undo) => selector("handleGPUIMenuItem:"),
Some(crate::OsAction::Redo) => selector("handleGPUIMenuItem:"),
None => selector("handleGPUIMenuItem:"),
};
let selector = match os_action {
Some(crate::OsAction::Cut) => selector("cut:"),
Some(crate::OsAction::Copy) => selector("copy:"),
Some(crate::OsAction::Paste) => selector("paste:"),
Some(crate::OsAction::SelectAll) => selector("selectAll:"),
// "undo:" and "redo:" are always disabled in our case, as
// we don't have a NSTextView/NSTextField to enable them on.
Some(crate::OsAction::Undo) => selector("handleGPUIMenuItem:"),
Some(crate::OsAction::Redo) => selector("handleGPUIMenuItem:"),
None => selector("handleGPUIMenuItem:"),
};
let item;
if let Some(keystrokes) = keystrokes {
if keystrokes.len() == 1 {
let keystroke = &keystrokes[0];
let mut mask = NSEventModifierFlags::empty();
for (modifier, flag) in &[
(
keystroke.modifiers.platform,
NSEventModifierFlags::NSCommandKeyMask,
),
(
keystroke.modifiers.control,
NSEventModifierFlags::NSControlKeyMask,
),
(
keystroke.modifiers.alt,
NSEventModifierFlags::NSAlternateKeyMask,
),
(
keystroke.modifiers.shift,
NSEventModifierFlags::NSShiftKeyMask,
),
] {
if *modifier {
mask |= *flag;
let item;
if let Some(keystrokes) = keystrokes {
if keystrokes.len() == 1 {
let keystroke = &keystrokes[0];
let mut mask = NSEventModifierFlags::empty();
for (modifier, flag) in &[
(
keystroke.modifiers.platform,
NSEventModifierFlags::NSCommandKeyMask,
),
(
keystroke.modifiers.control,
NSEventModifierFlags::NSControlKeyMask,
),
(
keystroke.modifiers.alt,
NSEventModifierFlags::NSAlternateKeyMask,
),
(
keystroke.modifiers.shift,
NSEventModifierFlags::NSShiftKeyMask,
),
] {
if *modifier {
mask |= *flag;
}
}
}
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(key_to_native(&keystroke.key).as_ref()),
)
.autorelease();
if MacPlatform::os_version().unwrap() >= SemanticVersion::new(12, 0, 0) {
let _: () =
msg_send![item, setAllowsAutomaticKeyEquivalentLocalization: NO];
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(key_to_native(&keystroke.key).as_ref()),
)
.autorelease();
if MacPlatform::os_version().unwrap() >= SemanticVersion::new(12, 0, 0)
{
let _: () = msg_send![item, setAllowsAutomaticKeyEquivalentLocalization: NO];
}
item.setKeyEquivalentModifierMask_(mask);
} else {
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(""),
)
.autorelease();
}
item.setKeyEquivalentModifierMask_(mask);
} else {
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
@ -356,36 +375,28 @@ impl MacPlatform {
)
.autorelease();
}
} else {
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(""),
)
.autorelease();
}
let tag = actions.len() as NSInteger;
let _: () = msg_send![item, setTag: tag];
actions.push(action);
item
}
MenuItem::Submenu(Menu { name, items }) => {
let item = NSMenuItem::new(nil).autorelease();
let submenu = NSMenu::new(nil).autorelease();
submenu.setDelegate_(delegate);
for item in items {
submenu.addItem_(Self::create_menu_item(item, delegate, actions, keymap));
}
item.setSubmenu_(submenu);
item.setTitle_(ns_string(&name));
if name == "Services" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setServicesMenu_(item);
let tag = actions.len() as NSInteger;
let _: () = msg_send![item, setTag: tag];
actions.push(action);
item
}
MenuItem::Submenu(Menu { name, items }) => {
let item = NSMenuItem::new(nil).autorelease();
let submenu = NSMenu::new(nil).autorelease();
submenu.setDelegate_(delegate);
for item in items {
submenu.addItem_(Self::create_menu_item(item, delegate, actions, keymap));
}
item.setSubmenu_(submenu);
item.setTitle_(ns_string(&name));
if name == "Services" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setServicesMenu_(item);
}
item
item
}
}
}
}
@ -460,8 +471,10 @@ impl Platform for MacPlatform {
}
unsafe extern "C" fn quit(_: *mut c_void) {
let app = NSApplication::sharedApplication(nil);
let _: () = msg_send![app, terminate: nil];
unsafe {
let app = NSApplication::sharedApplication(nil);
let _: () = msg_send![app, terminate: nil];
}
}
}
@ -1180,75 +1193,81 @@ impl MacPlatform {
state: &MacPlatformState,
text_bytes: &[u8],
) -> ClipboardItem {
let text = String::from_utf8_lossy(text_bytes).to_string();
let metadata = self
.read_from_pasteboard(state.pasteboard, state.text_hash_pasteboard_type)
.and_then(|hash_bytes| {
let hash_bytes = hash_bytes.try_into().ok()?;
let hash = u64::from_be_bytes(hash_bytes);
let metadata =
self.read_from_pasteboard(state.pasteboard, state.metadata_pasteboard_type)?;
unsafe {
let text = String::from_utf8_lossy(text_bytes).to_string();
let metadata = self
.read_from_pasteboard(state.pasteboard, state.text_hash_pasteboard_type)
.and_then(|hash_bytes| {
let hash_bytes = hash_bytes.try_into().ok()?;
let hash = u64::from_be_bytes(hash_bytes);
let metadata = self
.read_from_pasteboard(state.pasteboard, state.metadata_pasteboard_type)?;
if hash == ClipboardString::text_hash(&text) {
String::from_utf8(metadata.to_vec()).ok()
} else {
None
}
});
if hash == ClipboardString::text_hash(&text) {
String::from_utf8(metadata.to_vec()).ok()
} else {
None
}
});
ClipboardItem {
entries: vec![ClipboardEntry::String(ClipboardString { text, metadata })],
ClipboardItem {
entries: vec![ClipboardEntry::String(ClipboardString { text, metadata })],
}
}
}
unsafe fn write_plaintext_to_clipboard(&self, string: &ClipboardString) {
let state = self.0.lock();
state.pasteboard.clearContents();
unsafe {
let state = self.0.lock();
state.pasteboard.clearContents();
let text_bytes = NSData::dataWithBytes_length_(
nil,
string.text.as_ptr() as *const c_void,
string.text.len() as u64,
);
state
.pasteboard
.setData_forType(text_bytes, NSPasteboardTypeString);
if let Some(metadata) = string.metadata.as_ref() {
let hash_bytes = ClipboardString::text_hash(&string.text).to_be_bytes();
let hash_bytes = NSData::dataWithBytes_length_(
let text_bytes = NSData::dataWithBytes_length_(
nil,
hash_bytes.as_ptr() as *const c_void,
hash_bytes.len() as u64,
string.text.as_ptr() as *const c_void,
string.text.len() as u64,
);
state
.pasteboard
.setData_forType(hash_bytes, state.text_hash_pasteboard_type);
.setData_forType(text_bytes, NSPasteboardTypeString);
let metadata_bytes = NSData::dataWithBytes_length_(
nil,
metadata.as_ptr() as *const c_void,
metadata.len() as u64,
);
state
.pasteboard
.setData_forType(metadata_bytes, state.metadata_pasteboard_type);
if let Some(metadata) = string.metadata.as_ref() {
let hash_bytes = ClipboardString::text_hash(&string.text).to_be_bytes();
let hash_bytes = NSData::dataWithBytes_length_(
nil,
hash_bytes.as_ptr() as *const c_void,
hash_bytes.len() as u64,
);
state
.pasteboard
.setData_forType(hash_bytes, state.text_hash_pasteboard_type);
let metadata_bytes = NSData::dataWithBytes_length_(
nil,
metadata.as_ptr() as *const c_void,
metadata.len() as u64,
);
state
.pasteboard
.setData_forType(metadata_bytes, state.metadata_pasteboard_type);
}
}
}
unsafe fn write_image_to_clipboard(&self, image: &Image) {
let state = self.0.lock();
state.pasteboard.clearContents();
unsafe {
let state = self.0.lock();
state.pasteboard.clearContents();
let bytes = NSData::dataWithBytes_length_(
nil,
image.bytes.as_ptr() as *const c_void,
image.bytes.len() as u64,
);
let bytes = NSData::dataWithBytes_length_(
nil,
image.bytes.as_ptr() as *const c_void,
image.bytes.len() as u64,
);
state
.pasteboard
.setData_forType(bytes, Into::<UTType>::into(image.format).inner_mut());
state
.pasteboard
.setData_forType(bytes, Into::<UTType>::into(image.format).inner_mut());
}
}
}
@ -1280,15 +1299,17 @@ fn try_clipboard_image(pasteboard: id, format: ImageFormat) -> Option<ClipboardI
unsafe fn path_from_objc(path: id) -> PathBuf {
let len = msg_send![path, lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
let bytes = path.UTF8String() as *const u8;
let path = str::from_utf8(slice::from_raw_parts(bytes, len)).unwrap();
let bytes = unsafe { path.UTF8String() as *const u8 };
let path = str::from_utf8(unsafe { slice::from_raw_parts(bytes, len) }).unwrap();
PathBuf::from(path)
}
unsafe fn get_mac_platform(object: &mut Object) -> &MacPlatform {
let platform_ptr: *mut c_void = *object.get_ivar(MAC_PLATFORM_IVAR);
assert!(!platform_ptr.is_null());
&*(platform_ptr as *const MacPlatform)
unsafe {
let platform_ptr: *mut c_void = *object.get_ivar(MAC_PLATFORM_IVAR);
assert!(!platform_ptr.is_null());
&*(platform_ptr as *const MacPlatform)
}
}
extern "C" fn did_finish_launching(this: &mut Object, _: Sel, _: id) {
@ -1438,25 +1459,24 @@ extern "C" fn handle_dock_menu(this: &mut Object, _: Sel, _: id) -> id {
}
unsafe fn ns_string(string: &str) -> id {
NSString::alloc(nil).init_str(string).autorelease()
unsafe { NSString::alloc(nil).init_str(string).autorelease() }
}
unsafe fn ns_url_to_path(url: id) -> Result<PathBuf> {
let path: *mut c_char = msg_send![url, fileSystemRepresentation];
if path.is_null() {
Err(anyhow!(
"url is not a file path: {}",
Err(anyhow!("url is not a file path: {}", unsafe {
CStr::from_ptr(url.absoluteString().UTF8String()).to_string_lossy()
))
}))
} else {
Ok(PathBuf::from(OsStr::from_bytes(
CStr::from_ptr(path).to_bytes(),
)))
Ok(PathBuf::from(OsStr::from_bytes(unsafe {
CStr::from_ptr(path).to_bytes()
})))
}
}
#[link(name = "Carbon", kind = "framework")]
extern "C" {
unsafe extern "C" {
pub(super) fn TISCopyCurrentKeyboardLayoutInputSource() -> *mut Object;
pub(super) fn TISGetInputSourceProperty(
inputSource: *mut Object,
@ -1485,7 +1505,7 @@ mod security {
use super::*;
#[link(name = "Security", kind = "framework")]
extern "C" {
unsafe extern "C" {
pub static kSecClass: CFStringRef;
pub static kSecClassInternetPassword: CFStringRef;
pub static kSecAttrServer: CFStringRef;

View file

@ -37,7 +37,7 @@ pub struct MacScreenCaptureStream {
}
#[link(name = "ScreenCaptureKit", kind = "framework")]
extern "C" {}
unsafe extern "C" {}
static mut DELEGATE_CLASS: *const Class = ptr::null();
static mut OUTPUT_CLASS: *const Class = ptr::null();
@ -200,28 +200,31 @@ pub(crate) fn get_sources() -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptur
#[ctor]
unsafe fn build_classes() {
let mut decl = ClassDecl::new("GPUIStreamDelegate", class!(NSObject)).unwrap();
decl.add_method(
sel!(outputVideoEffectDidStartForStream:),
output_video_effect_did_start_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(outputVideoEffectDidStopForStream:),
output_video_effect_did_stop_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(stream:didStopWithError:),
stream_did_stop_with_error as extern "C" fn(&Object, Sel, id, id),
);
DELEGATE_CLASS = decl.register();
unsafe {
decl.add_method(
sel!(outputVideoEffectDidStartForStream:),
output_video_effect_did_start_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(outputVideoEffectDidStopForStream:),
output_video_effect_did_stop_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(stream:didStopWithError:),
stream_did_stop_with_error as extern "C" fn(&Object, Sel, id, id),
);
DELEGATE_CLASS = decl.register();
let mut decl = ClassDecl::new("GPUIStreamOutput", class!(NSObject)).unwrap();
decl.add_method(
sel!(stream:didOutputSampleBuffer:ofType:),
stream_did_output_sample_buffer_of_type as extern "C" fn(&Object, Sel, id, id, NSInteger),
);
decl.add_ivar::<*mut c_void>(FRAME_CALLBACK_IVAR);
let mut decl = ClassDecl::new("GPUIStreamOutput", class!(NSObject)).unwrap();
decl.add_method(
sel!(stream:didOutputSampleBuffer:ofType:),
stream_did_output_sample_buffer_of_type
as extern "C" fn(&Object, Sel, id, id, NSInteger),
);
decl.add_ivar::<*mut c_void>(FRAME_CALLBACK_IVAR);
OUTPUT_CLASS = decl.register();
OUTPUT_CLASS = decl.register();
}
}
extern "C" fn output_video_effect_did_start_for_stream(_this: &Object, _: Sel, _stream: id) {}

View file

@ -664,9 +664,11 @@ mod lenient_font_attributes {
}
unsafe fn wrap_under_get_rule(reference: CFStringRef) -> CFString {
assert!(!reference.is_null(), "Attempted to create a NULL object.");
let reference = CFRetain(reference as *const ::std::os::raw::c_void) as CFStringRef;
TCFType::wrap_under_create_rule(reference)
unsafe {
assert!(!reference.is_null(), "Attempted to create a NULL object.");
let reference = CFRetain(reference as *const ::std::os::raw::c_void) as CFStringRef;
TCFType::wrap_under_create_rule(reference)
}
}
}

View file

@ -80,7 +80,7 @@ const NSDragOperationNone: NSDragOperation = 0;
const NSDragOperationCopy: NSDragOperation = 1;
#[link(name = "CoreGraphics", kind = "framework")]
extern "C" {
unsafe extern "C" {
// Widely used private APIs; Apple uses them for their Terminal.app.
fn CGSMainConnectionID() -> id;
fn CGSSetWindowBackgroundBlurRadius(
@ -92,152 +92,155 @@ extern "C" {
#[ctor]
unsafe fn build_classes() {
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
PANEL_CLASS = build_window_class("GPUIPanel", class!(NSPanel));
VIEW_CLASS = {
let mut decl = ClassDecl::new("GPUIView", class!(NSView)).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
unsafe {
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
PANEL_CLASS = build_window_class("GPUIPanel", class!(NSPanel));
VIEW_CLASS = {
let mut decl = ClassDecl::new("GPUIView", class!(NSView)).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
unsafe {
decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel));
decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(performKeyEquivalent:),
handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(keyDown:),
handle_key_down as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(keyUp:),
handle_key_up as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseMoved:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseExited:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDragged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(scrollWheel:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(swipeWithEvent:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(flagsChanged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(performKeyEquivalent:),
handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(keyDown:),
handle_key_down as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(keyUp:),
handle_key_up as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseMoved:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseExited:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDragged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(scrollWheel:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(swipeWithEvent:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(flagsChanged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(makeBackingLayer),
make_backing_layer as extern "C" fn(&Object, Sel) -> id,
);
decl.add_method(
sel!(makeBackingLayer),
make_backing_layer as extern "C" fn(&Object, Sel) -> id,
);
decl.add_protocol(Protocol::get("CALayerDelegate").unwrap());
decl.add_method(
sel!(viewDidChangeBackingProperties),
view_did_change_backing_properties as extern "C" fn(&Object, Sel),
);
decl.add_method(
sel!(setFrameSize:),
set_frame_size as extern "C" fn(&Object, Sel, NSSize),
);
decl.add_method(
sel!(displayLayer:),
display_layer as extern "C" fn(&Object, Sel, id),
);
decl.add_protocol(Protocol::get("CALayerDelegate").unwrap());
decl.add_method(
sel!(viewDidChangeBackingProperties),
view_did_change_backing_properties as extern "C" fn(&Object, Sel),
);
decl.add_method(
sel!(setFrameSize:),
set_frame_size as extern "C" fn(&Object, Sel, NSSize),
);
decl.add_method(
sel!(displayLayer:),
display_layer as extern "C" fn(&Object, Sel, id),
);
decl.add_protocol(Protocol::get("NSTextInputClient").unwrap());
decl.add_method(
sel!(validAttributesForMarkedText),
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
);
decl.add_method(
sel!(hasMarkedText),
has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(markedRange),
marked_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(selectedRange),
selected_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(firstRectForCharacterRange:actualRange:),
first_rect_for_character_range
as extern "C" fn(&Object, Sel, NSRange, id) -> NSRect,
);
decl.add_method(
sel!(insertText:replacementRange:),
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
);
decl.add_method(
sel!(setMarkedText:selectedRange:replacementRange:),
set_marked_text as extern "C" fn(&Object, Sel, id, NSRange, NSRange),
);
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(attributedSubstringForProposedRange:actualRange:),
attributed_substring_for_proposed_range
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
);
decl.add_method(
sel!(viewDidChangeEffectiveAppearance),
view_did_change_effective_appearance as extern "C" fn(&Object, Sel),
);
decl.add_protocol(Protocol::get("NSTextInputClient").unwrap());
decl.add_method(
sel!(validAttributesForMarkedText),
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
);
decl.add_method(
sel!(hasMarkedText),
has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(markedRange),
marked_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(selectedRange),
selected_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(firstRectForCharacterRange:actualRange:),
first_rect_for_character_range as extern "C" fn(&Object, Sel, NSRange, id) -> NSRect,
);
decl.add_method(
sel!(insertText:replacementRange:),
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
);
decl.add_method(
sel!(setMarkedText:selectedRange:replacementRange:),
set_marked_text as extern "C" fn(&Object, Sel, id, NSRange, NSRange),
);
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(attributedSubstringForProposedRange:actualRange:),
attributed_substring_for_proposed_range
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
);
decl.add_method(
sel!(viewDidChangeEffectiveAppearance),
view_did_change_effective_appearance as extern "C" fn(&Object, Sel),
);
// Suppress beep on keystrokes with modifier keys.
decl.add_method(
sel!(doCommandBySelector:),
do_command_by_selector as extern "C" fn(&Object, Sel, Sel),
);
// Suppress beep on keystrokes with modifier keys.
decl.add_method(
sel!(doCommandBySelector:),
do_command_by_selector as extern "C" fn(&Object, Sel, Sel),
);
decl.add_method(
sel!(acceptsFirstMouse:),
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(acceptsFirstMouse:),
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(characterIndexForPoint:),
character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> u64,
);
decl.register()
};
decl.add_method(
sel!(characterIndexForPoint:),
character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> u64,
);
}
decl.register()
};
}
}
pub(crate) fn convert_mouse_position(position: NSPoint, window_height: Pixels) -> Point<Pixels> {
@ -249,78 +252,81 @@ pub(crate) fn convert_mouse_position(position: NSPoint, window_height: Pixels) -
}
unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const Class {
let mut decl = ClassDecl::new(name, superclass).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
decl.add_method(sel!(dealloc), dealloc_window as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(canBecomeMainWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(canBecomeKeyWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(windowDidResize:),
window_did_resize as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeOcclusionState:),
window_did_change_occlusion_state as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillEnterFullScreen:),
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillExitFullScreen:),
window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidMove:),
window_did_move as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeScreen:),
window_did_change_screen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidBecomeKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidResignKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowShouldClose:),
window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,
);
unsafe {
let mut decl = ClassDecl::new(name, superclass).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
decl.add_method(sel!(dealloc), dealloc_window as extern "C" fn(&Object, Sel));
decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(canBecomeMainWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(canBecomeKeyWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(windowDidResize:),
window_did_resize as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeOcclusionState:),
window_did_change_occlusion_state as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillEnterFullScreen:),
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillExitFullScreen:),
window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidMove:),
window_did_move as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeScreen:),
window_did_change_screen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidBecomeKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidResignKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowShouldClose:),
window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(draggingEntered:),
dragging_entered as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingUpdated:),
dragging_updated as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingExited:),
dragging_exited as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(performDragOperation:),
perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(concludeDragOperation:),
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
);
decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel));
decl.register()
decl.add_method(
sel!(draggingEntered:),
dragging_entered as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingUpdated:),
dragging_updated as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingExited:),
dragging_exited as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(performDragOperation:),
perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(concludeDragOperation:),
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
);
decl.register()
}
}
struct MacWindowState {
@ -913,7 +919,7 @@ impl PlatformWindow for MacWindow {
.iter()
.enumerate()
.rev()
.find(|(_, &label)| label != "Cancel")
.find(|(_, label)| **label != "Cancel")
.filter(|&(label_index, _)| label_index > 0);
unsafe {
@ -1200,16 +1206,20 @@ fn get_scale_factor(native_window: id) -> f32 {
}
unsafe fn get_window_state(object: &Object) -> Arc<Mutex<MacWindowState>> {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
let rc1 = Arc::from_raw(raw as *mut Mutex<MacWindowState>);
let rc2 = rc1.clone();
mem::forget(rc1);
rc2
unsafe {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
let rc1 = Arc::from_raw(raw as *mut Mutex<MacWindowState>);
let rc2 = rc1.clone();
mem::forget(rc1);
rc2
}
}
unsafe fn drop_window_state(object: &Object) {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
Arc::from_raw(raw as *mut Mutex<MacWindowState>);
unsafe {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
Arc::from_raw(raw as *mut Mutex<MacWindowState>);
}
}
extern "C" fn yes(_: &Object, _: Sel) -> BOOL {
@ -2069,9 +2079,11 @@ where
}
unsafe fn display_id_for_screen(screen: id) -> CGDirectDisplayID {
let device_description = NSScreen::deviceDescription(screen);
let screen_number_key: id = NSString::alloc(nil).init_str("NSScreenNumber");
let screen_number = device_description.objectForKey_(screen_number_key);
let screen_number: NSUInteger = msg_send![screen_number, unsignedIntegerValue];
screen_number as CGDirectDisplayID
unsafe {
let device_description = NSScreen::deviceDescription(screen);
let screen_number_key: id = NSString::alloc(nil).init_str("NSScreenNumber");
let screen_number = device_description.objectForKey_(screen_number_key);
let screen_number: NSUInteger = msg_send![screen_number, unsignedIntegerValue];
screen_number as CGDirectDisplayID
}
}

View file

@ -10,26 +10,28 @@ use std::ffi::CStr;
impl WindowAppearance {
pub(crate) unsafe fn from_native(appearance: id) -> Self {
let name: id = msg_send![appearance, name];
if name == NSAppearanceNameVibrantLight {
Self::VibrantLight
} else if name == NSAppearanceNameVibrantDark {
Self::VibrantDark
} else if name == NSAppearanceNameAqua {
Self::Light
} else if name == NSAppearanceNameDarkAqua {
Self::Dark
} else {
println!(
"unknown appearance: {:?}",
CStr::from_ptr(name.UTF8String())
);
Self::Light
unsafe {
if name == NSAppearanceNameVibrantLight {
Self::VibrantLight
} else if name == NSAppearanceNameVibrantDark {
Self::VibrantDark
} else if name == NSAppearanceNameAqua {
Self::Light
} else if name == NSAppearanceNameDarkAqua {
Self::Dark
} else {
println!(
"unknown appearance: {:?}",
CStr::from_ptr(name.UTF8String())
);
Self::Light
}
}
}
}
#[link(name = "AppKit", kind = "framework")]
extern "C" {
unsafe extern "C" {
pub static NSAppearanceNameAqua: id;
pub static NSAppearanceNameDarkAqua: id;
}

View file

@ -89,7 +89,7 @@ impl TestDispatcher {
self.state.lock().time = new_now;
}
pub fn simulate_random_delay(&self) -> impl 'static + Send + Future<Output = ()> {
pub fn simulate_random_delay(&self) -> impl 'static + Send + Future<Output = ()> + use<> {
struct YieldNow {
pub(crate) count: usize,
}

View file

@ -333,7 +333,7 @@ impl DirectWriteState {
&self,
font_features: &FontFeatures,
) -> Result<IDWriteTypography> {
let direct_write_features = self.components.factory.CreateTypography()?;
let direct_write_features = unsafe { self.components.factory.CreateTypography()? };
apply_font_features(&direct_write_features, font_features)?;
Ok(direct_write_features)
}
@ -352,28 +352,32 @@ impl DirectWriteState {
} else {
&self.custom_font_collection
};
let fontset = collection.GetFontSet().log_err()?;
let font = fontset
.GetMatchingFonts(
&HSTRING::from(family_name),
font_weight.into(),
DWRITE_FONT_STRETCH_NORMAL,
font_style.into(),
)
.log_err()?;
let total_number = font.GetFontCount();
let fontset = unsafe { collection.GetFontSet().log_err()? };
let font = unsafe {
fontset
.GetMatchingFonts(
&HSTRING::from(family_name),
font_weight.into(),
DWRITE_FONT_STRETCH_NORMAL,
font_style.into(),
)
.log_err()?
};
let total_number = unsafe { font.GetFontCount() };
for index in 0..total_number {
let Some(font_face_ref) = font.GetFontFaceReference(index).log_err() else {
let Some(font_face_ref) = (unsafe { font.GetFontFaceReference(index).log_err() })
else {
continue;
};
let Some(font_face) = font_face_ref.CreateFontFace().log_err() else {
let Some(font_face) = (unsafe { font_face_ref.CreateFontFace().log_err() }) else {
continue;
};
let Some(identifier) = get_font_identifier(&font_face, &self.components.locale) else {
continue;
};
let is_emoji = font_face.IsColorFont().as_bool();
let Some(direct_write_features) = self.generate_font_features(font_features).log_err()
let is_emoji = unsafe { font_face.IsColorFont().as_bool() };
let Some(direct_write_features) =
(unsafe { self.generate_font_features(font_features).log_err() })
else {
continue;
};
@ -396,14 +400,14 @@ impl DirectWriteState {
}
unsafe fn update_system_font_collection(&mut self) {
let mut collection = std::mem::zeroed();
if self
.components
.factory
.GetSystemFontCollection(false, &mut collection, true)
.log_err()
.is_some()
{
let mut collection = unsafe { std::mem::zeroed() };
if unsafe {
self.components
.factory
.GetSystemFontCollection(false, &mut collection, true)
.log_err()
.is_some()
} {
self.system_font_collection = collection.unwrap();
}
}
@ -461,35 +465,37 @@ impl DirectWriteState {
fallbacks: Option<&FontFallbacks>,
) -> Option<FontId> {
// try to find target font in custom font collection first
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
false,
)
.or_else(|| {
unsafe {
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
false,
)
})
.or_else(|| {
self.update_system_font_collection();
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
)
})
.or_else(|| {
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
)
})
.or_else(|| {
self.update_system_font_collection();
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
)
})
}
}
fn layout_line(

View file

@ -27,8 +27,8 @@ impl JsonSchema for SharedString {
String::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
String::json_schema(gen)
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
String::json_schema(r#gen)
}
}

View file

@ -45,7 +45,7 @@ where
&self,
emitter_key: EmitterKey,
callback: Callback,
) -> (Subscription, impl FnOnce()) {
) -> (Subscription, impl FnOnce() + use<EmitterKey, Callback>) {
let active = Rc::new(Cell::new(false));
let mut lock = self.0.lock();
let subscriber_id = post_inc(&mut lock.next_subscriber_id);
@ -88,7 +88,10 @@ where
(subscription, move || active.set(true))
}
pub fn remove(&self, emitter: &EmitterKey) -> impl IntoIterator<Item = Callback> {
pub fn remove(
&self,
emitter: &EmitterKey,
) -> impl IntoIterator<Item = Callback> + use<EmitterKey, Callback> {
let subscribers = self.0.lock().subscribers.remove(emitter);
subscribers
.unwrap_or_default()

View file

@ -133,7 +133,7 @@ impl schemars::JsonSchema for FontFeatures {
"FontFeatures".into()
}
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
let mut schema = SchemaObject::default();
schema.instance_type = Some(schemars::schema::SingleOrVec::Single(Box::new(
InstanceType::Object,

View file

@ -936,7 +936,7 @@ impl Window {
pub(crate) fn new_focus_listener(
&self,
value: AnyWindowFocusListener,
) -> (Subscription, impl FnOnce()) {
) -> (Subscription, impl FnOnce() + use<>) {
self.focus_listeners.insert((), value)
}
}
@ -3719,11 +3719,11 @@ impl Window {
}
/// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.
pub fn handler_for<V: Render>(
pub fn handler_for<V: Render, Callback: Fn(&mut V, &mut Window, &mut Context<V>) + 'static>(
&self,
view: &Entity<V>,
f: impl Fn(&mut V, &mut Window, &mut Context<V>) + 'static,
) -> impl Fn(&mut Window, &mut App) {
f: Callback,
) -> impl Fn(&mut Window, &mut App) + use<V, Callback> {
let view = view.downgrade();
move |window: &mut Window, cx: &mut App| {
view.update(cx, |view, cx| f(view, window, cx)).ok();