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:
parent
d51aa2ffb0
commit
0729d24d77
162 changed files with 2333 additions and 1937 deletions
443
Cargo.lock
generated
443
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1412,7 +1412,11 @@ impl ActiveThread {
|
|||
)
|
||||
}
|
||||
|
||||
fn render_tool_use(&self, tool_use: ToolUse, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render_tool_use(
|
||||
&self,
|
||||
tool_use: ToolUse,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl IntoElement + use<> {
|
||||
let is_open = self
|
||||
.expanded_tool_uses
|
||||
.get(&tool_use.id)
|
||||
|
|
|
@ -105,7 +105,7 @@ impl AssistantConfiguration {
|
|||
&mut self,
|
||||
provider: &Arc<dyn LanguageModelProvider>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl IntoElement {
|
||||
) -> impl IntoElement + use<> {
|
||||
let provider_id = provider.id().0.clone();
|
||||
let provider_name = provider.name().0.clone();
|
||||
let configuration_view = self
|
||||
|
|
|
@ -687,7 +687,7 @@ pub fn refresh_context_store_text(
|
|||
context_store: Entity<ContextStore>,
|
||||
changed_buffers: &HashSet<Entity<Buffer>>,
|
||||
cx: &App,
|
||||
) -> impl Future<Output = Vec<ContextId>> {
|
||||
) -> impl Future<Output = Vec<ContextId>> + use<> {
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
for context in &context_store.read(cx).context {
|
||||
|
@ -855,7 +855,7 @@ fn refresh_thread_text(
|
|||
fn refresh_context_buffer(
|
||||
context_buffer: &ContextBuffer,
|
||||
cx: &App,
|
||||
) -> Option<impl Future<Output = ContextBuffer>> {
|
||||
) -> Option<impl Future<Output = ContextBuffer> + use<>> {
|
||||
let buffer = context_buffer.buffer.read(cx);
|
||||
let path = buffer_path_log_err(buffer)?;
|
||||
if buffer.version.changed_since(&context_buffer.version) {
|
||||
|
@ -875,7 +875,7 @@ fn refresh_context_buffer(
|
|||
fn refresh_context_symbol(
|
||||
context_symbol: &ContextSymbol,
|
||||
cx: &App,
|
||||
) -> Option<impl Future<Output = ContextSymbol>> {
|
||||
) -> Option<impl Future<Output = ContextSymbol> + use<>> {
|
||||
let buffer = context_symbol.buffer.read(cx);
|
||||
let path = buffer_path_log_err(buffer)?;
|
||||
let project_path = buffer.project_path(cx)?;
|
||||
|
|
|
@ -1192,7 +1192,7 @@ impl Thread {
|
|||
pub fn use_pending_tools(
|
||||
&mut self,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl IntoIterator<Item = PendingToolUse> {
|
||||
) -> impl IntoIterator<Item = PendingToolUse> + use<> {
|
||||
let request = self.to_completion_request(RequestKind::Chat, cx);
|
||||
let messages = Arc::new(request.messages);
|
||||
let pending_tool_uses = self
|
||||
|
|
|
@ -3413,7 +3413,7 @@ impl ContextEditorToolbarItem {
|
|||
pub fn render_remaining_tokens(
|
||||
context_editor: &Entity<ContextEditor>,
|
||||
cx: &App,
|
||||
) -> Option<impl IntoElement> {
|
||||
) -> Option<impl IntoElement + use<>> {
|
||||
let context = &context_editor.read(cx).context;
|
||||
|
||||
let (token_count_color, token_count, max_token_count, tooltip) = match token_state(context, cx)?
|
||||
|
|
|
@ -105,8 +105,8 @@ impl JsonSchema for AssistantSettingsContent {
|
|||
VersionedAssistantSettingsContent::schema_name()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> Schema {
|
||||
VersionedAssistantSettingsContent::json_schema(gen)
|
||||
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> Schema {
|
||||
VersionedAssistantSettingsContent::json_schema(r#gen)
|
||||
}
|
||||
|
||||
fn is_referenceable() -> bool {
|
||||
|
@ -416,7 +416,7 @@ pub struct LanguageModelSelection {
|
|||
pub model: String,
|
||||
}
|
||||
|
||||
fn providers_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
fn providers_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
schemars::schema::SchemaObject {
|
||||
enum_values: Some(vec![
|
||||
"anthropic".into(),
|
||||
|
|
|
@ -221,7 +221,7 @@ fn collect_files(
|
|||
project: Entity<Project>,
|
||||
glob_inputs: &[String],
|
||||
cx: &mut App,
|
||||
) -> impl Stream<Item = Result<SlashCommandEvent>> {
|
||||
) -> impl Stream<Item = Result<SlashCommandEvent>> + use<> {
|
||||
let Ok(matchers) = glob_inputs
|
||||
.into_iter()
|
||||
.map(|glob_input| {
|
||||
|
@ -782,7 +782,12 @@ mod test {
|
|||
assert_eq!(result.sections[6].label, "summercamp");
|
||||
assert_eq!(result.sections[7].label, separator!("zed/assets/themes"));
|
||||
|
||||
assert_eq!(result.text, separator!("zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n"));
|
||||
assert_eq!(
|
||||
result.text,
|
||||
separator!(
|
||||
"zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n"
|
||||
)
|
||||
);
|
||||
|
||||
// Ensure that the project lasts until after the last await
|
||||
drop(project);
|
||||
|
|
|
@ -81,7 +81,9 @@ impl Tool for BashTool {
|
|||
};
|
||||
|
||||
if worktrees.next().is_some() {
|
||||
return Task::ready(Err(anyhow!("'.' is ambiguous in multi-root workspaces. Please specify a root directory explicitly.")));
|
||||
return Task::ready(Err(anyhow!(
|
||||
"'.' is ambiguous in multi-root workspaces. Please specify a root directory explicitly."
|
||||
)));
|
||||
}
|
||||
|
||||
only_worktree.read(cx).abs_path()
|
||||
|
|
|
@ -526,7 +526,8 @@ impl EditToolRequest {
|
|||
}
|
||||
}
|
||||
|
||||
write!(&mut output,
|
||||
write!(
|
||||
&mut output,
|
||||
"The SEARCH section must exactly match an existing block of lines including all white \
|
||||
space, comments, indentation, docstrings, etc."
|
||||
)?;
|
||||
|
@ -545,7 +546,8 @@ impl EditToolRequest {
|
|||
}
|
||||
|
||||
if has_errors {
|
||||
writeln!(&mut output,
|
||||
writeln!(
|
||||
&mut output,
|
||||
"\n\nYou can fix errors by running the tool again. You can include instructions, \
|
||||
but errors are part of the conversation so you don't need to repeat them.",
|
||||
)?;
|
||||
|
|
|
@ -35,7 +35,7 @@ impl SoundRegistry {
|
|||
cx.set_global(GlobalSoundRegistry(SoundRegistry::new(source)));
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> Result<impl Source<Item = f32>> {
|
||||
pub fn get(&self, name: &str) -> Result<impl Source<Item = f32> + use<>> {
|
||||
if let Some(wav) = self.cache.lock().get(name) {
|
||||
return Ok(wav.clone());
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ impl AwsConnector for AwsHttpConnector {
|
|||
let req = match request.try_into_http1x() {
|
||||
Ok(req) => req,
|
||||
Err(err) => {
|
||||
return HttpConnectorFuture::ready(Err(ConnectorError::other(err.into(), None)))
|
||||
return HttpConnectorFuture::ready(Err(ConnectorError::other(err.into(), None)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -433,79 +433,82 @@ impl BufferDiffInner {
|
|||
|
||||
let max_point = buffer.max_point();
|
||||
let mut summaries = buffer.summaries_for_anchors_with_payload::<Point, _, _>(anchor_iter);
|
||||
iter::from_fn(move || loop {
|
||||
let (start_point, (start_anchor, start_base)) = summaries.next()?;
|
||||
let (mut end_point, (mut end_anchor, end_base)) = summaries.next()?;
|
||||
iter::from_fn(move || {
|
||||
loop {
|
||||
let (start_point, (start_anchor, start_base)) = summaries.next()?;
|
||||
let (mut end_point, (mut end_anchor, end_base)) = summaries.next()?;
|
||||
|
||||
if !start_anchor.is_valid(buffer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if end_point.column > 0 && end_point < max_point {
|
||||
end_point.row += 1;
|
||||
end_point.column = 0;
|
||||
end_anchor = buffer.anchor_before(end_point);
|
||||
}
|
||||
|
||||
let mut secondary_status = DiffHunkSecondaryStatus::NoSecondaryHunk;
|
||||
|
||||
let mut has_pending = false;
|
||||
if start_anchor
|
||||
.cmp(&pending_hunks_cursor.start().buffer_range.start, buffer)
|
||||
.is_gt()
|
||||
{
|
||||
pending_hunks_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
|
||||
}
|
||||
|
||||
if let Some(pending_hunk) = pending_hunks_cursor.item() {
|
||||
let mut pending_range = pending_hunk.buffer_range.to_point(buffer);
|
||||
if pending_range.end.column > 0 {
|
||||
pending_range.end.row += 1;
|
||||
pending_range.end.column = 0;
|
||||
if !start_anchor.is_valid(buffer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if pending_range == (start_point..end_point) {
|
||||
if !buffer.has_edits_since_in_range(
|
||||
&pending_hunk.buffer_version,
|
||||
start_anchor..end_anchor,
|
||||
) {
|
||||
has_pending = true;
|
||||
secondary_status = pending_hunk.new_status;
|
||||
}
|
||||
if end_point.column > 0 && end_point < max_point {
|
||||
end_point.row += 1;
|
||||
end_point.column = 0;
|
||||
end_anchor = buffer.anchor_before(end_point);
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(secondary_cursor), false) = (secondary_cursor.as_mut(), has_pending) {
|
||||
let mut secondary_status = DiffHunkSecondaryStatus::NoSecondaryHunk;
|
||||
|
||||
let mut has_pending = false;
|
||||
if start_anchor
|
||||
.cmp(&secondary_cursor.start().buffer_range.start, buffer)
|
||||
.cmp(&pending_hunks_cursor.start().buffer_range.start, buffer)
|
||||
.is_gt()
|
||||
{
|
||||
secondary_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
|
||||
pending_hunks_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
|
||||
}
|
||||
|
||||
if let Some(secondary_hunk) = secondary_cursor.item() {
|
||||
let mut secondary_range = secondary_hunk.buffer_range.to_point(buffer);
|
||||
if secondary_range.end.column > 0 {
|
||||
secondary_range.end.row += 1;
|
||||
secondary_range.end.column = 0;
|
||||
if let Some(pending_hunk) = pending_hunks_cursor.item() {
|
||||
let mut pending_range = pending_hunk.buffer_range.to_point(buffer);
|
||||
if pending_range.end.column > 0 {
|
||||
pending_range.end.row += 1;
|
||||
pending_range.end.column = 0;
|
||||
}
|
||||
if secondary_range.is_empty() && secondary_hunk.diff_base_byte_range.is_empty()
|
||||
|
||||
if pending_range == (start_point..end_point) {
|
||||
if !buffer.has_edits_since_in_range(
|
||||
&pending_hunk.buffer_version,
|
||||
start_anchor..end_anchor,
|
||||
) {
|
||||
has_pending = true;
|
||||
secondary_status = pending_hunk.new_status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(secondary_cursor), false) = (secondary_cursor.as_mut(), has_pending) {
|
||||
if start_anchor
|
||||
.cmp(&secondary_cursor.start().buffer_range.start, buffer)
|
||||
.is_gt()
|
||||
{
|
||||
// ignore
|
||||
} else if secondary_range == (start_point..end_point) {
|
||||
secondary_status = DiffHunkSecondaryStatus::HasSecondaryHunk;
|
||||
} else if secondary_range.start <= end_point {
|
||||
secondary_status = DiffHunkSecondaryStatus::OverlapsWithSecondaryHunk;
|
||||
secondary_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
|
||||
}
|
||||
|
||||
if let Some(secondary_hunk) = secondary_cursor.item() {
|
||||
let mut secondary_range = secondary_hunk.buffer_range.to_point(buffer);
|
||||
if secondary_range.end.column > 0 {
|
||||
secondary_range.end.row += 1;
|
||||
secondary_range.end.column = 0;
|
||||
}
|
||||
if secondary_range.is_empty()
|
||||
&& secondary_hunk.diff_base_byte_range.is_empty()
|
||||
{
|
||||
// ignore
|
||||
} else if secondary_range == (start_point..end_point) {
|
||||
secondary_status = DiffHunkSecondaryStatus::HasSecondaryHunk;
|
||||
} else if secondary_range.start <= end_point {
|
||||
secondary_status = DiffHunkSecondaryStatus::OverlapsWithSecondaryHunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Some(DiffHunk {
|
||||
range: start_point..end_point,
|
||||
diff_base_byte_range: start_base..end_base,
|
||||
buffer_range: start_anchor..end_anchor,
|
||||
secondary_status,
|
||||
});
|
||||
return Some(DiffHunk {
|
||||
range: start_point..end_point,
|
||||
diff_base_byte_range: start_base..end_base,
|
||||
buffer_range: start_anchor..end_anchor,
|
||||
secondary_status,
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -776,7 +779,7 @@ impl BufferDiff {
|
|||
language: Option<Arc<Language>>,
|
||||
language_registry: Option<Arc<LanguageRegistry>>,
|
||||
cx: &mut App,
|
||||
) -> impl Future<Output = BufferDiffInner> {
|
||||
) -> impl Future<Output = BufferDiffInner> + use<> {
|
||||
let base_text_pair;
|
||||
let base_text_exists;
|
||||
let base_text_snapshot;
|
||||
|
@ -818,7 +821,7 @@ impl BufferDiff {
|
|||
base_text: Option<Arc<String>>,
|
||||
base_text_snapshot: language::BufferSnapshot,
|
||||
cx: &App,
|
||||
) -> impl Future<Output = BufferDiffInner> {
|
||||
) -> impl Future<Output = BufferDiffInner> + use<> {
|
||||
let base_text_exists = base_text.is_some();
|
||||
let base_text_pair = base_text.map(|text| (text, base_text_snapshot.as_rope().clone()));
|
||||
cx.background_spawn(async move {
|
||||
|
@ -2071,7 +2074,7 @@ mod tests {
|
|||
)
|
||||
});
|
||||
let working_copy = working_copy.read_with(cx, |working_copy, _| working_copy.snapshot());
|
||||
let mut index_text = if rng.gen() {
|
||||
let mut index_text = if rng.r#gen() {
|
||||
Rope::from(head_text.as_str())
|
||||
} else {
|
||||
working_copy.as_rope().clone()
|
||||
|
|
|
@ -243,7 +243,7 @@ impl Room {
|
|||
}
|
||||
}
|
||||
|
||||
fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
|
||||
fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> + use<> {
|
||||
let task = if self.status.is_online() {
|
||||
let leave = self.leave_internal(cx);
|
||||
Some(cx.background_spawn(async move {
|
||||
|
@ -665,7 +665,7 @@ impl Room {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn room_update_completed(&mut self) -> impl Future<Output = ()> {
|
||||
pub fn room_update_completed(&mut self) -> impl Future<Output = ()> + use<> {
|
||||
let mut done_rx = self.room_update_completed_rx.clone();
|
||||
async move {
|
||||
while let Some(result) = done_rx.next().await {
|
||||
|
|
|
@ -183,7 +183,7 @@ impl ChannelChat {
|
|||
|
||||
let channel_id = self.channel_id;
|
||||
let pending_id = ChannelMessageId::Pending(post_inc(&mut self.next_pending_message_id));
|
||||
let nonce = self.rng.gen();
|
||||
let nonce = self.rng.r#gen();
|
||||
self.insert_messages(
|
||||
SumTree::from_item(
|
||||
ChannelMessage {
|
||||
|
@ -257,7 +257,7 @@ impl ChannelChat {
|
|||
cx,
|
||||
);
|
||||
|
||||
let nonce: u128 = self.rng.gen();
|
||||
let nonce: u128 = self.rng.r#gen();
|
||||
|
||||
let request = self.rpc.request(proto::UpdateChannelMessage {
|
||||
channel_id: self.channel_id.0,
|
||||
|
|
|
@ -824,7 +824,10 @@ impl ChannelStore {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn remove_channel(&self, channel_id: ChannelId) -> impl Future<Output = Result<()>> {
|
||||
pub fn remove_channel(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
) -> impl Future<Output = Result<()>> + use<> {
|
||||
let client = self.client.clone();
|
||||
async move {
|
||||
client
|
||||
|
|
|
@ -465,7 +465,7 @@ mod linux {
|
|||
match fork::fork() {
|
||||
Ok(Fork::Parent(_)) => Ok(()),
|
||||
Ok(Fork::Child) => {
|
||||
std::env::set_var(FORCE_CLI_MODE_ENV_VAR_NAME, "");
|
||||
unsafe { std::env::set_var(FORCE_CLI_MODE_ENV_VAR_NAME, "") };
|
||||
if let Err(_) = fork::setsid() {
|
||||
eprintln!("failed to setsid: {}", std::io::Error::last_os_error());
|
||||
process::exit(1);
|
||||
|
@ -521,7 +521,7 @@ mod flatpak {
|
|||
paths.push(extra_path.into());
|
||||
}
|
||||
|
||||
env::set_var("LD_LIBRARY_PATH", env::join_paths(paths).unwrap());
|
||||
unsafe { env::set_var("LD_LIBRARY_PATH", env::join_paths(paths).unwrap()) };
|
||||
}
|
||||
|
||||
/// Restarts outside of the sandbox if currently running within it
|
||||
|
@ -562,7 +562,9 @@ mod flatpak {
|
|||
{
|
||||
if args.zed.is_none() {
|
||||
args.zed = Some("/app/libexec/zed-editor".into());
|
||||
env::set_var("ZED_UPDATE_EXPLANATION", "Please use flatpak to update zed");
|
||||
unsafe {
|
||||
env::set_var("ZED_UPDATE_EXPLANATION", "Please use flatpak to update zed")
|
||||
};
|
||||
}
|
||||
}
|
||||
args
|
||||
|
|
|
@ -817,7 +817,7 @@ impl Client {
|
|||
| Status::Reauthenticating { .. }
|
||||
| Status::ReconnectionError { .. } => false,
|
||||
Status::Connected { .. } | Status::Connecting { .. } | Status::Reconnecting { .. } => {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
}
|
||||
Status::UpgradeRequired => return Err(EstablishConnectionError::UpgradeRequired)?,
|
||||
};
|
||||
|
@ -1024,7 +1024,7 @@ impl Client {
|
|||
&self,
|
||||
http: Arc<HttpClientWithUrl>,
|
||||
release_channel: Option<ReleaseChannel>,
|
||||
) -> impl Future<Output = Result<url::Url>> {
|
||||
) -> impl Future<Output = Result<url::Url>> + use<> {
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
let url_override = self.rpc_url.read().clone();
|
||||
|
||||
|
@ -1444,7 +1444,7 @@ impl Client {
|
|||
pub fn request<T: RequestMessage>(
|
||||
&self,
|
||||
request: T,
|
||||
) -> impl Future<Output = Result<T::Response>> {
|
||||
) -> impl Future<Output = Result<T::Response>> + use<T> {
|
||||
self.request_envelope(request)
|
||||
.map_ok(|envelope| envelope.payload)
|
||||
}
|
||||
|
@ -1476,7 +1476,7 @@ impl Client {
|
|||
pub fn request_envelope<T: RequestMessage>(
|
||||
&self,
|
||||
request: T,
|
||||
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> {
|
||||
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> + use<T> {
|
||||
let client_id = self.id();
|
||||
log::debug!(
|
||||
"rpc request start. client_id:{}. name:{}",
|
||||
|
@ -1501,7 +1501,7 @@ impl Client {
|
|||
&self,
|
||||
envelope: proto::Envelope,
|
||||
request_type: &'static str,
|
||||
) -> impl Future<Output = Result<proto::Envelope>> {
|
||||
) -> impl Future<Output = Result<proto::Envelope>> + use<> {
|
||||
let client_id = self.id();
|
||||
log::debug!(
|
||||
"rpc request start. client_id:{}. name:{}",
|
||||
|
|
|
@ -273,14 +273,14 @@ impl Telemetry {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> {
|
||||
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> + use<> {
|
||||
Task::ready(())
|
||||
}
|
||||
|
||||
// Skip calling this function in tests.
|
||||
// TestAppContext ends up calling this function on shutdown and it panics when trying to find the TelemetrySettings
|
||||
#[cfg(not(any(test, feature = "test-support")))]
|
||||
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> {
|
||||
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> + use<> {
|
||||
telemetry::event!("App Closed");
|
||||
// TODO: close final edit period and make sure it's sent
|
||||
Task::ready(())
|
||||
|
|
|
@ -581,7 +581,7 @@ impl UserStore {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn clear_contacts(&self) -> impl Future<Output = ()> {
|
||||
pub fn clear_contacts(&self) -> impl Future<Output = ()> + use<> {
|
||||
let (tx, mut rx) = postage::barrier::channel();
|
||||
self.update_contacts_tx
|
||||
.unbounded_send(UpdateContacts::Clear(tx))
|
||||
|
|
|
@ -534,7 +534,9 @@ async fn poll_stripe_events(
|
|||
if event_pages.page.has_more {
|
||||
if pages_of_already_processed_events >= NUMBER_OF_ALREADY_PROCESSED_PAGES_BEFORE_WE_STOP
|
||||
{
|
||||
log::info!("Stripe events: stopping, saw {pages_of_already_processed_events} pages of already-processed events");
|
||||
log::info!(
|
||||
"Stripe events: stopping, saw {pages_of_already_processed_events} pages of already-processed events"
|
||||
);
|
||||
break;
|
||||
} else {
|
||||
log::info!("Stripe events: retrieving next page");
|
||||
|
|
|
@ -853,7 +853,7 @@ fn db_status_to_proto(
|
|||
_ => {
|
||||
return Err(anyhow!(
|
||||
"Unexpected combination of status fields: {entry:?}"
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
Ok(proto::StatusEntry {
|
||||
|
|
|
@ -74,7 +74,7 @@ impl TestDb {
|
|||
let mut rng = StdRng::from_entropy();
|
||||
let url = format!(
|
||||
"postgres://postgres@localhost/zed-test-{}",
|
||||
rng.gen::<u128>()
|
||||
rng.r#gen::<u128>()
|
||||
);
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn get_dotenv_vars(current_dir: impl AsRef<Path>) -> Result<Vec<(String, Str
|
|||
|
||||
pub fn load_dotenv() -> Result<()> {
|
||||
for (key, value) in get_dotenv_vars("./crates/collab")? {
|
||||
std::env::set_var(key, value);
|
||||
unsafe { std::env::set_var(key, value) };
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ impl Executor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn sleep(&self, duration: Duration) -> impl Future<Output = ()> {
|
||||
pub fn sleep(&self, duration: Duration) -> impl Future<Output = ()> + use<> {
|
||||
let this = self.clone();
|
||||
async move {
|
||||
match this {
|
||||
|
|
|
@ -193,7 +193,9 @@ mod tests {
|
|||
.to_vec();
|
||||
assert_eq!(
|
||||
String::from_utf8(response_body).unwrap(),
|
||||
format!("access to {provider:?} models is not available in your region ({country_code})")
|
||||
format!(
|
||||
"access to {provider:?} models is not available in your region ({country_code})"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ impl TestLlmDb {
|
|||
let mut rng = StdRng::from_entropy();
|
||||
let url = format!(
|
||||
"postgres://postgres@localhost/zed-llm-test-{}",
|
||||
rng.gen::<u128>()
|
||||
rng.r#gen::<u128>()
|
||||
);
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
|
|
|
@ -724,7 +724,7 @@ impl Server {
|
|||
system_id: Option<String>,
|
||||
send_connection_id: Option<oneshot::Sender<ConnectionId>>,
|
||||
executor: Executor,
|
||||
) -> impl Future<Output = ()> {
|
||||
) -> impl Future<Output = ()> + use<> {
|
||||
let this = self.clone();
|
||||
let span = info_span!("handle connection", %address,
|
||||
connection_id=field::Empty,
|
||||
|
|
|
@ -5103,7 +5103,9 @@ async fn test_project_search(
|
|||
results.entry(buffer).or_insert(ranges);
|
||||
}
|
||||
SearchResult::LimitReached => {
|
||||
panic!("Unexpectedly reached search limit in tests. If you do want to assert limit-reached, change this panic call.")
|
||||
panic!(
|
||||
"Unexpectedly reached search limit in tests. If you do want to assert limit-reached, change this panic call."
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -5602,7 +5604,7 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it(
|
|||
|
||||
let definitions;
|
||||
let buffer_b2;
|
||||
if rng.gen() {
|
||||
if rng.r#gen() {
|
||||
definitions = project_b.update(cx_b, |p, cx| p.definition(&buffer_b1, 23, cx));
|
||||
(buffer_b2, _) = project_b
|
||||
.update(cx_b, |p, cx| {
|
||||
|
|
|
@ -279,7 +279,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
let project_root_name = root_name_for_project(&project, cx);
|
||||
let mut paths = client.fs().paths(false);
|
||||
paths.remove(0);
|
||||
let new_root_path = if paths.is_empty() || rng.gen() {
|
||||
let new_root_path = if paths.is_empty() || rng.r#gen() {
|
||||
Path::new(path!("/")).join(plan.next_root_dir_name())
|
||||
} else {
|
||||
paths.choose(rng).unwrap().clone()
|
||||
|
@ -309,7 +309,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
.choose(rng)
|
||||
});
|
||||
let Some(worktree) = worktree else { continue };
|
||||
let is_dir = rng.gen::<bool>();
|
||||
let is_dir = rng.r#gen::<bool>();
|
||||
let mut full_path =
|
||||
worktree.read_with(cx, |w, _| PathBuf::from(w.root_name()));
|
||||
full_path.push(gen_file_name(rng));
|
||||
|
@ -387,7 +387,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
language::Bias::Left,
|
||||
)
|
||||
});
|
||||
let detach = rng.gen();
|
||||
let detach = rng.r#gen();
|
||||
break ClientOperation::RequestLspDataInBuffer {
|
||||
project_root_name,
|
||||
full_path,
|
||||
|
@ -460,7 +460,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
|
||||
// Create or update a file or directory
|
||||
96.. => {
|
||||
let is_dir = rng.gen::<bool>();
|
||||
let is_dir = rng.r#gen::<bool>();
|
||||
let content;
|
||||
let mut path;
|
||||
let dir_paths = client.fs().directories(false);
|
||||
|
@ -1315,7 +1315,9 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
match (host_file, guest_file) {
|
||||
(Some(host_file), Some(guest_file)) => {
|
||||
assert_eq!(guest_file.path(), host_file.path());
|
||||
assert_eq!(guest_file.disk_state(), host_file.disk_state(),
|
||||
assert_eq!(
|
||||
guest_file.disk_state(),
|
||||
host_file.disk_state(),
|
||||
"guest {} disk_state does not match host {} for path {:?} in project {}",
|
||||
guest_user_id,
|
||||
host_user_id,
|
||||
|
@ -1347,52 +1349,54 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
.base_text_string()
|
||||
});
|
||||
assert_eq!(
|
||||
guest_diff_base, host_diff_base,
|
||||
"guest {} diff base does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
guest_diff_base, host_diff_base,
|
||||
"guest {} diff base does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
|
||||
let host_saved_version =
|
||||
host_buffer.read_with(host_cx, |b, _| b.saved_version().clone());
|
||||
let guest_saved_version =
|
||||
guest_buffer.read_with(client_cx, |b, _| b.saved_version().clone());
|
||||
assert_eq!(
|
||||
guest_saved_version, host_saved_version,
|
||||
"guest {} saved version does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
guest_saved_version, host_saved_version,
|
||||
"guest {} saved version does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
|
||||
let host_is_dirty = host_buffer.read_with(host_cx, |b, _| b.is_dirty());
|
||||
let guest_is_dirty = guest_buffer.read_with(client_cx, |b, _| b.is_dirty());
|
||||
assert_eq!(
|
||||
guest_is_dirty, host_is_dirty,
|
||||
"guest {} dirty state does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
guest_is_dirty, host_is_dirty,
|
||||
"guest {} dirty state does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
|
||||
let host_saved_mtime = host_buffer.read_with(host_cx, |b, _| b.saved_mtime());
|
||||
let guest_saved_mtime =
|
||||
guest_buffer.read_with(client_cx, |b, _| b.saved_mtime());
|
||||
assert_eq!(
|
||||
guest_saved_mtime, host_saved_mtime,
|
||||
"guest {} saved mtime does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
guest_saved_mtime, host_saved_mtime,
|
||||
"guest {} saved mtime does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
|
||||
let host_is_dirty = host_buffer.read_with(host_cx, |b, _| b.is_dirty());
|
||||
let guest_is_dirty = guest_buffer.read_with(client_cx, |b, _| b.is_dirty());
|
||||
assert_eq!(guest_is_dirty, host_is_dirty,
|
||||
"guest {} dirty status does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
assert_eq!(
|
||||
guest_is_dirty, host_is_dirty,
|
||||
"guest {} dirty status does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
|
||||
let host_has_conflict = host_buffer.read_with(host_cx, |b, _| b.has_conflict());
|
||||
let guest_has_conflict =
|
||||
guest_buffer.read_with(client_cx, |b, _| b.has_conflict());
|
||||
assert_eq!(guest_has_conflict, host_has_conflict,
|
||||
"guest {} conflict status does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
assert_eq!(
|
||||
guest_has_conflict, host_has_conflict,
|
||||
"guest {} conflict status does not match host's for path {path:?} in project {project_id}",
|
||||
client.username
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -332,7 +332,7 @@ impl ChatPanel {
|
|||
.color(Color::Muted),
|
||||
)
|
||||
}),
|
||||
)
|
||||
);
|
||||
}
|
||||
Some(val) => val,
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ fn normalize_query(input: &str) -> String {
|
|||
match (last_char, char) {
|
||||
(Some(':'), ':') => continue,
|
||||
(Some(last_char), char) if last_char.is_whitespace() && char.is_whitespace() => {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
last_char = Some(char);
|
||||
|
|
|
@ -158,7 +158,7 @@ pub fn components() -> AllComponents {
|
|||
let data = COMPONENT_DATA.read();
|
||||
let mut all_components = AllComponents::new();
|
||||
|
||||
for (ref scope, name, description) in &data.components {
|
||||
for (scope, name, description) in &data.components {
|
||||
let preview = data.previews.get(name).cloned();
|
||||
let component_name = SharedString::new_static(name);
|
||||
let id = ComponentId(name);
|
||||
|
|
|
@ -244,7 +244,7 @@ impl ComponentPreview {
|
|||
ix: usize,
|
||||
entry: &PreviewEntry,
|
||||
cx: &Context<Self>,
|
||||
) -> impl IntoElement {
|
||||
) -> impl IntoElement + use<> {
|
||||
match entry {
|
||||
PreviewEntry::Component(component_metadata) => {
|
||||
let id = component_metadata.id();
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||
|
||||
use collections::HashMap;
|
||||
use gpui::App;
|
||||
use schemars::gen::SchemaGenerator;
|
||||
use schemars::r#gen::SchemaGenerator;
|
||||
use schemars::schema::{InstanceType, Schema, SchemaObject};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
|
@ -348,7 +348,10 @@ impl Copilot {
|
|||
this
|
||||
}
|
||||
|
||||
fn shutdown_language_server(&mut self, _cx: &mut Context<Self>) -> impl Future<Output = ()> {
|
||||
fn shutdown_language_server(
|
||||
&mut self,
|
||||
_cx: &mut Context<Self>,
|
||||
) -> impl Future<Output = ()> + use<> {
|
||||
let shutdown = match mem::replace(&mut self.server, CopilotServer::Disabled) {
|
||||
CopilotServer::Running(server) => Some(Box::pin(async move { server.lsp.shutdown() })),
|
||||
_ => None,
|
||||
|
|
|
@ -296,7 +296,9 @@ impl DebugPanel {
|
|||
match event {
|
||||
dap_store::DapStoreEvent::DebugClientStarted(session_id) => {
|
||||
let Some(session) = dap_store.read(cx).session_by_id(session_id) else {
|
||||
return log::error!("Couldn't get session with id: {session_id:?} from DebugClientStarted event");
|
||||
return log::error!(
|
||||
"Couldn't get session with id: {session_id:?} from DebugClientStarted event"
|
||||
);
|
||||
};
|
||||
|
||||
let Some(project) = self.project.upgrade() else {
|
||||
|
|
|
@ -437,7 +437,9 @@ impl VariableList {
|
|||
});
|
||||
|
||||
if res.is_none() {
|
||||
log::error!("Couldn't confirm variable edit because variable doesn't have a leaf name or a parent reference id");
|
||||
log::error!(
|
||||
"Couldn't confirm variable edit because variable doesn't have a leaf name or a parent reference id"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ impl<'a> CommitAvatar<'a> {
|
|||
&'a self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<CommitTooltip>,
|
||||
) -> Option<impl IntoElement> {
|
||||
) -> Option<impl IntoElement + use<>> {
|
||||
let remote = self
|
||||
.commit
|
||||
.message
|
||||
|
|
|
@ -1464,7 +1464,7 @@ pub mod tests {
|
|||
});
|
||||
|
||||
let buffer = cx.update(|cx| {
|
||||
if rng.gen() {
|
||||
if rng.r#gen() {
|
||||
let len = rng.gen_range(0..10);
|
||||
let text = util::RandomCharIter::new(&mut rng)
|
||||
.take(len)
|
||||
|
@ -1526,7 +1526,7 @@ pub mod tests {
|
|||
}
|
||||
30..=44 => {
|
||||
map.update(cx, |map, cx| {
|
||||
if rng.gen() || blocks.is_empty() {
|
||||
if rng.r#gen() || blocks.is_empty() {
|
||||
let buffer = map.snapshot(cx).buffer_snapshot;
|
||||
let block_properties = (0..rng.gen_range(1..=1))
|
||||
.map(|_| {
|
||||
|
@ -1536,7 +1536,7 @@ pub mod tests {
|
|||
Bias::Left,
|
||||
));
|
||||
|
||||
let placement = if rng.gen() {
|
||||
let placement = if rng.r#gen() {
|
||||
BlockPlacement::Above(position)
|
||||
} else {
|
||||
BlockPlacement::Below(position)
|
||||
|
@ -1580,7 +1580,7 @@ pub mod tests {
|
|||
});
|
||||
}
|
||||
|
||||
if rng.gen() && fold_count > 0 {
|
||||
if rng.r#gen() && fold_count > 0 {
|
||||
log::info!("unfolding ranges: {:?}", ranges);
|
||||
map.update(cx, |map, cx| {
|
||||
map.unfold_intersecting(ranges, true, cx);
|
||||
|
|
|
@ -1370,7 +1370,7 @@ impl BlockSnapshot {
|
|||
while let Some(transform) = cursor.item() {
|
||||
match &transform.block {
|
||||
Some(Block::ExcerptBoundary { excerpt, .. }) => {
|
||||
return Some(StickyHeaderExcerpt { excerpt })
|
||||
return Some(StickyHeaderExcerpt { excerpt });
|
||||
}
|
||||
Some(block) if block.is_buffer_header() => return None,
|
||||
_ => {
|
||||
|
@ -2913,7 +2913,7 @@ mod tests {
|
|||
|
||||
log::info!("Wrap width: {:?}", wrap_width);
|
||||
log::info!("Excerpt Header Height: {:?}", excerpt_header_height);
|
||||
let is_singleton = rng.gen();
|
||||
let is_singleton = rng.r#gen();
|
||||
let buffer = if is_singleton {
|
||||
let len = rng.gen_range(0..10);
|
||||
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
|
||||
|
@ -3077,7 +3077,9 @@ mod tests {
|
|||
let fold = !unfolded_buffers.is_empty() && rng.gen_bool(0.5);
|
||||
let unfold = !folded_buffers.is_empty() && rng.gen_bool(0.5);
|
||||
if !fold && !unfold {
|
||||
log::info!("Noop fold/unfold operation. Unfolded buffers: {unfolded_count}, folded buffers: {folded_count}");
|
||||
log::info!(
|
||||
"Noop fold/unfold operation. Unfolded buffers: {unfolded_count}, folded buffers: {folded_count}"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1616,7 +1616,7 @@ mod tests {
|
|||
|
||||
let len = rng.gen_range(0..10);
|
||||
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
|
||||
let buffer = if rng.gen() {
|
||||
let buffer = if rng.r#gen() {
|
||||
MultiBuffer::build_simple(&text, cx)
|
||||
} else {
|
||||
MultiBuffer::build_random(&mut rng, cx)
|
||||
|
@ -1962,7 +1962,7 @@ mod tests {
|
|||
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
|
||||
to_unfold.push(start..end);
|
||||
}
|
||||
let inclusive = rng.gen();
|
||||
let inclusive = rng.r#gen();
|
||||
log::info!("unfolding {:?} (inclusive: {})", to_unfold, inclusive);
|
||||
let (mut writer, snapshot, edits) = self.write(inlay_snapshot, vec![]);
|
||||
snapshot_edits.push((snapshot, edits));
|
||||
|
|
|
@ -610,9 +610,9 @@ impl InlayMap {
|
|||
let mut to_insert = Vec::new();
|
||||
let snapshot = &mut self.snapshot;
|
||||
for i in 0..rng.gen_range(1..=5) {
|
||||
if self.inlays.is_empty() || rng.gen() {
|
||||
if self.inlays.is_empty() || rng.r#gen() {
|
||||
let position = snapshot.buffer.random_byte_range(0, rng).start;
|
||||
let bias = if rng.gen() { Bias::Left } else { Bias::Right };
|
||||
let bias = if rng.r#gen() { Bias::Left } else { Bias::Right };
|
||||
let len = if rng.gen_bool(0.01) {
|
||||
0
|
||||
} else {
|
||||
|
@ -1500,7 +1500,7 @@ mod tests {
|
|||
.unwrap_or(10);
|
||||
|
||||
let len = rng.gen_range(0..30);
|
||||
let buffer = if rng.gen() {
|
||||
let buffer = if rng.r#gen() {
|
||||
let text = util::RandomCharIter::new(&mut rng)
|
||||
.take(len)
|
||||
.collect::<String>();
|
||||
|
|
|
@ -738,7 +738,7 @@ mod tests {
|
|||
fn test_random_tabs(cx: &mut gpui::App, mut rng: StdRng) {
|
||||
let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
|
||||
let len = rng.gen_range(0..30);
|
||||
let buffer = if rng.gen() {
|
||||
let buffer = if rng.r#gen() {
|
||||
let text = util::RandomCharIter::new(&mut rng)
|
||||
.take(len)
|
||||
.collect::<String>();
|
||||
|
|
|
@ -1207,7 +1207,7 @@ mod tests {
|
|||
log::info!("Wrap width: {:?}", wrap_width);
|
||||
|
||||
let buffer = cx.update(|cx| {
|
||||
if rng.gen() {
|
||||
if rng.r#gen() {
|
||||
MultiBuffer::build_random(&mut rng, cx)
|
||||
} else {
|
||||
let len = rng.gen_range(0..10);
|
||||
|
|
|
@ -2428,7 +2428,11 @@ impl Editor {
|
|||
background_executor.timer(SERIALIZATION_THROTTLE_TIME).await;
|
||||
DB.save_editor_folds(editor_id, workspace_id, db_folds)
|
||||
.await
|
||||
.with_context(|| format!("persisting editor folds for editor {editor_id}, workspace {workspace_id:?}"))
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"persisting editor folds for editor {editor_id}, workspace {workspace_id:?}"
|
||||
)
|
||||
})
|
||||
.log_err();
|
||||
});
|
||||
}
|
||||
|
@ -6200,7 +6204,9 @@ impl Editor {
|
|||
fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
|
||||
if self.tasks.insert(key, value).is_some() {
|
||||
// This case should hopefully be rare, but just in case...
|
||||
log::error!("multiple different run targets found on a single line, only the last target will be rendered")
|
||||
log::error!(
|
||||
"multiple different run targets found on a single line, only the last target will be rendered"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7985,7 +7985,9 @@ async fn test_multibuffer_format_during_save(cx: &mut TestAppContext) {
|
|||
assert!(cx.read(|cx| !multi_buffer_editor.is_dirty(cx)));
|
||||
assert_eq!(
|
||||
multi_buffer_editor.update(cx, |editor, cx| editor.text(cx)),
|
||||
uri!("a|o[file:///a/main.rs formatted]bbbb\ncccc\n\nffff\ngggg\n\njjjj\n\nlll[file:///a/other.rs formatted]mmmm\nnnnn|four|five|six|\nr\n\nuuuu\n\nvvvv\nwwww\nxxxx\n\n{{{{\n||||\n\n\u{7f}\u{7f}\u{7f}\u{7f}"),
|
||||
uri!(
|
||||
"a|o[file:///a/main.rs formatted]bbbb\ncccc\n\nffff\ngggg\n\njjjj\n\nlll[file:///a/other.rs formatted]mmmm\nnnnn|four|five|six|\nr\n\nuuuu\n\nvvvv\nwwww\nxxxx\n\n{{{{\n||||\n\n\u{7f}\u{7f}\u{7f}\u{7f}"
|
||||
),
|
||||
);
|
||||
buffer_1.update(cx, |buffer, _| {
|
||||
assert!(!buffer.is_dirty());
|
||||
|
@ -18669,7 +18671,7 @@ fn assert_selection_ranges(marked_text: &str, editor: &mut Editor, cx: &mut Cont
|
|||
pub fn handle_signature_help_request(
|
||||
cx: &mut EditorLspTestContext,
|
||||
mocked_response: lsp::SignatureHelp,
|
||||
) -> impl Future<Output = ()> {
|
||||
) -> impl Future<Output = ()> + use<> {
|
||||
let mut request =
|
||||
cx.set_request_handler::<lsp::request::SignatureHelpRequest, _, _>(move |_, _, _| {
|
||||
let mocked_response = mocked_response.clone();
|
||||
|
|
|
@ -4190,8 +4190,7 @@ impl EditorElement {
|
|||
None;
|
||||
for (&new_row, &new_background) in &layout.highlighted_rows {
|
||||
match &mut current_paint {
|
||||
Some((current_background, current_range, mut edges)) => {
|
||||
let current_background = *current_background;
|
||||
&mut Some((current_background, ref mut current_range, mut edges)) => {
|
||||
let new_range_started = current_background != new_background
|
||||
|| current_range.end.next_row() != new_row;
|
||||
if new_range_started {
|
||||
|
@ -8793,8 +8792,10 @@ mod tests {
|
|||
px(500.0),
|
||||
show_line_numbers,
|
||||
);
|
||||
assert!(invisibles.is_empty(),
|
||||
"For editor mode {editor_mode_without_invisibles:?} no invisibles was expected but got {invisibles:?}");
|
||||
assert!(
|
||||
invisibles.is_empty(),
|
||||
"For editor mode {editor_mode_without_invisibles:?} no invisibles was expected but got {invisibles:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8872,7 +8873,9 @@ mod tests {
|
|||
(Invisible::Whitespace { .. }, Invisible::Whitespace { .. })
|
||||
| (Invisible::Tab { .. }, Invisible::Tab { .. }) => {}
|
||||
_ => {
|
||||
panic!("At index {i}, expected invisible {expected_invisible:?} does not match actual {actual_invisible:?} by kind. Actual invisibles: {actual_invisibles:?}")
|
||||
panic!(
|
||||
"At index {i}, expected invisible {expected_invisible:?} does not match actual {actual_invisible:?} by kind. Actual invisibles: {actual_invisibles:?}"
|
||||
)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
|
|
|
@ -26,8 +26,7 @@ use wit_component::ComponentEncoder;
|
|||
/// Once Rust 1.78 is released, there will be a `wasm32-wasip2` target available, so we will
|
||||
/// not need the adapter anymore.
|
||||
const RUST_TARGET: &str = "wasm32-wasip1";
|
||||
const WASI_ADAPTER_URL: &str =
|
||||
"https://github.com/bytecodealliance/wasmtime/releases/download/v18.0.2/wasi_snapshot_preview1.reactor.wasm";
|
||||
const WASI_ADAPTER_URL: &str = "https://github.com/bytecodealliance/wasmtime/releases/download/v18.0.2/wasi_snapshot_preview1.reactor.wasm";
|
||||
|
||||
/// Compiling Tree-sitter parsers from C to WASM requires Clang 17, and a WASM build of libc
|
||||
/// and clang's runtime library. The `wasi-sdk` provides these binaries.
|
||||
|
@ -100,7 +99,9 @@ impl ExtensionBuilder {
|
|||
for (grammar_name, grammar_metadata) in &extension_manifest.grammars {
|
||||
let snake_cased_grammar_name = grammar_name.to_case(Case::Snake);
|
||||
if grammar_name.as_ref() != snake_cased_grammar_name.as_str() {
|
||||
bail!("grammar name '{grammar_name}' must be written in snake_case: {snake_cased_grammar_name}");
|
||||
bail!(
|
||||
"grammar name '{grammar_name}' must be written in snake_case: {snake_cased_grammar_name}"
|
||||
);
|
||||
}
|
||||
|
||||
log::info!(
|
||||
|
|
|
@ -19,7 +19,7 @@ path = "src/extension_api.rs"
|
|||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
wit-bindgen = "0.22"
|
||||
wit-bindgen = "0.41"
|
||||
|
||||
[package.metadata.component]
|
||||
target = { path = "wit" }
|
||||
|
|
|
@ -185,7 +185,7 @@ pub trait Extension: Send + Sync {
|
|||
#[macro_export]
|
||||
macro_rules! register_extension {
|
||||
($extension_type:ty) => {
|
||||
#[export_name = "init-extension"]
|
||||
#[unsafe(export_name = "init-extension")]
|
||||
pub extern "C" fn __init_extension() {
|
||||
std::env::set_current_dir(std::env::var("PWD").unwrap()).unwrap();
|
||||
zed_extension_api::register_extension(|| {
|
||||
|
|
|
@ -398,7 +398,7 @@ impl ExtensionStore {
|
|||
&mut self,
|
||||
modified_extension: Option<Arc<str>>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl Future<Output = ()> {
|
||||
) -> impl Future<Output = ()> + use<> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.reload_complete_senders.push(tx);
|
||||
self.reload_tx
|
||||
|
|
|
@ -839,64 +839,64 @@ async fn test_query_history(cx: &mut gpui::TestAppContext) {
|
|||
let history_after_third =
|
||||
open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
|
||||
assert_eq!(
|
||||
history_after_third,
|
||||
vec![
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/third.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/third.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/second.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/second.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/first.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/first.rs")))
|
||||
),
|
||||
],
|
||||
"Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
|
||||
history_after_third,
|
||||
vec![
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/third.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/third.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/second.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/second.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/first.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/first.rs")))
|
||||
),
|
||||
],
|
||||
"Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
|
||||
3rd item should be the first in the history, as the last opened."
|
||||
);
|
||||
);
|
||||
|
||||
let history_after_second_again =
|
||||
open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
|
||||
assert_eq!(
|
||||
history_after_second_again,
|
||||
vec![
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/second.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/second.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/third.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/third.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/first.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/first.rs")))
|
||||
),
|
||||
],
|
||||
"Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
|
||||
history_after_second_again,
|
||||
vec![
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/second.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/second.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/third.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/third.rs")))
|
||||
),
|
||||
FoundPath::new(
|
||||
ProjectPath {
|
||||
worktree_id,
|
||||
path: Arc::from(Path::new("test/first.rs")),
|
||||
},
|
||||
Some(PathBuf::from(path!("/src/test/first.rs")))
|
||||
),
|
||||
],
|
||||
"Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
|
||||
2nd item, as the last opened, 3rd item should go next as it was opened right before."
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -1656,15 +1656,15 @@ async fn test_nonexistent_history_items_not_shown(cx: &mut gpui::TestAppContext)
|
|||
cx.simulate_input("rs");
|
||||
|
||||
picker.update(cx, |picker, _| {
|
||||
assert_eq!(
|
||||
collect_search_matches(picker).history,
|
||||
vec![
|
||||
PathBuf::from("test/first.rs"),
|
||||
PathBuf::from("test/third.rs"),
|
||||
],
|
||||
"Should have all opened files in the history, except the ones that do not exist on disk"
|
||||
);
|
||||
});
|
||||
assert_eq!(
|
||||
collect_search_matches(picker).history,
|
||||
vec![
|
||||
PathBuf::from("test/first.rs"),
|
||||
PathBuf::from("test/third.rs"),
|
||||
],
|
||||
"Should have all opened files in the history, except the ones that do not exist on disk"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
|
|
@ -430,7 +430,7 @@ impl Fs for RealFs {
|
|||
|
||||
unsafe {
|
||||
unsafe fn ns_string(string: &str) -> id {
|
||||
NSString::alloc(nil).init_str(string).autorelease()
|
||||
unsafe { NSString::alloc(nil).init_str(string).autorelease() }
|
||||
}
|
||||
|
||||
let url: id = msg_send![class!(NSURL), fileURLWithPath: ns_string(path.to_string_lossy().as_ref())];
|
||||
|
@ -591,7 +591,7 @@ impl Fs for RealFs {
|
|||
(io::ErrorKind::NotFound, _) => Ok(None),
|
||||
(io::ErrorKind::Other, Some(libc::ENOTDIR)) => Ok(None),
|
||||
_ => Err(anyhow::Error::new(err)),
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ impl std::fmt::Display for StreamFlags {
|
|||
}
|
||||
|
||||
#[link(name = "CoreServices", kind = "framework")]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
pub fn FSEventsGetCurrentEventId() -> u64;
|
||||
}
|
||||
|
||||
|
|
|
@ -1548,7 +1548,7 @@ impl GitPanel {
|
|||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl Future<Output = Result<bool, anyhow::Error>> {
|
||||
) -> impl Future<Output = Result<bool, anyhow::Error>> + use<> {
|
||||
let repo = self.active_repository.clone();
|
||||
let mut cx = window.to_async(cx);
|
||||
|
||||
|
@ -2007,7 +2007,7 @@ impl GitPanel {
|
|||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl Future<Output = anyhow::Result<Option<Remote>>> {
|
||||
) -> impl Future<Output = anyhow::Result<Option<Remote>>> + use<> {
|
||||
let repo = self.active_repository.clone();
|
||||
let workspace = self.workspace.clone();
|
||||
let mut cx = window.to_async(cx);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 || {
|
||||
|
|
|
@ -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, {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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: {:?}",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -65,7 +65,7 @@ impl MacDisplay {
|
|||
}
|
||||
|
||||
#[link(name = "ApplicationServices", kind = "framework")]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -17,7 +17,7 @@ pub fn derive_app_context(input: TokenStream) -> TokenStream {
|
|||
let type_name = &ast.ident;
|
||||
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
|
||||
|
||||
let gen = quote! {
|
||||
let r#gen = quote! {
|
||||
impl #impl_generics gpui::AppContext for #type_name #type_generics
|
||||
#where_clause
|
||||
{
|
||||
|
@ -98,5 +98,5 @@ pub fn derive_app_context(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
};
|
||||
|
||||
gen.into()
|
||||
r#gen.into()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ pub fn derive_into_element(input: TokenStream) -> TokenStream {
|
|||
let type_name = &ast.ident;
|
||||
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
|
||||
|
||||
let gen = quote! {
|
||||
let r#gen = quote! {
|
||||
impl #impl_generics gpui::IntoElement for #type_name #type_generics
|
||||
#where_clause
|
||||
{
|
||||
|
@ -19,5 +19,5 @@ pub fn derive_into_element(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
};
|
||||
|
||||
gen.into()
|
||||
r#gen.into()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
|
|||
let type_name = &ast.ident;
|
||||
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
|
||||
|
||||
let gen = quote! {
|
||||
let r#gen = quote! {
|
||||
impl #impl_generics gpui::Render for #type_name #type_generics
|
||||
#where_clause
|
||||
{
|
||||
|
@ -17,5 +17,5 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
};
|
||||
|
||||
gen.into()
|
||||
r#gen.into()
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn derive_visual_context(input: TokenStream) -> TokenStream {
|
|||
let type_name = &ast.ident;
|
||||
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
|
||||
|
||||
let gen = quote! {
|
||||
let r#gen = quote! {
|
||||
impl #impl_generics gpui::VisualContext for #type_name #type_generics
|
||||
#where_clause
|
||||
{
|
||||
|
@ -67,5 +67,5 @@ pub fn derive_visual_context(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
};
|
||||
|
||||
gen.into()
|
||||
r#gen.into()
|
||||
}
|
||||
|
|
|
@ -1292,27 +1292,27 @@ fn border_prefixes() -> Vec<BorderStylePrefix> {
|
|||
quote! { border_widths.bottom },
|
||||
quote! { border_widths.left },
|
||||
],
|
||||
doc_string_prefix: "Sets the border width of the element. [Docs](https://tailwindcss.com/docs/border-width)"
|
||||
doc_string_prefix: "Sets the border width of the element. [Docs](https://tailwindcss.com/docs/border-width)",
|
||||
},
|
||||
BorderStylePrefix {
|
||||
prefix: "border_t",
|
||||
fields: vec![quote! { border_widths.top }],
|
||||
doc_string_prefix: "Sets the border width of the top side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
|
||||
doc_string_prefix: "Sets the border width of the top side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
|
||||
},
|
||||
BorderStylePrefix {
|
||||
prefix: "border_b",
|
||||
fields: vec![quote! { border_widths.bottom }],
|
||||
doc_string_prefix: "Sets the border width of the bottom side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
|
||||
doc_string_prefix: "Sets the border width of the bottom side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
|
||||
},
|
||||
BorderStylePrefix {
|
||||
prefix: "border_r",
|
||||
fields: vec![quote! { border_widths.right }],
|
||||
doc_string_prefix: "Sets the border width of the right side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
|
||||
doc_string_prefix: "Sets the border width of the right side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
|
||||
},
|
||||
BorderStylePrefix {
|
||||
prefix: "border_l",
|
||||
fields: vec![quote! { border_widths.left }],
|
||||
doc_string_prefix: "Sets the border width of the left side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
|
||||
doc_string_prefix: "Sets the border width of the left side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
|
||||
},
|
||||
BorderStylePrefix {
|
||||
prefix: "border_x",
|
||||
|
@ -1320,7 +1320,7 @@ fn border_prefixes() -> Vec<BorderStylePrefix> {
|
|||
quote! { border_widths.left },
|
||||
quote! { border_widths.right },
|
||||
],
|
||||
doc_string_prefix: "Sets the border width of the vertical sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)"
|
||||
doc_string_prefix: "Sets the border width of the vertical sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)",
|
||||
},
|
||||
BorderStylePrefix {
|
||||
prefix: "border_y",
|
||||
|
@ -1328,7 +1328,7 @@ fn border_prefixes() -> Vec<BorderStylePrefix> {
|
|||
quote! { border_widths.top },
|
||||
quote! { border_widths.bottom },
|
||||
],
|
||||
doc_string_prefix: "Sets the border width of the horizontal sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)"
|
||||
doc_string_prefix: "Sets the border width of the horizontal sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)",
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -441,7 +441,9 @@ mod persistence {
|
|||
.collect::<Vec<&str>>()
|
||||
.join(", ");
|
||||
|
||||
let query = format!("DELETE FROM image_viewers WHERE workspace_id = ? AND item_id NOT IN ({placeholders})");
|
||||
let query = format!(
|
||||
"DELETE FROM image_viewers WHERE workspace_id = ? AND item_id NOT IN ({placeholders})"
|
||||
);
|
||||
|
||||
self.write(move |conn| {
|
||||
let mut statement = Statement::prepare(conn, query)?;
|
||||
|
|
|
@ -989,7 +989,7 @@ impl Buffer {
|
|||
language: Option<Arc<Language>>,
|
||||
language_registry: Option<Arc<LanguageRegistry>>,
|
||||
cx: &mut App,
|
||||
) -> impl Future<Output = BufferSnapshot> {
|
||||
) -> impl Future<Output = BufferSnapshot> + use<> {
|
||||
let entity_id = cx.reserve_entity::<Self>().entity_id();
|
||||
let buffer_id = entity_id.as_non_zero_u64().into();
|
||||
async move {
|
||||
|
@ -1587,7 +1587,9 @@ impl Buffer {
|
|||
}
|
||||
}
|
||||
|
||||
fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>>> {
|
||||
fn compute_autoindents(
|
||||
&self,
|
||||
) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>> + use<>> {
|
||||
let max_rows_between_yields = 100;
|
||||
let snapshot = self.snapshot();
|
||||
if snapshot.syntax.is_empty() || self.autoindent_requests.is_empty() {
|
||||
|
@ -2082,23 +2084,26 @@ impl Buffer {
|
|||
}
|
||||
|
||||
/// Waits for the buffer to receive operations with the given timestamps.
|
||||
pub fn wait_for_edits(
|
||||
pub fn wait_for_edits<It: IntoIterator<Item = clock::Lamport>>(
|
||||
&mut self,
|
||||
edit_ids: impl IntoIterator<Item = clock::Lamport>,
|
||||
) -> impl Future<Output = Result<()>> {
|
||||
edit_ids: It,
|
||||
) -> impl Future<Output = Result<()>> + use<It> {
|
||||
self.text.wait_for_edits(edit_ids)
|
||||
}
|
||||
|
||||
/// Waits for the buffer to receive the operations necessary for resolving the given anchors.
|
||||
pub fn wait_for_anchors(
|
||||
pub fn wait_for_anchors<It: IntoIterator<Item = Anchor>>(
|
||||
&mut self,
|
||||
anchors: impl IntoIterator<Item = Anchor>,
|
||||
) -> impl 'static + Future<Output = Result<()>> {
|
||||
anchors: It,
|
||||
) -> impl 'static + Future<Output = Result<()>> + use<It> {
|
||||
self.text.wait_for_anchors(anchors)
|
||||
}
|
||||
|
||||
/// Waits for the buffer to receive operations up to the given version.
|
||||
pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future<Output = Result<()>> {
|
||||
pub fn wait_for_version(
|
||||
&mut self,
|
||||
version: clock::Global,
|
||||
) -> impl Future<Output = Result<()>> + use<> {
|
||||
self.text.wait_for_version(version)
|
||||
}
|
||||
|
||||
|
@ -3916,91 +3921,93 @@ impl BufferSnapshot {
|
|||
.map(|grammar| grammar.runnable_config.as_ref())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
iter::from_fn(move || loop {
|
||||
let mat = syntax_matches.peek()?;
|
||||
iter::from_fn(move || {
|
||||
loop {
|
||||
let mat = syntax_matches.peek()?;
|
||||
|
||||
let test_range = test_configs[mat.grammar_index].and_then(|test_configs| {
|
||||
let mut run_range = None;
|
||||
let full_range = mat.captures.iter().fold(
|
||||
Range {
|
||||
start: usize::MAX,
|
||||
end: 0,
|
||||
},
|
||||
|mut acc, next| {
|
||||
let byte_range = next.node.byte_range();
|
||||
if acc.start > byte_range.start {
|
||||
acc.start = byte_range.start;
|
||||
}
|
||||
if acc.end < byte_range.end {
|
||||
acc.end = byte_range.end;
|
||||
}
|
||||
acc
|
||||
},
|
||||
);
|
||||
if full_range.start > full_range.end {
|
||||
// We did not find a full spanning range of this match.
|
||||
return None;
|
||||
let test_range = test_configs[mat.grammar_index].and_then(|test_configs| {
|
||||
let mut run_range = None;
|
||||
let full_range = mat.captures.iter().fold(
|
||||
Range {
|
||||
start: usize::MAX,
|
||||
end: 0,
|
||||
},
|
||||
|mut acc, next| {
|
||||
let byte_range = next.node.byte_range();
|
||||
if acc.start > byte_range.start {
|
||||
acc.start = byte_range.start;
|
||||
}
|
||||
if acc.end < byte_range.end {
|
||||
acc.end = byte_range.end;
|
||||
}
|
||||
acc
|
||||
},
|
||||
);
|
||||
if full_range.start > full_range.end {
|
||||
// We did not find a full spanning range of this match.
|
||||
return None;
|
||||
}
|
||||
let extra_captures: SmallVec<[_; 1]> =
|
||||
SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
|
||||
test_configs
|
||||
.extra_captures
|
||||
.get(capture.index as usize)
|
||||
.cloned()
|
||||
.and_then(|tag_name| match tag_name {
|
||||
RunnableCapture::Named(name) => {
|
||||
Some((capture.node.byte_range(), name))
|
||||
}
|
||||
RunnableCapture::Run => {
|
||||
let _ = run_range.insert(capture.node.byte_range());
|
||||
None
|
||||
}
|
||||
})
|
||||
}));
|
||||
let run_range = run_range?;
|
||||
let tags = test_configs
|
||||
.query
|
||||
.property_settings(mat.pattern_index)
|
||||
.iter()
|
||||
.filter_map(|property| {
|
||||
if *property.key == *"tag" {
|
||||
property
|
||||
.value
|
||||
.as_ref()
|
||||
.map(|value| RunnableTag(value.to_string().into()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let extra_captures = extra_captures
|
||||
.into_iter()
|
||||
.map(|(range, name)| {
|
||||
(
|
||||
name.to_string(),
|
||||
self.text_for_range(range.clone()).collect::<String>(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
// All tags should have the same range.
|
||||
Some(RunnableRange {
|
||||
run_range,
|
||||
full_range,
|
||||
runnable: Runnable {
|
||||
tags,
|
||||
language: mat.language,
|
||||
buffer: self.remote_id(),
|
||||
},
|
||||
extra_captures,
|
||||
buffer_id: self.remote_id(),
|
||||
})
|
||||
});
|
||||
|
||||
syntax_matches.advance();
|
||||
if test_range.is_some() {
|
||||
// It's fine for us to short-circuit on .peek()? returning None. We don't want to return None from this iter if we
|
||||
// had a capture that did not contain a run marker, hence we'll just loop around for the next capture.
|
||||
return test_range;
|
||||
}
|
||||
let extra_captures: SmallVec<[_; 1]> =
|
||||
SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
|
||||
test_configs
|
||||
.extra_captures
|
||||
.get(capture.index as usize)
|
||||
.cloned()
|
||||
.and_then(|tag_name| match tag_name {
|
||||
RunnableCapture::Named(name) => {
|
||||
Some((capture.node.byte_range(), name))
|
||||
}
|
||||
RunnableCapture::Run => {
|
||||
let _ = run_range.insert(capture.node.byte_range());
|
||||
None
|
||||
}
|
||||
})
|
||||
}));
|
||||
let run_range = run_range?;
|
||||
let tags = test_configs
|
||||
.query
|
||||
.property_settings(mat.pattern_index)
|
||||
.iter()
|
||||
.filter_map(|property| {
|
||||
if *property.key == *"tag" {
|
||||
property
|
||||
.value
|
||||
.as_ref()
|
||||
.map(|value| RunnableTag(value.to_string().into()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let extra_captures = extra_captures
|
||||
.into_iter()
|
||||
.map(|(range, name)| {
|
||||
(
|
||||
name.to_string(),
|
||||
self.text_for_range(range.clone()).collect::<String>(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
// All tags should have the same range.
|
||||
Some(RunnableRange {
|
||||
run_range,
|
||||
full_range,
|
||||
runnable: Runnable {
|
||||
tags,
|
||||
language: mat.language,
|
||||
buffer: self.remote_id(),
|
||||
},
|
||||
extra_captures,
|
||||
buffer_id: self.remote_id(),
|
||||
})
|
||||
});
|
||||
|
||||
syntax_matches.advance();
|
||||
if test_range.is_some() {
|
||||
// It's fine for us to short-circuit on .peek()? returning None. We don't want to return None from this iter if we
|
||||
// had a capture that did not contain a run marker, hence we'll just loop around for the next capture.
|
||||
return test_range;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -4352,7 +4359,10 @@ impl<'a> BufferChunks<'a> {
|
|||
} else {
|
||||
// We cannot obtain new highlights for a language-aware buffer iterator, as we don't have a buffer snapshot.
|
||||
// Seeking such BufferChunks is not supported.
|
||||
debug_assert!(false, "Attempted to seek on a language-aware buffer iterator without associated buffer snapshot");
|
||||
debug_assert!(
|
||||
false,
|
||||
"Attempted to seek on a language-aware buffer iterator without associated buffer snapshot"
|
||||
);
|
||||
}
|
||||
|
||||
highlights.captures.set_byte_range(self.range.clone());
|
||||
|
|
|
@ -38,7 +38,7 @@ pub use manifest::{ManifestName, ManifestProvider, ManifestQuery};
|
|||
use parking_lot::Mutex;
|
||||
use regex::Regex;
|
||||
use schemars::{
|
||||
gen::SchemaGenerator,
|
||||
r#gen::SchemaGenerator,
|
||||
schema::{InstanceType, Schema, SchemaObject},
|
||||
JsonSchema,
|
||||
};
|
||||
|
@ -598,7 +598,9 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
/// Should not be called unless the callee is sure that
|
||||
/// `Self::is_primary_zed_json_schema_adapter` returns `true`
|
||||
async fn clear_zed_json_schema_cache(&self) {
|
||||
unreachable!("Not implemented for this adapter. This method should only be called on the default JSON language server adapter");
|
||||
unreachable!(
|
||||
"Not implemented for this adapter. This method should only be called on the default JSON language server adapter"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -931,8 +933,8 @@ impl BracketPairConfig {
|
|||
}
|
||||
}
|
||||
|
||||
fn bracket_pair_config_json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||
Option::<Vec<BracketPairContent>>::json_schema(gen)
|
||||
fn bracket_pair_config_json_schema(r#gen: &mut SchemaGenerator) -> Schema {
|
||||
Option::<Vec<BracketPairContent>>::json_schema(r#gen)
|
||||
}
|
||||
|
||||
#[derive(Deserialize, JsonSchema)]
|
||||
|
@ -1532,7 +1534,9 @@ impl Language {
|
|||
.scope_opt_in_language_servers
|
||||
.contains(server_name)
|
||||
{
|
||||
util::debug_panic!("Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server");
|
||||
util::debug_panic!(
|
||||
"Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -597,7 +597,7 @@ impl LanguageRegistry {
|
|||
pub fn language_for_name(
|
||||
self: &Arc<Self>,
|
||||
name: &str,
|
||||
) -> impl Future<Output = Result<Arc<Language>>> {
|
||||
) -> impl Future<Output = Result<Arc<Language>>> + use<> {
|
||||
let name = UniCase::new(name);
|
||||
let rx = self.get_or_load_language(|language_name, _| {
|
||||
if UniCase::new(&language_name.0) == name {
|
||||
|
|
|
@ -1300,7 +1300,7 @@ impl settings::Settings for AllLanguageSettings {
|
|||
}
|
||||
|
||||
fn json_schema(
|
||||
generator: &mut schemars::gen::SchemaGenerator,
|
||||
generator: &mut schemars::r#gen::SchemaGenerator,
|
||||
params: &settings::SettingsJsonSchemaParams,
|
||||
_: &App,
|
||||
) -> schemars::schema::RootSchema {
|
||||
|
|
|
@ -153,14 +153,14 @@ fn test_syntax_map_layers_for_range(cx: &mut App) {
|
|||
syntax_map.reparse(language.clone(), &buffer);
|
||||
|
||||
assert_layers_for_range(
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(2, 14)..Point::new(2, 16),
|
||||
&[
|
||||
"...(function_item ...",
|
||||
"...(tuple_expression (call_expression ... arguments: (arguments (reference_expression value: (array_expression...",
|
||||
],
|
||||
);
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(2, 14)..Point::new(2, 16),
|
||||
&[
|
||||
"...(function_item ...",
|
||||
"...(tuple_expression (call_expression ... arguments: (arguments (reference_expression value: (array_expression...",
|
||||
],
|
||||
);
|
||||
|
||||
// Put the vec! macro back, adding back the syntactic layer.
|
||||
buffer.undo();
|
||||
|
@ -207,15 +207,15 @@ fn test_dynamic_language_injection(cx: &mut App) {
|
|||
syntax_map.reparse(markdown.clone(), &buffer);
|
||||
syntax_map.reparse(markdown_inline.clone(), &buffer);
|
||||
assert_layers_for_range(
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
"...(function_item name: (identifier) parameters: (parameters) body: (block)...",
|
||||
],
|
||||
);
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
"...(function_item name: (identifier) parameters: (parameters) body: (block)...",
|
||||
],
|
||||
);
|
||||
|
||||
// Replace `rs` with a path to ending in `.rb` in code block.
|
||||
let macro_name_range = range_for_text(&buffer, "rs");
|
||||
|
@ -224,15 +224,15 @@ fn test_dynamic_language_injection(cx: &mut App) {
|
|||
syntax_map.reparse(markdown.clone(), &buffer);
|
||||
syntax_map.reparse(markdown_inline.clone(), &buffer);
|
||||
assert_layers_for_range(
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
"...(call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list) block: (block)...",
|
||||
],
|
||||
);
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
"...(call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list) block: (block)...",
|
||||
],
|
||||
);
|
||||
|
||||
// Replace Ruby with a language that hasn't been loaded yet.
|
||||
let macro_name_range = range_for_text(&buffer, "foo/bar/baz.rb");
|
||||
|
@ -241,29 +241,29 @@ fn test_dynamic_language_injection(cx: &mut App) {
|
|||
syntax_map.reparse(markdown.clone(), &buffer);
|
||||
syntax_map.reparse(markdown_inline.clone(), &buffer);
|
||||
assert_layers_for_range(
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
],
|
||||
);
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
],
|
||||
);
|
||||
assert!(syntax_map.contains_unknown_injections());
|
||||
|
||||
registry.add(Arc::new(html_lang()));
|
||||
syntax_map.reparse(markdown.clone(), &buffer);
|
||||
syntax_map.reparse(markdown_inline.clone(), &buffer);
|
||||
assert_layers_for_range(
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
"(document (text))",
|
||||
],
|
||||
);
|
||||
&syntax_map,
|
||||
&buffer,
|
||||
Point::new(3, 0)..Point::new(3, 0),
|
||||
&[
|
||||
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
|
||||
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
|
||||
"(document (text))",
|
||||
],
|
||||
);
|
||||
assert!(!syntax_map.contains_unknown_injections());
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ impl RateLimiter {
|
|||
pub fn stream<'a, Fut, T>(
|
||||
&self,
|
||||
future: Fut,
|
||||
) -> impl 'a + Future<Output = Result<impl Stream<Item = T::Item>>>
|
||||
) -> impl 'a + Future<Output = Result<impl Stream<Item = T::Item> + use<Fut, T>>>
|
||||
where
|
||||
Fut: 'a + Future<Output = Result<T>>,
|
||||
T: Stream,
|
||||
|
|
|
@ -125,11 +125,21 @@ impl LanguageModelProvider for CopilotChatLanguageModelProvider {
|
|||
|
||||
let err = match copilot.read(cx).status() {
|
||||
Status::Authorized => return Task::ready(Ok(())),
|
||||
Status::Disabled => anyhow!("Copilot must be enabled for Copilot Chat to work. Please enable Copilot and try again."),
|
||||
Status::Error(err) => anyhow!(format!("Received the following error while signing into Copilot: {err}")),
|
||||
Status::Starting { task: _ } => anyhow!("Copilot is still starting, please wait for Copilot to start then try again"),
|
||||
Status::Unauthorized => anyhow!("Unable to authorize with Copilot. Please make sure that you have an active Copilot and Copilot Chat subscription."),
|
||||
Status::SignedOut {..} => anyhow!("You have signed out of Copilot. Please sign in to Copilot and try again."),
|
||||
Status::Disabled => anyhow!(
|
||||
"Copilot must be enabled for Copilot Chat to work. Please enable Copilot and try again."
|
||||
),
|
||||
Status::Error(err) => anyhow!(format!(
|
||||
"Received the following error while signing into Copilot: {err}"
|
||||
)),
|
||||
Status::Starting { task: _ } => anyhow!(
|
||||
"Copilot is still starting, please wait for Copilot to start then try again"
|
||||
),
|
||||
Status::Unauthorized => anyhow!(
|
||||
"Unable to authorize with Copilot. Please make sure that you have an active Copilot and Copilot Chat subscription."
|
||||
),
|
||||
Status::SignedOut { .. } => {
|
||||
anyhow!("You have signed out of Copilot. Please sign in to Copilot and try again.")
|
||||
}
|
||||
Status::SigningIn { prompt: _ } => anyhow!("Still signing into Copilot..."),
|
||||
};
|
||||
|
||||
|
@ -398,8 +408,7 @@ impl Render for ConfigurationView {
|
|||
.child(svg().size_8().path(IconName::CopilotError.path()))
|
||||
}
|
||||
_ => {
|
||||
const LABEL: &str =
|
||||
"To use Zed's assistant with GitHub Copilot, you need to be logged in to GitHub. Note that your GitHub account must have an active Copilot Chat subscription.";
|
||||
const LABEL: &str = "To use Zed's assistant with GitHub Copilot, you need to be logged in to GitHub. Note that your GitHub account must have an active Copilot Chat subscription.";
|
||||
v_flex().gap_6().child(Label::new(LABEL)).child(
|
||||
v_flex()
|
||||
.gap_2()
|
||||
|
|
|
@ -2,8 +2,7 @@ use anyhow::{anyhow, Context as _, Result};
|
|||
use collections::BTreeMap;
|
||||
use credentials_provider::CredentialsProvider;
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use futures::Stream;
|
||||
use futures::{future::BoxFuture, FutureExt, StreamExt};
|
||||
use futures::{future::BoxFuture, FutureExt, Stream, StreamExt};
|
||||
use google_ai::{FunctionDeclaration, GenerateContentResponse, Part, UsageMetadata};
|
||||
use gpui::{
|
||||
AnyView, App, AsyncApp, Context, Entity, FontStyle, Subscription, Task, TextStyle, WhiteSpace,
|
||||
|
|
|
@ -415,8 +415,7 @@ impl Render for ConfigurationView {
|
|||
let is_authenticated = self.state.read(cx).is_authenticated();
|
||||
|
||||
let lmstudio_intro = "Run local LLMs like Llama, Phi, and Qwen.";
|
||||
let lmstudio_reqs =
|
||||
"To use LM Studio as a provider for Zed assistant, it needs to be running with at least one model downloaded.";
|
||||
let lmstudio_reqs = "To use LM Studio as a provider for Zed assistant, it needs to be running with at least one model downloaded.";
|
||||
|
||||
let inline_code_bg = cx.theme().colors().editor_foreground.opacity(0.05);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue