mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
gpui: Add support for window transparency & blur on macOS (#9610)
This PR adds support for transparent and blurred window backgrounds on macOS. Release Notes: - Added support for transparent and blurred window backgrounds on macOS ([#5040](https://github.com/zed-industries/zed/issues/5040)). - This requires themes to specify a new `background.appearance` key ("opaque", "transparent" or "blurred") and to include an alpha value in colors that should be transparent. <img width="913" alt="image" src="https://github.com/zed-industries/zed/assets/2588851/7547ee2a-e376-4d55-9114-e6fc2f5110bc"> <img width="994" alt="image" src="https://github.com/zed-industries/zed/assets/2588851/b36fbc14-6e4d-4140-9448-69cad803c45a"> <img width="1020" alt="image" src="https://github.com/zed-industries/zed/assets/2588851/d70e2005-54fd-4991-a211-ed484ccf26ef"> --------- Co-authored-by: Luiz Marcondes <luizgustavodevergennes@gmail.com> Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
1360dffead
commit
49144d94bf
@ -13,8 +13,8 @@ use call::{report_call_event_for_room, ActiveCall};
|
|||||||
pub use collab_panel::CollabPanel;
|
pub use collab_panel::CollabPanel;
|
||||||
pub use collab_titlebar_item::CollabTitlebarItem;
|
pub use collab_titlebar_item::CollabTitlebarItem;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, point, AppContext, DevicePixels, Pixels, PlatformDisplay, Size, Task, WindowContext,
|
actions, point, AppContext, DevicePixels, Pixels, PlatformDisplay, Size, Task,
|
||||||
WindowKind, WindowOptions,
|
WindowBackgroundAppearance, WindowContext, WindowKind, WindowOptions,
|
||||||
};
|
};
|
||||||
use panel_settings::MessageEditorSettings;
|
use panel_settings::MessageEditorSettings;
|
||||||
pub use panel_settings::{
|
pub use panel_settings::{
|
||||||
@ -121,5 +121,6 @@ fn notification_window_options(
|
|||||||
is_movable: false,
|
is_movable: false,
|
||||||
display_id: Some(screen.id()),
|
display_id: Some(screen.id()),
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
|
window_background: WindowBackgroundAppearance::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ fn main() {
|
|||||||
display_id: Some(screen.id()),
|
display_id: Some(screen.id()),
|
||||||
|
|
||||||
titlebar: None,
|
titlebar: None,
|
||||||
|
window_background: WindowBackgroundAppearance::default(),
|
||||||
focus: false,
|
focus: false,
|
||||||
show: true,
|
show: true,
|
||||||
kind: WindowKind::PopUp,
|
kind: WindowKind::PopUp,
|
||||||
|
@ -190,6 +190,7 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
|
|||||||
fn activate(&self);
|
fn activate(&self);
|
||||||
fn is_active(&self) -> bool;
|
fn is_active(&self) -> bool;
|
||||||
fn set_title(&mut self, title: &str);
|
fn set_title(&mut self, title: &str);
|
||||||
|
fn set_background_appearance(&mut self, background_appearance: WindowBackgroundAppearance);
|
||||||
fn set_edited(&mut self, edited: bool);
|
fn set_edited(&mut self, edited: bool);
|
||||||
fn show_character_palette(&self);
|
fn show_character_palette(&self);
|
||||||
fn minimize(&self);
|
fn minimize(&self);
|
||||||
@ -533,6 +534,9 @@ pub struct WindowOptions {
|
|||||||
/// The display to create the window on, if this is None,
|
/// The display to create the window on, if this is None,
|
||||||
/// the window will be created on the main display
|
/// the window will be created on the main display
|
||||||
pub display_id: Option<DisplayId>,
|
pub display_id: Option<DisplayId>,
|
||||||
|
|
||||||
|
/// The appearance of the window background.
|
||||||
|
pub window_background: WindowBackgroundAppearance,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The variables that can be configured when creating a new window
|
/// The variables that can be configured when creating a new window
|
||||||
@ -555,6 +559,8 @@ pub(crate) struct WindowParams {
|
|||||||
pub show: bool,
|
pub show: bool,
|
||||||
|
|
||||||
pub display_id: Option<DisplayId>,
|
pub display_id: Option<DisplayId>,
|
||||||
|
|
||||||
|
pub window_background: WindowBackgroundAppearance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WindowOptions {
|
impl Default for WindowOptions {
|
||||||
@ -572,6 +578,7 @@ impl Default for WindowOptions {
|
|||||||
is_movable: true,
|
is_movable: true,
|
||||||
display_id: None,
|
display_id: None,
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
|
window_background: WindowBackgroundAppearance::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -633,6 +640,27 @@ impl Default for WindowAppearance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The appearance of the background of the window itself, when there is
|
||||||
|
/// no content or the content is transparent.
|
||||||
|
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||||
|
pub enum WindowBackgroundAppearance {
|
||||||
|
/// Opaque.
|
||||||
|
///
|
||||||
|
/// This lets the window manager know that content behind this
|
||||||
|
/// window does not need to be drawn.
|
||||||
|
///
|
||||||
|
/// Actual color depends on the system and themes should define a fully
|
||||||
|
/// opaque background color instead.
|
||||||
|
#[default]
|
||||||
|
Opaque,
|
||||||
|
/// Plain alpha transparency.
|
||||||
|
Transparent,
|
||||||
|
/// Transparency, but the contents behind the window are blurred.
|
||||||
|
///
|
||||||
|
/// Not always supported.
|
||||||
|
Blurred,
|
||||||
|
}
|
||||||
|
|
||||||
/// The options that can be configured for a file dialog prompt
|
/// The options that can be configured for a file dialog prompt
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct PathPromptOptions {
|
pub struct PathPromptOptions {
|
||||||
|
@ -23,7 +23,7 @@ use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow};
|
|||||||
use crate::scene::Scene;
|
use crate::scene::Scene;
|
||||||
use crate::{
|
use crate::{
|
||||||
px, size, Bounds, DevicePixels, Modifiers, Pixels, PlatformDisplay, PlatformInput, Point,
|
px, size, Bounds, DevicePixels, Modifiers, Pixels, PlatformDisplay, PlatformInput, Point,
|
||||||
PromptLevel, Size, WindowAppearance, WindowParams,
|
PromptLevel, Size, WindowAppearance, WindowBackgroundAppearance, WindowParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -355,6 +355,10 @@ impl PlatformWindow for WaylandWindow {
|
|||||||
self.0.toplevel.set_title(title.to_string());
|
self.0.toplevel.set_title(title.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_background_appearance(&mut self, _background_appearance: WindowBackgroundAppearance) {
|
||||||
|
// todo(linux)
|
||||||
|
}
|
||||||
|
|
||||||
fn set_edited(&mut self, edited: bool) {
|
fn set_edited(&mut self, edited: bool) {
|
||||||
// todo(linux)
|
// todo(linux)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
platform::blade::BladeRenderer, size, Bounds, DevicePixels, Modifiers, Pixels, PlatformAtlas,
|
platform::blade::BladeRenderer, size, Bounds, DevicePixels, Modifiers, Pixels, PlatformAtlas,
|
||||||
PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PromptLevel,
|
PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PromptLevel,
|
||||||
Scene, Size, WindowAppearance, WindowOptions, WindowParams,
|
Scene, Size, WindowAppearance, WindowBackgroundAppearance, WindowOptions, WindowParams,
|
||||||
};
|
};
|
||||||
use blade_graphics as gpu;
|
use blade_graphics as gpu;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@ -423,6 +423,10 @@ impl PlatformWindow for X11Window {
|
|||||||
// todo(linux)
|
// todo(linux)
|
||||||
fn set_edited(&mut self, edited: bool) {}
|
fn set_edited(&mut self, edited: bool) {}
|
||||||
|
|
||||||
|
fn set_background_appearance(&mut self, _background_appearance: WindowBackgroundAppearance) {
|
||||||
|
// todo(linux)
|
||||||
|
}
|
||||||
|
|
||||||
// todo(linux), this corresponds to `orderFrontCharacterPalette` on macOS,
|
// todo(linux), this corresponds to `orderFrontCharacterPalette` on macOS,
|
||||||
// but it looks like the equivalent for Linux is GTK specific:
|
// but it looks like the equivalent for Linux is GTK specific:
|
||||||
//
|
//
|
||||||
|
@ -73,7 +73,7 @@ impl MetalRenderer {
|
|||||||
let layer = metal::MetalLayer::new();
|
let layer = metal::MetalLayer::new();
|
||||||
layer.set_device(&device);
|
layer.set_device(&device);
|
||||||
layer.set_pixel_format(MTLPixelFormat::RGBA8Unorm);
|
layer.set_pixel_format(MTLPixelFormat::RGBA8Unorm);
|
||||||
layer.set_opaque(true);
|
layer.set_opaque(false);
|
||||||
layer.set_maximum_drawable_count(3);
|
layer.set_maximum_drawable_count(3);
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![&*layer, setAllowsNextDrawableTimeout: NO];
|
let _: () = msg_send![&*layer, setAllowsNextDrawableTimeout: NO];
|
||||||
|
@ -4,12 +4,12 @@ use crate::{
|
|||||||
DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke,
|
DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke,
|
||||||
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||||
Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel,
|
Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel,
|
||||||
Size, Timer, WindowAppearance, WindowKind, WindowParams,
|
Size, Timer, WindowAppearance, WindowBackgroundAppearance, WindowKind, WindowParams,
|
||||||
};
|
};
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{
|
appkit::{
|
||||||
CGPoint, NSApplication, NSBackingStoreBuffered, NSEventModifierFlags,
|
CGPoint, NSApplication, NSBackingStoreBuffered, NSColor, NSEvent, NSEventModifierFlags,
|
||||||
NSFilenamesPboardType, NSPasteboard, NSScreen, NSView, NSViewHeightSizable,
|
NSFilenamesPboardType, NSPasteboard, NSScreen, NSView, NSViewHeightSizable,
|
||||||
NSViewWidthSizable, NSWindow, NSWindowButton, NSWindowCollectionBehavior,
|
NSViewWidthSizable, NSWindow, NSWindowButton, NSWindowCollectionBehavior,
|
||||||
NSWindowOcclusionState, NSWindowStyleMask, NSWindowTitleVisibility,
|
NSWindowOcclusionState, NSWindowStyleMask, NSWindowTitleVisibility,
|
||||||
@ -83,6 +83,17 @@ const NSDragOperationNone: NSDragOperation = 0;
|
|||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const NSDragOperationCopy: NSDragOperation = 1;
|
const NSDragOperationCopy: NSDragOperation = 1;
|
||||||
|
|
||||||
|
#[link(name = "CoreGraphics", kind = "framework")]
|
||||||
|
extern "C" {
|
||||||
|
// Widely used private APIs; Apple uses them for their Terminal.app.
|
||||||
|
fn CGSMainConnectionID() -> id;
|
||||||
|
fn CGSSetWindowBackgroundBlurRadius(
|
||||||
|
connection_id: id,
|
||||||
|
window_id: NSInteger,
|
||||||
|
radius: i64,
|
||||||
|
) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
#[ctor]
|
#[ctor]
|
||||||
unsafe fn build_classes() {
|
unsafe fn build_classes() {
|
||||||
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
|
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
|
||||||
@ -509,6 +520,7 @@ impl MacWindow {
|
|||||||
pub fn open(
|
pub fn open(
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
WindowParams {
|
WindowParams {
|
||||||
|
window_background,
|
||||||
bounds,
|
bounds,
|
||||||
titlebar,
|
titlebar,
|
||||||
kind,
|
kind,
|
||||||
@ -606,7 +618,7 @@ impl MacWindow {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let window = Self(Arc::new(Mutex::new(MacWindowState {
|
let mut window = Self(Arc::new(Mutex::new(MacWindowState {
|
||||||
handle,
|
handle,
|
||||||
executor,
|
executor,
|
||||||
native_window,
|
native_window,
|
||||||
@ -685,6 +697,8 @@ impl MacWindow {
|
|||||||
native_window.setContentView_(native_view.autorelease());
|
native_window.setContentView_(native_view.autorelease());
|
||||||
native_window.makeFirstResponder_(native_view);
|
native_window.makeFirstResponder_(native_view);
|
||||||
|
|
||||||
|
window.set_background_appearance(window_background);
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
WindowKind::Normal => {
|
WindowKind::Normal => {
|
||||||
native_window.setLevel_(NSNormalWindowLevel);
|
native_window.setLevel_(NSNormalWindowLevel);
|
||||||
@ -967,6 +981,31 @@ impl PlatformWindow for MacWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_background_appearance(&mut self, background_appearance: WindowBackgroundAppearance) {
|
||||||
|
let this = self.0.as_ref().lock();
|
||||||
|
let blur_radius = if background_appearance == WindowBackgroundAppearance::Blurred {
|
||||||
|
80
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let opaque = if background_appearance == WindowBackgroundAppearance::Opaque {
|
||||||
|
YES
|
||||||
|
} else {
|
||||||
|
NO
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
this.native_window.setOpaque_(opaque);
|
||||||
|
let clear_color = if opaque == YES {
|
||||||
|
NSColor::colorWithSRGBRed_green_blue_alpha_(nil, 0f64, 0f64, 0f64, 1f64)
|
||||||
|
} else {
|
||||||
|
NSColor::clearColor(nil)
|
||||||
|
};
|
||||||
|
this.native_window.setBackgroundColor_(clear_color);
|
||||||
|
let window_number = this.native_window.windowNumber();
|
||||||
|
CGSSetWindowBackgroundBlurRadius(CGSMainConnectionID(), window_number, blur_radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_edited(&mut self, edited: bool) {
|
fn set_edited(&mut self, edited: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let window = self.0.lock().native_window;
|
let window = self.0.lock().native_window;
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DevicePixels,
|
AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DevicePixels,
|
||||||
DispatchEventResult, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
DispatchEventResult, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
|
||||||
PlatformInputHandler, PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance,
|
PlatformInputHandler, PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance,
|
||||||
WindowParams,
|
WindowBackgroundAppearance, WindowParams,
|
||||||
};
|
};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@ -190,6 +190,10 @@ impl PlatformWindow for TestWindow {
|
|||||||
self.0.lock().title = Some(title.to_owned());
|
self.0.lock().title = Some(title.to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_background_appearance(&mut self, _background: WindowBackgroundAppearance) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_edited(&mut self, edited: bool) {
|
fn set_edited(&mut self, edited: bool) {
|
||||||
self.0.lock().edited = edited;
|
self.0.lock().edited = edited;
|
||||||
}
|
}
|
||||||
|
@ -1468,6 +1468,10 @@ impl PlatformWindow for WindowsWindow {
|
|||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_background_appearance(&mut self, _background_appearance: WindowBackgroundAppearance) {
|
||||||
|
// todo(windows)
|
||||||
|
}
|
||||||
|
|
||||||
// todo(windows)
|
// todo(windows)
|
||||||
fn set_edited(&mut self, _edited: bool) {}
|
fn set_edited(&mut self, _edited: bool) {}
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ use crate::{
|
|||||||
Modifiers, ModifiersChangedEvent, MouseButton, MouseMoveEvent, MouseUpEvent, Pixels,
|
Modifiers, ModifiersChangedEvent, MouseButton, MouseMoveEvent, MouseUpEvent, Pixels,
|
||||||
PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel, Render,
|
PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point, PromptLevel, Render,
|
||||||
ScaledPixels, SharedString, Size, SubscriberSet, Subscription, TaffyLayoutEngine, Task,
|
ScaledPixels, SharedString, Size, SubscriberSet, Subscription, TaffyLayoutEngine, Task,
|
||||||
TextStyle, TextStyleRefinement, View, VisualContext, WeakView, WindowAppearance, WindowOptions,
|
TextStyle, TextStyleRefinement, View, VisualContext, WeakView, WindowAppearance,
|
||||||
WindowParams, WindowTextSystem,
|
WindowBackgroundAppearance, WindowOptions, WindowParams, WindowTextSystem,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
use collections::FxHashSet;
|
use collections::FxHashSet;
|
||||||
@ -398,6 +398,7 @@ impl Window {
|
|||||||
is_movable,
|
is_movable,
|
||||||
display_id,
|
display_id,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
|
window_background,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
let bounds = bounds.unwrap_or_else(|| default_bounds(display_id, cx));
|
let bounds = bounds.unwrap_or_else(|| default_bounds(display_id, cx));
|
||||||
@ -411,6 +412,7 @@ impl Window {
|
|||||||
focus,
|
focus,
|
||||||
show,
|
show,
|
||||||
display_id,
|
display_id,
|
||||||
|
window_background,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let display_id = platform_window.display().id();
|
let display_id = platform_window.display().id();
|
||||||
@ -872,7 +874,7 @@ impl<'a> WindowContext<'a> {
|
|||||||
self.window.platform_window.bounds()
|
self.window.platform_window.bounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retusn whether or not the window is currently fullscreen
|
/// Returns whether or not the window is currently fullscreen
|
||||||
pub fn is_fullscreen(&self) -> bool {
|
pub fn is_fullscreen(&self) -> bool {
|
||||||
self.window.platform_window.is_fullscreen()
|
self.window.platform_window.is_fullscreen()
|
||||||
}
|
}
|
||||||
@ -911,6 +913,13 @@ impl<'a> WindowContext<'a> {
|
|||||||
self.window.platform_window.set_title(title);
|
self.window.platform_window.set_title(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the window background appearance.
|
||||||
|
pub fn set_background_appearance(&mut self, background_appearance: WindowBackgroundAppearance) {
|
||||||
|
self.window
|
||||||
|
.platform_window
|
||||||
|
.set_background_appearance(background_appearance);
|
||||||
|
}
|
||||||
|
|
||||||
/// Mark the window as dirty at the platform level.
|
/// Mark the window as dirty at the platform level.
|
||||||
pub fn set_window_edited(&mut self, edited: bool) {
|
pub fn set_window_edited(&mut self, edited: bool) {
|
||||||
self.window.platform_window.set_edited(edited);
|
self.window.platform_window.set_edited(edited);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use gpui::WindowBackgroundAppearance;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -15,6 +17,7 @@ fn zed_pro_daylight() -> Theme {
|
|||||||
name: "Zed Pro Daylight".into(),
|
name: "Zed Pro Daylight".into(),
|
||||||
appearance: Appearance::Light,
|
appearance: Appearance::Light,
|
||||||
styles: ThemeStyles {
|
styles: ThemeStyles {
|
||||||
|
window_background_appearance: WindowBackgroundAppearance::Opaque,
|
||||||
system: SystemColors::default(),
|
system: SystemColors::default(),
|
||||||
colors: ThemeColors::light(),
|
colors: ThemeColors::light(),
|
||||||
status: StatusColors::light(),
|
status: StatusColors::light(),
|
||||||
@ -45,6 +48,7 @@ pub(crate) fn zed_pro_moonlight() -> Theme {
|
|||||||
name: "Zed Pro Moonlight".into(),
|
name: "Zed Pro Moonlight".into(),
|
||||||
appearance: Appearance::Dark,
|
appearance: Appearance::Dark,
|
||||||
styles: ThemeStyles {
|
styles: ThemeStyles {
|
||||||
|
window_background_appearance: WindowBackgroundAppearance::Opaque,
|
||||||
system: SystemColors::default(),
|
system: SystemColors::default(),
|
||||||
colors: ThemeColors::dark(),
|
colors: ThemeColors::dark(),
|
||||||
status: StatusColors::dark(),
|
status: StatusColors::dark(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gpui::{hsla, FontStyle, FontWeight, HighlightStyle};
|
use gpui::{hsla, FontStyle, FontWeight, HighlightStyle, WindowBackgroundAppearance};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
default_color_scales, Appearance, PlayerColors, StatusColors, SyntaxTheme, SystemColors, Theme,
|
default_color_scales, Appearance, PlayerColors, StatusColors, SyntaxTheme, SystemColors, Theme,
|
||||||
@ -39,8 +39,8 @@ pub(crate) fn one_dark() -> Theme {
|
|||||||
id: "one_dark".to_string(),
|
id: "one_dark".to_string(),
|
||||||
name: "One Dark".into(),
|
name: "One Dark".into(),
|
||||||
appearance: Appearance::Dark,
|
appearance: Appearance::Dark,
|
||||||
|
|
||||||
styles: ThemeStyles {
|
styles: ThemeStyles {
|
||||||
|
window_background_appearance: WindowBackgroundAppearance::Opaque,
|
||||||
system: SystemColors::default(),
|
system: SystemColors::default(),
|
||||||
colors: ThemeColors {
|
colors: ThemeColors {
|
||||||
border: hsla(225. / 360., 13. / 100., 12. / 100., 1.),
|
border: hsla(225. / 360., 13. / 100., 12. / 100., 1.),
|
||||||
|
@ -122,6 +122,13 @@ impl ThemeRegistry {
|
|||||||
AppearanceContent::Light => SyntaxTheme::light(),
|
AppearanceContent::Light => SyntaxTheme::light(),
|
||||||
AppearanceContent::Dark => SyntaxTheme::dark(),
|
AppearanceContent::Dark => SyntaxTheme::dark(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let window_background_appearance = user_theme
|
||||||
|
.style
|
||||||
|
.window_background_appearance
|
||||||
|
.map(Into::into)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
if !user_theme.style.syntax.is_empty() {
|
if !user_theme.style.syntax.is_empty() {
|
||||||
syntax_colors.highlights = user_theme
|
syntax_colors.highlights = user_theme
|
||||||
.style
|
.style
|
||||||
@ -153,6 +160,7 @@ impl ThemeRegistry {
|
|||||||
},
|
},
|
||||||
styles: ThemeStyles {
|
styles: ThemeStyles {
|
||||||
system: SystemColors::default(),
|
system: SystemColors::default(),
|
||||||
|
window_background_appearance,
|
||||||
colors: theme_colors,
|
colors: theme_colors,
|
||||||
status: status_colors,
|
status: status_colors,
|
||||||
player: player_colors,
|
player: player_colors,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gpui::{FontStyle, FontWeight, HighlightStyle, Hsla};
|
use gpui::{FontStyle, FontWeight, HighlightStyle, Hsla, WindowBackgroundAppearance};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use palette::FromColor;
|
use palette::FromColor;
|
||||||
use schemars::gen::SchemaGenerator;
|
use schemars::gen::SchemaGenerator;
|
||||||
@ -33,6 +33,25 @@ pub enum AppearanceContent {
|
|||||||
Dark,
|
Dark,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The background appearance of the window.
|
||||||
|
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum WindowBackgroundContent {
|
||||||
|
Opaque,
|
||||||
|
Transparent,
|
||||||
|
Blurred,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WindowBackgroundContent> for WindowBackgroundAppearance {
|
||||||
|
fn from(value: WindowBackgroundContent) -> Self {
|
||||||
|
match value {
|
||||||
|
WindowBackgroundContent::Opaque => WindowBackgroundAppearance::Opaque,
|
||||||
|
WindowBackgroundContent::Transparent => WindowBackgroundAppearance::Transparent,
|
||||||
|
WindowBackgroundContent::Blurred => WindowBackgroundAppearance::Blurred,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The content of a serialized theme family.
|
/// The content of a serialized theme family.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct ThemeFamilyContent {
|
pub struct ThemeFamilyContent {
|
||||||
@ -53,6 +72,9 @@ pub struct ThemeContent {
|
|||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct ThemeStyleContent {
|
pub struct ThemeStyleContent {
|
||||||
|
#[serde(default, rename = "background.appearance")]
|
||||||
|
pub window_background_appearance: Option<WindowBackgroundContent>,
|
||||||
|
|
||||||
#[serde(flatten, default)]
|
#[serde(flatten, default)]
|
||||||
pub colors: ThemeColorsContent,
|
pub colors: ThemeColorsContent,
|
||||||
|
|
||||||
|
@ -244,6 +244,12 @@ impl ThemeSettings {
|
|||||||
if let Some(theme_overrides) = &self.theme_overrides {
|
if let Some(theme_overrides) = &self.theme_overrides {
|
||||||
let mut base_theme = (*self.active_theme).clone();
|
let mut base_theme = (*self.active_theme).clone();
|
||||||
|
|
||||||
|
if let Some(window_background_appearance) = theme_overrides.window_background_appearance
|
||||||
|
{
|
||||||
|
base_theme.styles.window_background_appearance =
|
||||||
|
window_background_appearance.into();
|
||||||
|
}
|
||||||
|
|
||||||
base_theme
|
base_theme
|
||||||
.styles
|
.styles
|
||||||
.colors
|
.colors
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use gpui::Hsla;
|
use gpui::{Hsla, WindowBackgroundAppearance};
|
||||||
use refineable::Refineable;
|
use refineable::Refineable;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -235,6 +235,8 @@ pub struct ThemeColors {
|
|||||||
|
|
||||||
#[derive(Refineable, Clone)]
|
#[derive(Refineable, Clone)]
|
||||||
pub struct ThemeStyles {
|
pub struct ThemeStyles {
|
||||||
|
/// The background appearance of the window.
|
||||||
|
pub window_background_appearance: WindowBackgroundAppearance,
|
||||||
pub system: SystemColors,
|
pub system: SystemColors,
|
||||||
/// An array of colors used for theme elements that iterate through a series of colors.
|
/// An array of colors used for theme elements that iterate through a series of colors.
|
||||||
///
|
///
|
||||||
|
@ -27,7 +27,9 @@ pub use schema::*;
|
|||||||
pub use settings::*;
|
pub use settings::*;
|
||||||
pub use styles::*;
|
pub use styles::*;
|
||||||
|
|
||||||
use gpui::{AppContext, AssetSource, Hsla, SharedString, WindowAppearance};
|
use gpui::{
|
||||||
|
AppContext, AssetSource, Hsla, SharedString, WindowAppearance, WindowBackgroundAppearance,
|
||||||
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy, Deserialize)]
|
#[derive(Debug, PartialEq, Clone, Copy, Deserialize)]
|
||||||
@ -158,6 +160,12 @@ impl Theme {
|
|||||||
pub fn appearance(&self) -> Appearance {
|
pub fn appearance(&self) -> 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn color_alpha(color: Hsla, alpha: f32) -> Hsla {
|
pub fn color_alpha(color: Hsla, alpha: f32) -> Hsla {
|
||||||
|
@ -56,6 +56,7 @@ impl VsCodeThemeConverter {
|
|||||||
name: self.theme_metadata.name,
|
name: self.theme_metadata.name,
|
||||||
appearance,
|
appearance,
|
||||||
style: ThemeStyleContent {
|
style: ThemeStyleContent {
|
||||||
|
window_background_appearance: Some(theme::WindowBackgroundContent::Opaque),
|
||||||
colors: theme_colors,
|
colors: theme_colors,
|
||||||
status: status_colors,
|
status: status_colors,
|
||||||
players: Vec::new(),
|
players: Vec::new(),
|
||||||
|
@ -208,12 +208,21 @@ fn main() {
|
|||||||
watch_file_types(fs.clone(), cx);
|
watch_file_types(fs.clone(), cx);
|
||||||
|
|
||||||
languages.set_theme(cx.theme().clone());
|
languages.set_theme(cx.theme().clone());
|
||||||
|
|
||||||
cx.observe_global::<SettingsStore>({
|
cx.observe_global::<SettingsStore>({
|
||||||
let languages = languages.clone();
|
let languages = languages.clone();
|
||||||
let http = http.clone();
|
let http = http.clone();
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
|
|
||||||
move |cx| {
|
move |cx| {
|
||||||
|
for &mut window in cx.windows().iter_mut() {
|
||||||
|
let background_appearance = cx.theme().window_background_appearance();
|
||||||
|
window
|
||||||
|
.update(cx, |_, cx| {
|
||||||
|
cx.set_background_appearance(background_appearance)
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
languages.set_theme(cx.theme().clone());
|
languages.set_theme(cx.theme().clone());
|
||||||
let new_host = &client::ClientSettings::get_global(cx).server_url;
|
let new_host = &client::ClientSettings::get_global(cx).server_url;
|
||||||
if &http.base_url() != new_host {
|
if &http.base_url() != new_host {
|
||||||
|
@ -34,6 +34,7 @@ use task::{
|
|||||||
oneshot_source::OneshotSource,
|
oneshot_source::OneshotSource,
|
||||||
static_source::{StaticSource, TrackedFile},
|
static_source::{StaticSource, TrackedFile},
|
||||||
};
|
};
|
||||||
|
use theme::ActiveTheme;
|
||||||
|
|
||||||
use terminal_view::terminal_panel::{self, TerminalPanel};
|
use terminal_view::terminal_panel::{self, TerminalPanel};
|
||||||
use util::{
|
use util::{
|
||||||
@ -104,6 +105,7 @@ pub fn build_window_options(display_uuid: Option<Uuid>, cx: &mut AppContext) ->
|
|||||||
is_movable: true,
|
is_movable: true,
|
||||||
display_id: display.map(|display| display.id()),
|
display_id: display.map(|display| display.id()),
|
||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
|
window_background: cx.theme().window_background_appearance(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user