logiguard fork: GPUI xdg-activation keyboard-focus serial fix
Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled
Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled
Single-commit orphan branch: full zed-industries/zed @ 8c74db0 source tree with a 3-file patch applied (no upstream history). Patch (crates/gpui_linux/src/linux/wayland/): - serial.rs: add SerialKind::KeyboardEnter - client.rs: store wl_keyboard.enter serial; add latest_serial_of() - window.rs: activate() uses keyboard-enter serial (Mutter focus gate) Mutter honors window activation only when the token carries the keyboard- focus serial from wl_keyboard.enter; GPUI used a stale mouse-press serial. See docs/tray-window-focus-wayland.md in logiguard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
324
crates/theme/src/theme.rs
Normal file
324
crates/theme/src/theme.rs
Normal file
@@ -0,0 +1,324 @@
|
||||
#![deny(missing_docs)]
|
||||
|
||||
//! # Theme
|
||||
//!
|
||||
//! This crate provides the theme system for Zed.
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! A theme is a collection of colors used to build a consistent appearance for UI components across the application.
|
||||
|
||||
mod default_colors;
|
||||
mod fallback_themes;
|
||||
mod font_family_cache;
|
||||
mod icon_theme;
|
||||
mod icon_theme_schema;
|
||||
mod registry;
|
||||
mod scale;
|
||||
mod schema;
|
||||
mod styles;
|
||||
mod theme_settings_provider;
|
||||
mod ui_density;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use gpui::BorrowAppContext;
|
||||
use gpui::Global;
|
||||
use gpui::{
|
||||
App, AssetSource, Hsla, Pixels, SharedString, WindowAppearance, WindowBackgroundAppearance, px,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
pub use crate::default_colors::*;
|
||||
pub use crate::fallback_themes::{apply_status_color_defaults, apply_theme_color_defaults};
|
||||
pub use crate::font_family_cache::*;
|
||||
pub use crate::icon_theme::*;
|
||||
pub use crate::icon_theme_schema::*;
|
||||
pub use crate::registry::*;
|
||||
pub use crate::scale::*;
|
||||
pub use crate::schema::*;
|
||||
pub use crate::styles::*;
|
||||
pub use crate::theme_settings_provider::*;
|
||||
pub use crate::ui_density::*;
|
||||
|
||||
/// The name of the default dark theme.
|
||||
pub const DEFAULT_DARK_THEME: &str = "One Dark";
|
||||
|
||||
/// Defines window border radius for platforms that use client side decorations.
|
||||
pub const CLIENT_SIDE_DECORATION_ROUNDING: Pixels = px(10.0);
|
||||
/// Defines window shadow size for platforms that use client side decorations.
|
||||
pub const CLIENT_SIDE_DECORATION_SHADOW: Pixels = px(10.0);
|
||||
|
||||
/// The appearance of the theme.
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Deserialize)]
|
||||
pub enum Appearance {
|
||||
/// A light appearance.
|
||||
Light,
|
||||
/// A dark appearance.
|
||||
Dark,
|
||||
}
|
||||
|
||||
impl Appearance {
|
||||
/// Returns whether the appearance is light.
|
||||
pub fn is_light(&self) -> bool {
|
||||
match self {
|
||||
Self::Light => true,
|
||||
Self::Dark => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowAppearance> for Appearance {
|
||||
fn from(value: WindowAppearance) -> Self {
|
||||
match value {
|
||||
WindowAppearance::Dark | WindowAppearance::VibrantDark => Self::Dark,
|
||||
WindowAppearance::Light | WindowAppearance::VibrantLight => Self::Light,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Which themes should be loaded. This is used primarily for testing.
|
||||
pub enum LoadThemes {
|
||||
/// Only load the base theme.
|
||||
///
|
||||
/// No user themes will be loaded.
|
||||
JustBase,
|
||||
|
||||
/// Load all of the built-in themes.
|
||||
All(Box<dyn AssetSource>),
|
||||
}
|
||||
|
||||
/// Initialize the theme system with default themes.
|
||||
///
|
||||
/// This sets up the [`ThemeRegistry`], [`FontFamilyCache`], [`SystemAppearance`],
|
||||
/// and [`GlobalTheme`] with the default dark theme. It does NOT load bundled
|
||||
/// themes from JSON or integrate with settings — use `theme_settings::init` for that.
|
||||
pub fn init(themes_to_load: LoadThemes, cx: &mut App) {
|
||||
SystemAppearance::init(cx);
|
||||
let assets = match themes_to_load {
|
||||
LoadThemes::JustBase => Box::new(()) as Box<dyn AssetSource>,
|
||||
LoadThemes::All(assets) => assets,
|
||||
};
|
||||
ThemeRegistry::set_global(assets, cx);
|
||||
FontFamilyCache::init_global(cx);
|
||||
|
||||
let themes = ThemeRegistry::default_global(cx);
|
||||
let theme = themes.get(DEFAULT_DARK_THEME).unwrap_or_else(|_| {
|
||||
themes
|
||||
.list()
|
||||
.into_iter()
|
||||
.next()
|
||||
.map(|m| themes.get(&m.name).unwrap())
|
||||
.unwrap()
|
||||
});
|
||||
let icon_theme = themes.default_icon_theme().unwrap();
|
||||
cx.set_global(GlobalTheme { theme, icon_theme });
|
||||
}
|
||||
|
||||
/// Implementing this trait allows accessing the active theme.
|
||||
pub trait ActiveTheme {
|
||||
/// Returns the active theme.
|
||||
fn theme(&self) -> &Arc<Theme>;
|
||||
}
|
||||
|
||||
impl ActiveTheme for App {
|
||||
fn theme(&self) -> &Arc<Theme> {
|
||||
GlobalTheme::theme(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// The appearance of the system.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct SystemAppearance(pub Appearance);
|
||||
|
||||
impl std::ops::Deref for SystemAppearance {
|
||||
type Target = Appearance;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SystemAppearance {
|
||||
fn default() -> Self {
|
||||
Self(Appearance::Dark)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct GlobalSystemAppearance(SystemAppearance);
|
||||
|
||||
impl std::ops::DerefMut for GlobalSystemAppearance {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for GlobalSystemAppearance {
|
||||
type Target = SystemAppearance;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Global for GlobalSystemAppearance {}
|
||||
|
||||
impl SystemAppearance {
|
||||
/// Initializes the [`SystemAppearance`] for the application.
|
||||
pub fn init(cx: &mut App) {
|
||||
*cx.default_global::<GlobalSystemAppearance>() =
|
||||
GlobalSystemAppearance(SystemAppearance(cx.window_appearance().into()));
|
||||
}
|
||||
|
||||
/// Returns the global [`SystemAppearance`].
|
||||
pub fn global(cx: &App) -> Self {
|
||||
cx.global::<GlobalSystemAppearance>().0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the global [`SystemAppearance`].
|
||||
pub fn global_mut(cx: &mut App) -> &mut Self {
|
||||
cx.global_mut::<GlobalSystemAppearance>()
|
||||
}
|
||||
}
|
||||
|
||||
/// A theme family is a grouping of themes under a single name.
|
||||
///
|
||||
/// For example, the "One" theme family contains the "One Light" and "One Dark" themes.
|
||||
///
|
||||
/// It can also be used to package themes with many variants.
|
||||
///
|
||||
/// For example, the "Atelier" theme family contains "Cave", "Dune", "Estuary", "Forest", "Heath", etc.
|
||||
pub struct ThemeFamily {
|
||||
/// The unique identifier for the theme family.
|
||||
pub id: String,
|
||||
/// The name of the theme family. This will be displayed in the UI, such as when adding or removing a theme family.
|
||||
pub name: SharedString,
|
||||
/// The author of the theme family.
|
||||
pub author: SharedString,
|
||||
/// The [Theme]s in the family.
|
||||
pub themes: Vec<Theme>,
|
||||
/// The color scales used by the themes in the family.
|
||||
/// Note: This will be removed in the future.
|
||||
pub scales: ColorScales,
|
||||
}
|
||||
|
||||
/// A theme is the primary mechanism for defining the appearance of the UI.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Theme {
|
||||
/// The unique identifier for the theme.
|
||||
pub id: String,
|
||||
/// The name of the theme.
|
||||
pub name: SharedString,
|
||||
/// The appearance of the theme (light or dark).
|
||||
pub appearance: Appearance,
|
||||
/// The colors and other styles for the theme.
|
||||
pub styles: ThemeStyles,
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
/// Returns the [`SystemColors`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn system(&self) -> &SystemColors {
|
||||
&self.styles.system
|
||||
}
|
||||
|
||||
/// Returns the [`AccentColors`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn accents(&self) -> &AccentColors {
|
||||
&self.styles.accents
|
||||
}
|
||||
|
||||
/// Returns the [`PlayerColors`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn players(&self) -> &PlayerColors {
|
||||
&self.styles.player
|
||||
}
|
||||
|
||||
/// Returns the [`ThemeColors`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn colors(&self) -> &ThemeColors {
|
||||
&self.styles.colors
|
||||
}
|
||||
|
||||
/// Returns the [`SyntaxTheme`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn syntax(&self) -> &Arc<SyntaxTheme> {
|
||||
&self.styles.syntax
|
||||
}
|
||||
|
||||
/// Returns the [`StatusColors`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn status(&self) -> &StatusColors {
|
||||
&self.styles.status
|
||||
}
|
||||
|
||||
/// Returns the [`Appearance`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn appearance(&self) -> Appearance {
|
||||
self.appearance
|
||||
}
|
||||
|
||||
/// Returns the [`WindowBackgroundAppearance`] for the theme.
|
||||
#[inline(always)]
|
||||
pub fn window_background_appearance(&self) -> WindowBackgroundAppearance {
|
||||
self.styles.window_background_appearance
|
||||
}
|
||||
|
||||
/// Darkens the color by reducing its lightness.
|
||||
/// The resulting lightness is clamped to ensure it doesn't go below 0.0.
|
||||
///
|
||||
/// The first value darkens light appearance mode, the second darkens appearance dark mode.
|
||||
///
|
||||
/// Note: This is a tentative solution and may be replaced with a more robust color system.
|
||||
pub fn darken(&self, color: Hsla, light_amount: f32, dark_amount: f32) -> Hsla {
|
||||
let amount = match self.appearance {
|
||||
Appearance::Light => light_amount,
|
||||
Appearance::Dark => dark_amount,
|
||||
};
|
||||
let mut hsla = color;
|
||||
hsla.l = (hsla.l - amount).max(0.0);
|
||||
hsla
|
||||
}
|
||||
}
|
||||
|
||||
/// Deserializes an icon theme from the given bytes.
|
||||
pub fn deserialize_icon_theme(bytes: &[u8]) -> anyhow::Result<IconThemeFamilyContent> {
|
||||
let icon_theme_family: IconThemeFamilyContent = serde_json_lenient::from_slice(bytes)?;
|
||||
|
||||
Ok(icon_theme_family)
|
||||
}
|
||||
|
||||
/// The active theme.
|
||||
pub struct GlobalTheme {
|
||||
theme: Arc<Theme>,
|
||||
icon_theme: Arc<IconTheme>,
|
||||
}
|
||||
impl Global for GlobalTheme {}
|
||||
|
||||
impl GlobalTheme {
|
||||
/// Creates a new [`GlobalTheme`] with the given theme and icon theme.
|
||||
pub fn new(theme: Arc<Theme>, icon_theme: Arc<IconTheme>) -> Self {
|
||||
Self { theme, icon_theme }
|
||||
}
|
||||
|
||||
/// Updates the active theme.
|
||||
pub fn update_theme(cx: &mut App, theme: Arc<Theme>) {
|
||||
cx.update_global::<Self, _>(|this, _| this.theme = theme);
|
||||
}
|
||||
|
||||
/// Updates the active icon theme.
|
||||
pub fn update_icon_theme(cx: &mut App, icon_theme: Arc<IconTheme>) {
|
||||
cx.update_global::<Self, _>(|this, _| this.icon_theme = icon_theme);
|
||||
}
|
||||
|
||||
/// Returns the active theme.
|
||||
pub fn theme(cx: &App) -> &Arc<Theme> {
|
||||
&cx.global::<Self>().theme
|
||||
}
|
||||
|
||||
/// Returns the active icon theme.
|
||||
pub fn icon_theme(cx: &App) -> &Arc<IconTheme> {
|
||||
&cx.global::<Self>().icon_theme
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user