logiguard fork v3: full patch set on verified 8c74db0 tree
Includes prior-session patches (carry forward so the app compiles): - crates/gpui/build.rs: cross-compile manifest fix - crates/gpui/src/platform.rs: PlatformWindow::activate_with_token trait method - crates/gpui/src/window.rs: Window::activate_with_token public API - crates/gpui_linux/src/linux/wayland/window.rs: WaylandWindow::activate_with_token + activate() keyboard-serial fix Plus the focus-serial fix: - serial.rs: SerialKind::KeyboardEnter - client.rs: store wl_keyboard.enter serial; latest_serial_of() Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
21
crates/ui_macros/Cargo.toml
Normal file
21
crates/ui_macros/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "ui_macros"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
publish.workspace = true
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/ui_macros.rs"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote.workspace = true
|
||||
syn.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
component.workspace = true
|
||||
ui.workspace = true
|
||||
1
crates/ui_macros/LICENSE-GPL
Symbolic link
1
crates/ui_macros/LICENSE-GPL
Symbolic link
@@ -0,0 +1 @@
|
||||
../../LICENSE-GPL
|
||||
29
crates/ui_macros/src/derive_register_component.rs
Normal file
29
crates/ui_macros/src/derive_register_component.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{DeriveInput, parse_macro_input};
|
||||
|
||||
pub fn derive_register_component(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let name = input.ident;
|
||||
let register_fn_name = syn::Ident::new(
|
||||
&format!("__component_registry_internal_register_{}", name),
|
||||
name.span(),
|
||||
);
|
||||
let expanded = quote! {
|
||||
const _: () = {
|
||||
struct AssertComponent<T: component::Component>(::std::marker::PhantomData<T>);
|
||||
let _ = AssertComponent::<#name>(::std::marker::PhantomData);
|
||||
};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn #register_fn_name() {
|
||||
component::register_component::<#name>();
|
||||
}
|
||||
|
||||
component::__private::inventory::submit! {
|
||||
component::ComponentFn::new(#register_fn_name)
|
||||
}
|
||||
};
|
||||
expanded.into()
|
||||
}
|
||||
167
crates/ui_macros/src/dynamic_spacing.rs
Normal file
167
crates/ui_macros/src/dynamic_spacing.rs
Normal file
@@ -0,0 +1,167 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{
|
||||
LitInt, Token, parse::Parse, parse::ParseStream, parse_macro_input, punctuated::Punctuated,
|
||||
};
|
||||
|
||||
struct DynamicSpacingInput {
|
||||
values: Punctuated<DynamicSpacingValue, Token![,]>,
|
||||
}
|
||||
|
||||
// The input for the derive macro is a list of values.
|
||||
//
|
||||
// When a single value is provided, the standard spacing formula is
|
||||
// used to derive the of spacing values.
|
||||
//
|
||||
// When a tuple of three values is provided, the values are used as
|
||||
// the spacing values directly.
|
||||
enum DynamicSpacingValue {
|
||||
Single(LitInt),
|
||||
Tuple(LitInt, LitInt, LitInt),
|
||||
}
|
||||
|
||||
impl Parse for DynamicSpacingInput {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
Ok(DynamicSpacingInput {
|
||||
values: input.parse_terminated(DynamicSpacingValue::parse, Token![,])?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for DynamicSpacingValue {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
if input.peek(syn::token::Paren) {
|
||||
let content;
|
||||
syn::parenthesized!(content in input);
|
||||
let a: LitInt = content.parse()?;
|
||||
content.parse::<Token![,]>()?;
|
||||
let b: LitInt = content.parse()?;
|
||||
content.parse::<Token![,]>()?;
|
||||
let c: LitInt = content.parse()?;
|
||||
Ok(DynamicSpacingValue::Tuple(a, b, c))
|
||||
} else {
|
||||
Ok(DynamicSpacingValue::Single(input.parse()?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives the spacing method for the `DynamicSpacing` enum.
|
||||
pub fn derive_spacing(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DynamicSpacingInput);
|
||||
|
||||
let spacing_ratios: Vec<_> = input
|
||||
.values
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let variant = match v {
|
||||
DynamicSpacingValue::Single(n) => {
|
||||
format_ident!("Base{:02}", n.base10_parse::<u32>().unwrap())
|
||||
}
|
||||
DynamicSpacingValue::Tuple(_, b, _) => {
|
||||
format_ident!("Base{:02}", b.base10_parse::<u32>().unwrap())
|
||||
}
|
||||
};
|
||||
match v {
|
||||
DynamicSpacingValue::Single(n) => {
|
||||
let n = n.base10_parse::<f32>().unwrap();
|
||||
quote! {
|
||||
DynamicSpacing::#variant => match ::theme::theme_settings(cx).ui_density(cx) {
|
||||
::theme::UiDensity::Compact => (#n - 4.0).max(0.0) / BASE_REM_SIZE_IN_PX,
|
||||
::theme::UiDensity::Default => #n / BASE_REM_SIZE_IN_PX,
|
||||
::theme::UiDensity::Comfortable => (#n + 4.0) / BASE_REM_SIZE_IN_PX,
|
||||
}
|
||||
}
|
||||
}
|
||||
DynamicSpacingValue::Tuple(a, b, c) => {
|
||||
let a = a.base10_parse::<f32>().unwrap();
|
||||
let b = b.base10_parse::<f32>().unwrap();
|
||||
let c = c.base10_parse::<f32>().unwrap();
|
||||
quote! {
|
||||
DynamicSpacing::#variant => match ::theme::theme_settings(cx).ui_density(cx) {
|
||||
::theme::UiDensity::Compact => #a / BASE_REM_SIZE_IN_PX,
|
||||
::theme::UiDensity::Default => #b / BASE_REM_SIZE_IN_PX,
|
||||
::theme::UiDensity::Comfortable => #c / BASE_REM_SIZE_IN_PX,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let (variant_names, doc_strings): (Vec<_>, Vec<_>) = input
|
||||
.values
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let variant = match v {
|
||||
DynamicSpacingValue::Single(n) => {
|
||||
format_ident!("Base{:02}", n.base10_parse::<u32>().unwrap())
|
||||
}
|
||||
DynamicSpacingValue::Tuple(_, b, _) => {
|
||||
format_ident!("Base{:02}", b.base10_parse::<u32>().unwrap())
|
||||
}
|
||||
};
|
||||
let doc_string = match v {
|
||||
DynamicSpacingValue::Single(n) => {
|
||||
let n = n.base10_parse::<f32>().unwrap();
|
||||
let compact = (n - 4.0).max(0.0);
|
||||
let comfortable = n + 4.0;
|
||||
format!(
|
||||
"`{}px`|`{}px`|`{}px (@16px/rem)` - Scales with the user's rem size.",
|
||||
compact, n, comfortable
|
||||
)
|
||||
}
|
||||
DynamicSpacingValue::Tuple(a, b, c) => {
|
||||
let a = a.base10_parse::<f32>().unwrap();
|
||||
let b = b.base10_parse::<f32>().unwrap();
|
||||
let c = c.base10_parse::<f32>().unwrap();
|
||||
format!(
|
||||
"`{}px`|`{}px`|`{}px (@16px/rem)` - Scales with the user's rem size.",
|
||||
a, b, c
|
||||
)
|
||||
}
|
||||
};
|
||||
(quote!(#variant), quote!(#doc_string))
|
||||
})
|
||||
.unzip();
|
||||
|
||||
let expanded = quote! {
|
||||
/// A dynamic spacing system that adjusts spacing based on
|
||||
/// [UiDensity].
|
||||
///
|
||||
/// The number following "Base" refers to the base pixel size
|
||||
/// at the default rem size and spacing settings.
|
||||
///
|
||||
/// When possible, [DynamicSpacing] should be used over manual
|
||||
/// or built-in spacing values in places dynamic spacing is needed.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum DynamicSpacing {
|
||||
#(
|
||||
#[doc = #doc_strings]
|
||||
#variant_names,
|
||||
)*
|
||||
}
|
||||
|
||||
impl DynamicSpacing {
|
||||
/// Returns the spacing ratio, should only be used internally.
|
||||
fn spacing_ratio(&self, cx: &App) -> f32 {
|
||||
const BASE_REM_SIZE_IN_PX: f32 = 16.0;
|
||||
match self {
|
||||
#(#spacing_ratios,)*
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the spacing value in rems.
|
||||
pub fn rems(&self, cx: &App) -> Rems {
|
||||
rems(self.spacing_ratio(cx))
|
||||
}
|
||||
|
||||
/// Returns the spacing value in pixels.
|
||||
pub fn px(&self, cx: &App) -> Pixels {
|
||||
let ui_font_size_f32: f32 = ::theme::theme_settings(cx).ui_font_size(cx).into();
|
||||
px(ui_font_size_f32 * self.spacing_ratio(cx))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
37
crates/ui_macros/src/ui_macros.rs
Normal file
37
crates/ui_macros/src/ui_macros.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
mod derive_register_component;
|
||||
mod dynamic_spacing;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
/// Generates the DynamicSpacing enum used for density-aware spacing in the UI.
|
||||
#[proc_macro]
|
||||
pub fn derive_dynamic_spacing(input: TokenStream) -> TokenStream {
|
||||
dynamic_spacing::derive_spacing(input)
|
||||
}
|
||||
|
||||
/// Registers components that implement the `Component` trait.
|
||||
///
|
||||
/// This proc macro is used to automatically register structs that implement
|
||||
/// the `Component` trait with the [`component::ComponentRegistry`].
|
||||
///
|
||||
/// If the component trait is not implemented, it will generate a compile-time error.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use ui::Component;
|
||||
/// use ui_macros::RegisterComponent;
|
||||
///
|
||||
/// #[derive(RegisterComponent)]
|
||||
/// struct MyComponent;
|
||||
///
|
||||
/// impl Component for MyComponent {
|
||||
/// // Component implementation
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This example will add MyComponent to the ComponentRegistry.
|
||||
#[proc_macro_derive(RegisterComponent)]
|
||||
pub fn derive_register_component(input: TokenStream) -> TokenStream {
|
||||
derive_register_component::derive_register_component(input)
|
||||
}
|
||||
Reference in New Issue
Block a user