Refresh windows when OS appearance changes

This commit is contained in:
Antonio Scandurra 2022-09-14 11:47:43 +02:00
parent 0f9ff57568
commit f67e2bea29
14 changed files with 304 additions and 67 deletions

View file

@ -1,4 +1,3 @@
use super::{geometry::RectFExt, renderer::Renderer};
use crate::{
executor,
geometry::{
@ -6,7 +5,12 @@ use crate::{
vector::{vec2f, Vector2F},
},
keymap::Keystroke,
platform::{self, Event, WindowBounds},
mac::platform::{NSKeyValueObservingOptionNew, NSViewLayerContentsRedrawDuringViewResize},
platform::{
self,
mac::{geometry::RectFExt, renderer::Renderer},
Event, WindowBounds,
},
InputHandler, KeyDownEvent, ModifiersChangedEvent, MouseButton, MouseButtonEvent,
MouseMovedEvent, Scene,
};
@ -102,9 +106,6 @@ unsafe impl objc::Encode for NSRange {
}
}
#[allow(non_upper_case_globals)]
const NSViewLayerContentsRedrawDuringViewResize: NSInteger = 2;
#[ctor]
unsafe fn build_classes() {
WINDOW_CLASS = {
@ -264,6 +265,10 @@ unsafe fn build_classes() {
attributed_substring_for_proposed_range
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.
decl.add_method(
@ -298,6 +303,7 @@ struct WindowState {
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
should_close_callback: Option<Box<dyn FnMut() -> bool>>,
close_callback: Option<Box<dyn FnOnce()>>,
appearance_changed_callback: Option<Box<dyn FnMut()>>,
input_handler: Option<Box<dyn InputHandler>>,
pending_key_down: Option<(KeyDownEvent, Option<InsertText>)>,
performed_key_equivalent: bool,
@ -376,6 +382,7 @@ impl Window {
close_callback: None,
activate_callback: None,
fullscreen_callback: None,
appearance_changed_callback: None,
input_handler: None,
pending_key_down: None,
performed_key_equivalent: false,
@ -433,6 +440,13 @@ impl Window {
native_window.center();
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();
pool.drain();
@ -634,6 +648,17 @@ impl platform::Window for Window {
fn titlebar_height(&self) -> f32 {
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 {
@ -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(
window_state: Weak<RefCell<WindowState>>,
drag_id: usize,