Refresh windows when OS appearance changes
This commit is contained in:
parent
0f9ff57568
commit
f67e2bea29
14 changed files with 304 additions and 67 deletions
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{elements::*, Entity, RenderContext, View};
|
use gpui::{color::Color, elements::*, Appearance, Entity, RenderContext, View};
|
||||||
|
|
||||||
pub struct ContactsStatusItem;
|
pub struct ContactsStatusItem;
|
||||||
|
|
||||||
|
@ -11,8 +11,15 @@ impl View for ContactsStatusItem {
|
||||||
"ContactsStatusItem"
|
"ContactsStatusItem"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
|
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
Svg::new("icons/zed_22.svg").aligned().boxed()
|
let color = match cx.appearance {
|
||||||
|
Appearance::Light | Appearance::VibrantLight => Color::black(),
|
||||||
|
Appearance::Dark | Appearance::VibrantDark => Color::white(),
|
||||||
|
};
|
||||||
|
Svg::new("icons/zed_22.svg")
|
||||||
|
.with_color(color)
|
||||||
|
.aligned()
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1149,7 +1149,7 @@ mod tests {
|
||||||
editor: &ViewHandle<Editor>,
|
editor: &ViewHandle<Editor>,
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
) -> Vec<(u32, String)> {
|
) -> Vec<(u32, String)> {
|
||||||
let mut presenter = cx.build_presenter(editor.id(), 0.);
|
let mut presenter = cx.build_presenter(editor.id(), 0., Default::default());
|
||||||
let mut cx = presenter.build_layout_context(Default::default(), false, cx);
|
let mut cx = presenter.build_layout_context(Default::default(), false, cx);
|
||||||
cx.render(editor, |editor, cx| {
|
cx.render(editor, |editor, cx| {
|
||||||
let snapshot = editor.snapshot(cx);
|
let snapshot = editor.snapshot(cx);
|
||||||
|
|
|
@ -2044,7 +2044,7 @@ mod tests {
|
||||||
|
|
||||||
let layouts = editor.update(cx, |editor, cx| {
|
let layouts = editor.update(cx, |editor, cx| {
|
||||||
let snapshot = editor.snapshot(cx);
|
let snapshot = editor.snapshot(cx);
|
||||||
let mut presenter = cx.build_presenter(window_id, 30.);
|
let mut presenter = cx.build_presenter(window_id, 30., Default::default());
|
||||||
let layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx);
|
let layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx);
|
||||||
element.layout_line_numbers(0..6, &Default::default(), &snapshot, &layout_cx)
|
element.layout_line_numbers(0..6, &Default::default(), &snapshot, &layout_cx)
|
||||||
});
|
});
|
||||||
|
@ -2083,7 +2083,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut scene = Scene::new(1.0);
|
let mut scene = Scene::new(1.0);
|
||||||
let mut presenter = cx.build_presenter(window_id, 30.);
|
let mut presenter = cx.build_presenter(window_id, 30., Default::default());
|
||||||
let mut layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx);
|
let mut layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx);
|
||||||
let (size, mut state) = element.layout(
|
let (size, mut state) = element.layout(
|
||||||
SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)),
|
SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)),
|
||||||
|
|
|
@ -9,8 +9,8 @@ use crate::{
|
||||||
platform::{self, KeyDownEvent, Platform, PromptLevel, WindowOptions},
|
platform::{self, KeyDownEvent, Platform, PromptLevel, WindowOptions},
|
||||||
presenter::Presenter,
|
presenter::Presenter,
|
||||||
util::post_inc,
|
util::post_inc,
|
||||||
AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, MouseButton, MouseRegionId,
|
Appearance, AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, MouseButton,
|
||||||
PathPromptOptions, TextLayoutCache,
|
MouseRegionId, PathPromptOptions, TextLayoutCache,
|
||||||
};
|
};
|
||||||
pub use action::*;
|
pub use action::*;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
|
@ -579,6 +579,7 @@ impl TestAppContext {
|
||||||
hovered_region_ids: Default::default(),
|
hovered_region_ids: Default::default(),
|
||||||
clicked_region_ids: None,
|
clicked_region_ids: None,
|
||||||
refreshing: false,
|
refreshing: false,
|
||||||
|
appearance: Appearance::Light,
|
||||||
};
|
};
|
||||||
f(view, &mut render_cx)
|
f(view, &mut render_cx)
|
||||||
})
|
})
|
||||||
|
@ -1260,6 +1261,7 @@ impl MutableAppContext {
|
||||||
&mut self,
|
&mut self,
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
titlebar_height: f32,
|
titlebar_height: f32,
|
||||||
|
appearance: Appearance,
|
||||||
) -> HashMap<usize, ElementBox> {
|
) -> HashMap<usize, ElementBox> {
|
||||||
self.start_frame();
|
self.start_frame();
|
||||||
#[allow(clippy::needless_collect)]
|
#[allow(clippy::needless_collect)]
|
||||||
|
@ -1287,6 +1289,7 @@ impl MutableAppContext {
|
||||||
hovered_region_ids: Default::default(),
|
hovered_region_ids: Default::default(),
|
||||||
clicked_region_ids: None,
|
clicked_region_ids: None,
|
||||||
refreshing: false,
|
refreshing: false,
|
||||||
|
appearance,
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
|
@ -1925,9 +1928,11 @@ impl MutableAppContext {
|
||||||
this.cx
|
this.cx
|
||||||
.platform
|
.platform
|
||||||
.open_window(window_id, window_options, this.foreground.clone());
|
.open_window(window_id, window_options, this.foreground.clone());
|
||||||
let presenter = Rc::new(RefCell::new(
|
let presenter = Rc::new(RefCell::new(this.build_presenter(
|
||||||
this.build_presenter(window_id, window.titlebar_height()),
|
window_id,
|
||||||
));
|
window.titlebar_height(),
|
||||||
|
window.appearance(),
|
||||||
|
)));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut app = this.upgrade();
|
let mut app = this.upgrade();
|
||||||
|
@ -1977,6 +1982,12 @@ impl MutableAppContext {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut app = this.upgrade();
|
||||||
|
window
|
||||||
|
.on_appearance_changed(Box::new(move || app.update(|cx| cx.refresh_windows())));
|
||||||
|
}
|
||||||
|
|
||||||
window.set_input_handler(Box::new(WindowInputHandler {
|
window.set_input_handler(Box::new(WindowInputHandler {
|
||||||
app: this.upgrade().0,
|
app: this.upgrade().0,
|
||||||
window_id,
|
window_id,
|
||||||
|
@ -2019,7 +2030,11 @@ impl MutableAppContext {
|
||||||
root_view.update(this, |view, cx| view.on_focus_in(cx.handle().into(), cx));
|
root_view.update(this, |view, cx| view.on_focus_in(cx.handle().into(), cx));
|
||||||
|
|
||||||
let mut status_item = this.cx.platform.add_status_item();
|
let mut status_item = this.cx.platform.add_status_item();
|
||||||
let presenter = Rc::new(RefCell::new(this.build_presenter(window_id, 0.)));
|
let presenter = Rc::new(RefCell::new(this.build_presenter(
|
||||||
|
window_id,
|
||||||
|
0.,
|
||||||
|
status_item.appearance(),
|
||||||
|
)));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut app = this.upgrade();
|
let mut app = this.upgrade();
|
||||||
|
@ -2035,6 +2050,12 @@ impl MutableAppContext {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut app = this.upgrade();
|
||||||
|
status_item
|
||||||
|
.on_appearance_changed(Box::new(move || app.update(|cx| cx.refresh_windows())));
|
||||||
|
}
|
||||||
|
|
||||||
let scene = presenter.borrow_mut().build_scene(
|
let scene = presenter.borrow_mut().build_scene(
|
||||||
status_item.size(),
|
status_item.size(),
|
||||||
status_item.scale_factor(),
|
status_item.scale_factor(),
|
||||||
|
@ -2071,10 +2092,16 @@ impl MutableAppContext {
|
||||||
self.flush_effects();
|
self.flush_effects();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_presenter(&mut self, window_id: usize, titlebar_height: f32) -> Presenter {
|
pub fn build_presenter(
|
||||||
|
&mut self,
|
||||||
|
window_id: usize,
|
||||||
|
titlebar_height: f32,
|
||||||
|
appearance: Appearance,
|
||||||
|
) -> Presenter {
|
||||||
Presenter::new(
|
Presenter::new(
|
||||||
window_id,
|
window_id,
|
||||||
titlebar_height,
|
titlebar_height,
|
||||||
|
appearance,
|
||||||
self.cx.font_cache.clone(),
|
self.cx.font_cache.clone(),
|
||||||
TextLayoutCache::new(self.cx.platform.fonts()),
|
TextLayoutCache::new(self.cx.platform.fonts()),
|
||||||
self.assets.clone(),
|
self.assets.clone(),
|
||||||
|
@ -2412,7 +2439,7 @@ impl MutableAppContext {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let mut presenter = presenter.borrow_mut();
|
let mut presenter = presenter.borrow_mut();
|
||||||
presenter.invalidate(&mut invalidation, self);
|
presenter.invalidate(&mut invalidation, window.appearance(), self);
|
||||||
let scene =
|
let scene =
|
||||||
presenter.build_scene(window.size(), window.scale_factor(), false, self);
|
presenter.build_scene(window.size(), window.scale_factor(), false, self);
|
||||||
window.present_scene(scene);
|
window.present_scene(scene);
|
||||||
|
@ -2476,6 +2503,7 @@ impl MutableAppContext {
|
||||||
let mut presenter = presenter.borrow_mut();
|
let mut presenter = presenter.borrow_mut();
|
||||||
presenter.refresh(
|
presenter.refresh(
|
||||||
invalidation.as_mut().unwrap_or(&mut Default::default()),
|
invalidation.as_mut().unwrap_or(&mut Default::default()),
|
||||||
|
window.appearance(),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
let scene = presenter.build_scene(window.size(), window.scale_factor(), true, self);
|
let scene = presenter.build_scene(window.size(), window.scale_factor(), true, self);
|
||||||
|
@ -4082,6 +4110,7 @@ pub struct RenderParams {
|
||||||
pub hovered_region_ids: HashSet<MouseRegionId>,
|
pub hovered_region_ids: HashSet<MouseRegionId>,
|
||||||
pub clicked_region_ids: Option<(Vec<MouseRegionId>, MouseButton)>,
|
pub clicked_region_ids: Option<(Vec<MouseRegionId>, MouseButton)>,
|
||||||
pub refreshing: bool,
|
pub refreshing: bool,
|
||||||
|
pub appearance: Appearance,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RenderContext<'a, T: View> {
|
pub struct RenderContext<'a, T: View> {
|
||||||
|
@ -4092,6 +4121,7 @@ pub struct RenderContext<'a, T: View> {
|
||||||
pub(crate) clicked_region_ids: Option<(Vec<MouseRegionId>, MouseButton)>,
|
pub(crate) clicked_region_ids: Option<(Vec<MouseRegionId>, MouseButton)>,
|
||||||
pub app: &'a mut MutableAppContext,
|
pub app: &'a mut MutableAppContext,
|
||||||
pub titlebar_height: f32,
|
pub titlebar_height: f32,
|
||||||
|
pub appearance: Appearance,
|
||||||
pub refreshing: bool,
|
pub refreshing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4112,6 +4142,7 @@ impl<'a, V: View> RenderContext<'a, V> {
|
||||||
hovered_region_ids: params.hovered_region_ids.clone(),
|
hovered_region_ids: params.hovered_region_ids.clone(),
|
||||||
clicked_region_ids: params.clicked_region_ids.clone(),
|
clicked_region_ids: params.clicked_region_ids.clone(),
|
||||||
refreshing: params.refreshing,
|
refreshing: params.refreshing,
|
||||||
|
appearance: params.appearance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -659,7 +659,7 @@ mod tests {
|
||||||
|
|
||||||
#[crate::test(self)]
|
#[crate::test(self)]
|
||||||
fn test_layout(cx: &mut crate::MutableAppContext) {
|
fn test_layout(cx: &mut crate::MutableAppContext) {
|
||||||
let mut presenter = cx.build_presenter(0, 0.);
|
let mut presenter = cx.build_presenter(0, 0., Default::default());
|
||||||
let (_, view) = cx.add_window(Default::default(), |_| TestView);
|
let (_, view) = cx.add_window(Default::default(), |_| TestView);
|
||||||
let constraint = SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.));
|
let constraint = SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.));
|
||||||
|
|
||||||
|
@ -759,7 +759,7 @@ mod tests {
|
||||||
.unwrap_or(10);
|
.unwrap_or(10);
|
||||||
|
|
||||||
let (_, view) = cx.add_window(Default::default(), |_| TestView);
|
let (_, view) = cx.add_window(Default::default(), |_| TestView);
|
||||||
let mut presenter = cx.build_presenter(0, 0.);
|
let mut presenter = cx.build_presenter(0, 0., Default::default());
|
||||||
let mut next_id = 0;
|
let mut next_id = 0;
|
||||||
let elements = Rc::new(RefCell::new(
|
let elements = Rc::new(RefCell::new(
|
||||||
(0..rng.gen_range(0..=20))
|
(0..rng.gen_range(0..=20))
|
||||||
|
|
|
@ -291,7 +291,7 @@ mod tests {
|
||||||
#[crate::test(self)]
|
#[crate::test(self)]
|
||||||
fn test_soft_wrapping_with_carriage_returns(cx: &mut MutableAppContext) {
|
fn test_soft_wrapping_with_carriage_returns(cx: &mut MutableAppContext) {
|
||||||
let (window_id, _) = cx.add_window(Default::default(), |_| TestView);
|
let (window_id, _) = cx.add_window(Default::default(), |_| TestView);
|
||||||
let mut presenter = cx.build_presenter(window_id, Default::default());
|
let mut presenter = cx.build_presenter(window_id, Default::default(), Default::default());
|
||||||
fonts::with_font_cache(cx.font_cache().clone(), || {
|
fonts::with_font_cache(cx.font_cache().clone(), || {
|
||||||
let mut text = Text::new("Hello\r\n".into(), Default::default()).with_soft_wrap(true);
|
let mut text = Text::new("Hello\r\n".into(), Default::default()).with_soft_wrap(true);
|
||||||
let (_, state) = text.layout(
|
let (_, state) = text.layout(
|
||||||
|
|
|
@ -132,6 +132,8 @@ pub trait Window {
|
||||||
fn scale_factor(&self) -> f32;
|
fn scale_factor(&self) -> f32;
|
||||||
fn titlebar_height(&self) -> f32;
|
fn titlebar_height(&self) -> f32;
|
||||||
fn present_scene(&mut self, scene: Scene);
|
fn present_scene(&mut self, scene: Scene);
|
||||||
|
fn appearance(&self) -> Appearance;
|
||||||
|
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -147,6 +149,20 @@ pub struct TitlebarOptions<'a> {
|
||||||
pub traffic_light_position: Option<Vector2F>,
|
pub traffic_light_position: Option<Vector2F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum Appearance {
|
||||||
|
Light,
|
||||||
|
VibrantLight,
|
||||||
|
Dark,
|
||||||
|
VibrantDark,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Appearance {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Light
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum WindowBounds {
|
pub enum WindowBounds {
|
||||||
Maximized,
|
Maximized,
|
||||||
|
@ -173,6 +189,12 @@ pub enum CursorStyle {
|
||||||
IBeam,
|
IBeam,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for CursorStyle {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Arrow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct AppVersion {
|
pub struct AppVersion {
|
||||||
major: usize,
|
major: usize,
|
||||||
|
@ -180,12 +202,6 @@ pub struct AppVersion {
|
||||||
patch: usize,
|
patch: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CursorStyle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Arrow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for AppVersion {
|
impl FromStr for AppVersion {
|
||||||
type Err = anyhow::Error;
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod appearance;
|
||||||
mod atlas;
|
mod atlas;
|
||||||
mod dispatcher;
|
mod dispatcher;
|
||||||
mod event;
|
mod event;
|
||||||
|
|
37
crates/gpui/src/platform/mac/appearance.rs
Normal file
37
crates/gpui/src/platform/mac/appearance.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
use cocoa::{
|
||||||
|
appkit::{NSAppearanceNameVibrantDark, NSAppearanceNameVibrantLight},
|
||||||
|
base::id,
|
||||||
|
foundation::NSString,
|
||||||
|
};
|
||||||
|
use objc::{msg_send, sel, sel_impl};
|
||||||
|
|
||||||
|
use crate::Appearance;
|
||||||
|
|
||||||
|
impl Appearance {
|
||||||
|
pub 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[link(name = "AppKit", kind = "framework")]
|
||||||
|
extern "C" {
|
||||||
|
pub static NSAppearanceNameAqua: id;
|
||||||
|
pub static NSAppearanceNameDarkAqua: id;
|
||||||
|
}
|
|
@ -52,6 +52,11 @@ use time::UtcOffset;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const NSUTF8StringEncoding: NSUInteger = 4;
|
const NSUTF8StringEncoding: NSUInteger = 4;
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
pub const NSViewLayerContentsRedrawDuringViewResize: NSInteger = 2;
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
pub const NSKeyValueObservingOptionNew: NSInteger = 1;
|
||||||
|
|
||||||
const MAC_PLATFORM_IVAR: &str = "platform";
|
const MAC_PLATFORM_IVAR: &str = "platform";
|
||||||
static mut APP_CLASS: *const Class = ptr::null();
|
static mut APP_CLASS: *const Class = ptr::null();
|
||||||
static mut APP_DELEGATE_CLASS: *const Class = ptr::null();
|
static mut APP_DELEGATE_CLASS: *const Class = ptr::null();
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::vector::{vec2f, Vector2F},
|
geometry::vector::{vec2f, Vector2F},
|
||||||
platform::{self, mac::renderer::Renderer},
|
platform::{
|
||||||
|
self,
|
||||||
|
mac::{
|
||||||
|
platform::{NSKeyValueObservingOptionNew, NSViewLayerContentsRedrawDuringViewResize},
|
||||||
|
renderer::Renderer,
|
||||||
|
},
|
||||||
|
},
|
||||||
Event, FontSystem, Scene,
|
Event, FontSystem, Scene,
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{NSSquareStatusItemLength, NSStatusBar, NSStatusItem, NSView, NSWindow},
|
appkit::{NSSquareStatusItemLength, NSStatusBar, NSStatusItem, NSView, NSWindow},
|
||||||
base::{id, nil, YES},
|
base::{id, nil, YES},
|
||||||
foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize},
|
foundation::{NSPoint, NSRect, NSSize, NSString},
|
||||||
};
|
};
|
||||||
use ctor::ctor;
|
use ctor::ctor;
|
||||||
use foreign_types::ForeignTypeRef;
|
use foreign_types::ForeignTypeRef;
|
||||||
|
@ -15,7 +21,7 @@ use objc::{
|
||||||
declare::ClassDecl,
|
declare::ClassDecl,
|
||||||
msg_send,
|
msg_send,
|
||||||
rc::StrongPtr,
|
rc::StrongPtr,
|
||||||
runtime::{Class, Object, Sel},
|
runtime::{Class, Object, Protocol, Sel},
|
||||||
sel, sel_impl,
|
sel, sel_impl,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -77,6 +83,20 @@ unsafe fn build_classes() {
|
||||||
sel!(flagsChanged:),
|
sel!(flagsChanged:),
|
||||||
handle_view_event as extern "C" fn(&Object, Sel, id),
|
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!(observeValueForKeyPath:ofObject:change:context:),
|
||||||
|
appearance_changed as extern "C" fn(&Object, Sel, id, id, id, id),
|
||||||
|
);
|
||||||
|
|
||||||
|
decl.add_protocol(Protocol::get("CALayerDelegate").unwrap());
|
||||||
|
decl.add_method(
|
||||||
|
sel!(displayLayer:),
|
||||||
|
display_layer as extern "C" fn(&Object, Sel, id),
|
||||||
|
);
|
||||||
|
|
||||||
decl.register()
|
decl.register()
|
||||||
};
|
};
|
||||||
|
@ -86,15 +106,16 @@ pub struct StatusItem(Rc<RefCell<StatusItemState>>);
|
||||||
|
|
||||||
struct StatusItemState {
|
struct StatusItemState {
|
||||||
native_item: StrongPtr,
|
native_item: StrongPtr,
|
||||||
|
native_view: StrongPtr,
|
||||||
renderer: Renderer,
|
renderer: Renderer,
|
||||||
|
scene: Option<Scene>,
|
||||||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||||
|
appearance_changed_callback: Option<Box<dyn FnMut()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatusItem {
|
impl StatusItem {
|
||||||
pub fn add(fonts: Arc<dyn FontSystem>) -> Self {
|
pub fn add(fonts: Arc<dyn FontSystem>) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let pool = NSAutoreleasePool::new(nil);
|
|
||||||
|
|
||||||
let renderer = Renderer::new(false, fonts);
|
let renderer = Renderer::new(false, fonts);
|
||||||
let status_bar = NSStatusBar::systemStatusBar(nil);
|
let status_bar = NSStatusBar::systemStatusBar(nil);
|
||||||
let native_item =
|
let native_item =
|
||||||
|
@ -103,39 +124,51 @@ impl StatusItem {
|
||||||
let button = native_item.button();
|
let button = native_item.button();
|
||||||
let _: () = msg_send![button, setHidden: YES];
|
let _: () = msg_send![button, setHidden: YES];
|
||||||
|
|
||||||
let item = Self(Rc::new_cyclic(|state| {
|
let native_view = msg_send![VIEW_CLASS, alloc];
|
||||||
let parent_view = button.superview().superview();
|
let state = Rc::new(RefCell::new(StatusItemState {
|
||||||
|
|
||||||
let view: id = msg_send![VIEW_CLASS, alloc];
|
|
||||||
NSView::initWithFrame_(
|
|
||||||
view,
|
|
||||||
NSRect::new(NSPoint::new(0., 0.), NSView::frame(parent_view).size),
|
|
||||||
);
|
|
||||||
view.setWantsBestResolutionOpenGLSurface_(YES);
|
|
||||||
view.setLayer(renderer.layer().as_ptr() as id);
|
|
||||||
view.setWantsLayer(true);
|
|
||||||
(*view).set_ivar(STATE_IVAR, Weak::into_raw(state.clone()) as *const c_void);
|
|
||||||
parent_view.addSubview_(view.autorelease());
|
|
||||||
|
|
||||||
RefCell::new(StatusItemState {
|
|
||||||
native_item,
|
native_item,
|
||||||
|
native_view: StrongPtr::new(native_view),
|
||||||
renderer,
|
renderer,
|
||||||
|
scene: None,
|
||||||
event_callback: None,
|
event_callback: None,
|
||||||
})
|
appearance_changed_callback: None,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let parent_view = button.superview().superview();
|
||||||
|
NSView::initWithFrame_(
|
||||||
|
native_view,
|
||||||
|
NSRect::new(NSPoint::new(0., 0.), NSView::frame(parent_view).size),
|
||||||
|
);
|
||||||
|
(*native_view).set_ivar(
|
||||||
|
STATE_IVAR,
|
||||||
|
Weak::into_raw(Rc::downgrade(&state)) as *const c_void,
|
||||||
|
);
|
||||||
|
native_view.setWantsBestResolutionOpenGLSurface_(YES);
|
||||||
|
native_view.setWantsLayer(true);
|
||||||
|
let _: () = msg_send![
|
||||||
|
native_view,
|
||||||
|
setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawDuringViewResize
|
||||||
|
];
|
||||||
|
let _: () = msg_send![
|
||||||
|
button,
|
||||||
|
addObserver: native_view
|
||||||
|
forKeyPath: NSString::alloc(nil).init_str("effectiveAppearance")
|
||||||
|
options: NSKeyValueObservingOptionNew
|
||||||
|
context: nil
|
||||||
|
];
|
||||||
|
|
||||||
|
parent_view.addSubview_(native_view);
|
||||||
|
|
||||||
{
|
{
|
||||||
let item = item.0.borrow();
|
let state = state.borrow();
|
||||||
let layer = item.renderer.layer();
|
let layer = state.renderer.layer();
|
||||||
let scale_factor = item.scale_factor();
|
let scale_factor = state.scale_factor();
|
||||||
let size = item.size() * scale_factor;
|
let size = state.size() * scale_factor;
|
||||||
layer.set_contents_scale(scale_factor.into());
|
layer.set_contents_scale(scale_factor.into());
|
||||||
layer.set_drawable_size(metal::CGSize::new(size.x().into(), size.y().into()));
|
layer.set_drawable_size(metal::CGSize::new(size.x().into(), size.y().into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.drain();
|
Self(state)
|
||||||
|
|
||||||
item
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,6 +182,10 @@ impl platform::Window for StatusItem {
|
||||||
self.0.borrow_mut().event_callback = Some(callback);
|
self.0.borrow_mut().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>) {
|
||||||
|
self.0.borrow_mut().appearance_changed_callback = Some(callback);
|
||||||
|
}
|
||||||
|
|
||||||
fn on_active_status_change(&mut self, _: Box<dyn FnMut(bool)>) {
|
fn on_active_status_change(&mut self, _: Box<dyn FnMut(bool)>) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
@ -223,7 +260,18 @@ impl platform::Window for StatusItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn present_scene(&mut self, scene: Scene) {
|
fn present_scene(&mut self, scene: Scene) {
|
||||||
self.0.borrow_mut().renderer.render(&scene);
|
self.0.borrow_mut().scene = Some(scene);
|
||||||
|
unsafe {
|
||||||
|
let _: () = msg_send![*self.0.borrow().native_view, setNeedsDisplay: YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn appearance(&self) -> crate::Appearance {
|
||||||
|
unsafe {
|
||||||
|
let appearance: id =
|
||||||
|
msg_send![self.0.borrow().native_item.button(), effectiveAppearance];
|
||||||
|
crate::Appearance::from_native(appearance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,6 +295,7 @@ impl StatusItemState {
|
||||||
extern "C" fn dealloc_view(this: &Object, _: Sel) {
|
extern "C" fn dealloc_view(this: &Object, _: Sel) {
|
||||||
unsafe {
|
unsafe {
|
||||||
drop_state(this);
|
drop_state(this);
|
||||||
|
|
||||||
let _: () = msg_send![super(this, class!(NSView)), dealloc];
|
let _: () = msg_send![super(this, class!(NSView)), dealloc];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +315,39 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn make_backing_layer(this: &Object, _: Sel) -> id {
|
||||||
|
if let Some(state) = unsafe { get_state(this).upgrade() } {
|
||||||
|
let state = state.borrow();
|
||||||
|
state.renderer.layer().as_ptr() as id
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn display_layer(this: &Object, _: Sel, _: id) {
|
||||||
|
unsafe {
|
||||||
|
if let Some(state) = get_state(this).upgrade() {
|
||||||
|
let mut state = state.borrow_mut();
|
||||||
|
if let Some(scene) = state.scene.take() {
|
||||||
|
state.renderer.render(&scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn appearance_changed(this: &Object, _: Sel, _: id, _: id, _: id, _: id) {
|
||||||
|
unsafe {
|
||||||
|
if let Some(state) = get_state(this).upgrade() {
|
||||||
|
let mut state_borrow = state.as_ref().borrow_mut();
|
||||||
|
if let Some(mut callback) = state_borrow.appearance_changed_callback.take() {
|
||||||
|
drop(state_borrow);
|
||||||
|
callback();
|
||||||
|
state.borrow_mut().appearance_changed_callback = Some(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn get_state(object: &Object) -> Weak<RefCell<StatusItemState>> {
|
unsafe fn get_state(object: &Object) -> Weak<RefCell<StatusItemState>> {
|
||||||
let raw: *mut c_void = *object.get_ivar(STATE_IVAR);
|
let raw: *mut c_void = *object.get_ivar(STATE_IVAR);
|
||||||
let weak1 = Weak::from_raw(raw as *mut RefCell<StatusItemState>);
|
let weak1 = Weak::from_raw(raw as *mut RefCell<StatusItemState>);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use super::{geometry::RectFExt, renderer::Renderer};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executor,
|
executor,
|
||||||
geometry::{
|
geometry::{
|
||||||
|
@ -6,7 +5,12 @@ use crate::{
|
||||||
vector::{vec2f, Vector2F},
|
vector::{vec2f, Vector2F},
|
||||||
},
|
},
|
||||||
keymap::Keystroke,
|
keymap::Keystroke,
|
||||||
platform::{self, Event, WindowBounds},
|
mac::platform::{NSKeyValueObservingOptionNew, NSViewLayerContentsRedrawDuringViewResize},
|
||||||
|
platform::{
|
||||||
|
self,
|
||||||
|
mac::{geometry::RectFExt, renderer::Renderer},
|
||||||
|
Event, WindowBounds,
|
||||||
|
},
|
||||||
InputHandler, KeyDownEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
|
InputHandler, KeyDownEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
|
||||||
MouseMovedEvent, Scene,
|
MouseMovedEvent, Scene,
|
||||||
};
|
};
|
||||||
|
@ -102,9 +106,6 @@ unsafe impl objc::Encode for NSRange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const NSViewLayerContentsRedrawDuringViewResize: NSInteger = 2;
|
|
||||||
|
|
||||||
#[ctor]
|
#[ctor]
|
||||||
unsafe fn build_classes() {
|
unsafe fn build_classes() {
|
||||||
WINDOW_CLASS = {
|
WINDOW_CLASS = {
|
||||||
|
@ -264,6 +265,10 @@ unsafe fn build_classes() {
|
||||||
attributed_substring_for_proposed_range
|
attributed_substring_for_proposed_range
|
||||||
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
|
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
|
||||||
);
|
);
|
||||||
|
decl.add_method(
|
||||||
|
sel!(observeValueForKeyPath:ofObject:change:context:),
|
||||||
|
appearance_changed as extern "C" fn(&Object, Sel, id, id, id, id),
|
||||||
|
);
|
||||||
|
|
||||||
// Suppress beep on keystrokes with modifier keys.
|
// Suppress beep on keystrokes with modifier keys.
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
|
@ -298,6 +303,7 @@ struct WindowState {
|
||||||
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
||||||
should_close_callback: Option<Box<dyn FnMut() -> bool>>,
|
should_close_callback: Option<Box<dyn FnMut() -> bool>>,
|
||||||
close_callback: Option<Box<dyn FnOnce()>>,
|
close_callback: Option<Box<dyn FnOnce()>>,
|
||||||
|
appearance_changed_callback: Option<Box<dyn FnMut()>>,
|
||||||
input_handler: Option<Box<dyn InputHandler>>,
|
input_handler: Option<Box<dyn InputHandler>>,
|
||||||
pending_key_down: Option<(KeyDownEvent, Option<InsertText>)>,
|
pending_key_down: Option<(KeyDownEvent, Option<InsertText>)>,
|
||||||
performed_key_equivalent: bool,
|
performed_key_equivalent: bool,
|
||||||
|
@ -376,6 +382,7 @@ impl Window {
|
||||||
close_callback: None,
|
close_callback: None,
|
||||||
activate_callback: None,
|
activate_callback: None,
|
||||||
fullscreen_callback: None,
|
fullscreen_callback: None,
|
||||||
|
appearance_changed_callback: None,
|
||||||
input_handler: None,
|
input_handler: None,
|
||||||
pending_key_down: None,
|
pending_key_down: None,
|
||||||
performed_key_equivalent: false,
|
performed_key_equivalent: false,
|
||||||
|
@ -433,6 +440,13 @@ impl Window {
|
||||||
|
|
||||||
native_window.center();
|
native_window.center();
|
||||||
native_window.makeKeyAndOrderFront_(nil);
|
native_window.makeKeyAndOrderFront_(nil);
|
||||||
|
let _: () = msg_send![
|
||||||
|
native_window,
|
||||||
|
addObserver: native_view
|
||||||
|
forKeyPath: NSString::alloc(nil).init_str("effectiveAppearance")
|
||||||
|
options: NSKeyValueObservingOptionNew
|
||||||
|
context: nil
|
||||||
|
];
|
||||||
|
|
||||||
window.0.borrow().move_traffic_light();
|
window.0.borrow().move_traffic_light();
|
||||||
pool.drain();
|
pool.drain();
|
||||||
|
@ -634,6 +648,17 @@ impl platform::Window for Window {
|
||||||
fn titlebar_height(&self) -> f32 {
|
fn titlebar_height(&self) -> f32 {
|
||||||
self.0.as_ref().borrow().titlebar_height()
|
self.0.as_ref().borrow().titlebar_height()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn appearance(&self) -> crate::Appearance {
|
||||||
|
unsafe {
|
||||||
|
let appearance: id = msg_send![self.0.borrow().native_window, effectiveAppearance];
|
||||||
|
crate::Appearance::from_native(appearance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>) {
|
||||||
|
self.0.borrow_mut().appearance_changed_callback = Some(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowState {
|
impl WindowState {
|
||||||
|
@ -1270,6 +1295,18 @@ extern "C" fn do_command_by_selector(this: &Object, _: Sel, _: Sel) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn appearance_changed(this: &Object, _: Sel, _: id, _: id, _: id, _: id) {
|
||||||
|
unsafe {
|
||||||
|
let state = get_window_state(this);
|
||||||
|
let mut state_borrow = state.as_ref().borrow_mut();
|
||||||
|
if let Some(mut callback) = state_borrow.appearance_changed_callback.take() {
|
||||||
|
drop(state_borrow);
|
||||||
|
callback();
|
||||||
|
state.borrow_mut().appearance_changed_callback = Some(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn synthetic_drag(
|
async fn synthetic_drag(
|
||||||
window_state: Weak<RefCell<WindowState>>,
|
window_state: Weak<RefCell<WindowState>>,
|
||||||
drag_id: usize,
|
drag_id: usize,
|
||||||
|
|
|
@ -298,6 +298,12 @@ impl super::Window for Window {
|
||||||
fn present_scene(&mut self, scene: crate::Scene) {
|
fn present_scene(&mut self, scene: crate::Scene) {
|
||||||
self.current_scene = Some(scene);
|
self.current_scene = Some(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn appearance(&self) -> crate::Appearance {
|
||||||
|
crate::Appearance::Light
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_appearance_changed(&mut self, _: Box<dyn FnMut()>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn platform() -> Platform {
|
pub fn platform() -> Platform {
|
||||||
|
|
|
@ -11,10 +11,10 @@ use crate::{
|
||||||
HoverRegionEvent, MouseRegionEvent, MoveRegionEvent, UpOutRegionEvent, UpRegionEvent,
|
HoverRegionEvent, MouseRegionEvent, MoveRegionEvent, UpOutRegionEvent, UpRegionEvent,
|
||||||
},
|
},
|
||||||
text_layout::TextLayoutCache,
|
text_layout::TextLayoutCache,
|
||||||
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Entity,
|
Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, Appearance, AssetCache, ElementBox,
|
||||||
FontSystem, ModelHandle, MouseButton, MouseMovedEvent, MouseRegion, MouseRegionId, ParentId,
|
Entity, FontSystem, ModelHandle, MouseButton, MouseMovedEvent, MouseRegion, MouseRegionId,
|
||||||
ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle,
|
ParentId, ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle,
|
||||||
View, ViewHandle, WeakModelHandle, WeakViewHandle,
|
UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
||||||
|
@ -40,12 +40,14 @@ pub struct Presenter {
|
||||||
clicked_button: Option<MouseButton>,
|
clicked_button: Option<MouseButton>,
|
||||||
mouse_position: Vector2F,
|
mouse_position: Vector2F,
|
||||||
titlebar_height: f32,
|
titlebar_height: f32,
|
||||||
|
appearance: Appearance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Presenter {
|
impl Presenter {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
titlebar_height: f32,
|
titlebar_height: f32,
|
||||||
|
appearance: Appearance,
|
||||||
font_cache: Arc<FontCache>,
|
font_cache: Arc<FontCache>,
|
||||||
text_layout_cache: TextLayoutCache,
|
text_layout_cache: TextLayoutCache,
|
||||||
asset_cache: Arc<AssetCache>,
|
asset_cache: Arc<AssetCache>,
|
||||||
|
@ -53,7 +55,7 @@ impl Presenter {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
window_id,
|
window_id,
|
||||||
rendered_views: cx.render_views(window_id, titlebar_height),
|
rendered_views: cx.render_views(window_id, titlebar_height, appearance),
|
||||||
cursor_regions: Default::default(),
|
cursor_regions: Default::default(),
|
||||||
mouse_regions: Default::default(),
|
mouse_regions: Default::default(),
|
||||||
font_cache,
|
font_cache,
|
||||||
|
@ -65,15 +67,18 @@ impl Presenter {
|
||||||
clicked_button: None,
|
clicked_button: None,
|
||||||
mouse_position: vec2f(0., 0.),
|
mouse_position: vec2f(0., 0.),
|
||||||
titlebar_height,
|
titlebar_height,
|
||||||
|
appearance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invalidate(
|
pub fn invalidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
invalidation: &mut WindowInvalidation,
|
invalidation: &mut WindowInvalidation,
|
||||||
|
appearance: Appearance,
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
) {
|
) {
|
||||||
cx.start_frame();
|
cx.start_frame();
|
||||||
|
self.appearance = appearance;
|
||||||
for view_id in &invalidation.removed {
|
for view_id in &invalidation.removed {
|
||||||
invalidation.updated.remove(view_id);
|
invalidation.updated.remove(view_id);
|
||||||
self.rendered_views.remove(view_id);
|
self.rendered_views.remove(view_id);
|
||||||
|
@ -96,14 +101,20 @@ impl Presenter {
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
refreshing: false,
|
refreshing: false,
|
||||||
|
appearance,
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh(&mut self, invalidation: &mut WindowInvalidation, cx: &mut MutableAppContext) {
|
pub fn refresh(
|
||||||
self.invalidate(invalidation, cx);
|
&mut self,
|
||||||
|
invalidation: &mut WindowInvalidation,
|
||||||
|
appearance: Appearance,
|
||||||
|
cx: &mut MutableAppContext,
|
||||||
|
) {
|
||||||
|
self.invalidate(invalidation, appearance, cx);
|
||||||
for (view_id, view) in &mut self.rendered_views {
|
for (view_id, view) in &mut self.rendered_views {
|
||||||
if !invalidation.updated.contains(view_id) {
|
if !invalidation.updated.contains(view_id) {
|
||||||
*view = cx
|
*view = cx
|
||||||
|
@ -122,6 +133,7 @@ impl Presenter {
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
refreshing: true,
|
refreshing: true,
|
||||||
|
appearance,
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -194,6 +206,7 @@ impl Presenter {
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
titlebar_height: self.titlebar_height,
|
titlebar_height: self.titlebar_height,
|
||||||
|
appearance: self.appearance,
|
||||||
window_size,
|
window_size,
|
||||||
app: cx,
|
app: cx,
|
||||||
}
|
}
|
||||||
|
@ -545,6 +558,7 @@ pub struct LayoutContext<'a> {
|
||||||
pub refreshing: bool,
|
pub refreshing: bool,
|
||||||
pub window_size: Vector2F,
|
pub window_size: Vector2F,
|
||||||
titlebar_height: f32,
|
titlebar_height: f32,
|
||||||
|
appearance: Appearance,
|
||||||
hovered_region_ids: HashSet<MouseRegionId>,
|
hovered_region_ids: HashSet<MouseRegionId>,
|
||||||
clicked_region_ids: Option<(Vec<MouseRegionId>, MouseButton)>,
|
clicked_region_ids: Option<(Vec<MouseRegionId>, MouseButton)>,
|
||||||
}
|
}
|
||||||
|
@ -619,6 +633,7 @@ impl<'a> LayoutContext<'a> {
|
||||||
hovered_region_ids: self.hovered_region_ids.clone(),
|
hovered_region_ids: self.hovered_region_ids.clone(),
|
||||||
clicked_region_ids: self.clicked_region_ids.clone(),
|
clicked_region_ids: self.clicked_region_ids.clone(),
|
||||||
refreshing: self.refreshing,
|
refreshing: self.refreshing,
|
||||||
|
appearance: self.appearance,
|
||||||
};
|
};
|
||||||
f(view, &mut render_cx)
|
f(view, &mut render_cx)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue