Route whether or not a window is fullscreen down into GPUI

This still needs to be able to invalidate things to be useful
but it's a good first cut at just making the information available
to platform-agnostic code

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
ForLoveOfCats 2022-08-09 15:34:57 -04:00
parent ae8dd1e3fd
commit ab760493cf
4 changed files with 129 additions and 3 deletions

View file

@ -1248,6 +1248,13 @@ impl MutableAppContext {
.map_or(false, |window| window.is_active)
}
pub fn window_is_fullscreen(&self, window_id: usize) -> bool {
self.cx
.windows
.get(&window_id)
.map_or(false, |window| window.is_fullscreen)
}
pub fn render_view(&mut self, params: RenderParams) -> Result<ElementBox> {
let window_id = params.window_id;
let view_id = params.view_id;
@ -1934,6 +1941,7 @@ impl MutableAppContext {
focused_view_id: Some(root_view.id()),
is_active: false,
invalidation: None,
is_fullscreen: false,
},
);
root_view.update(this, |view, cx| view.on_focus(cx));
@ -2010,6 +2018,13 @@ impl MutableAppContext {
}));
}
{
let mut app = self.upgrade();
window.on_fullscreen(Box::new(move |is_fullscreen| {
app.update(|cx| cx.window_was_fullscreen_changed(window_id, is_fullscreen))
}));
}
{
let mut app = self.upgrade();
window.on_close(Box::new(move || {
@ -2151,7 +2166,9 @@ impl MutableAppContext {
subscription_id,
callback,
} => self.handle_subscription_effect(entity_id, subscription_id, callback),
Effect::Event { entity_id, payload } => self.emit_event(entity_id, payload),
Effect::GlobalSubscription {
type_id,
subscription_id,
@ -2161,21 +2178,27 @@ impl MutableAppContext {
subscription_id,
callback,
),
Effect::GlobalEvent { payload } => self.emit_global_event(payload),
Effect::Observation {
entity_id,
subscription_id,
callback,
} => self.handle_observation_effect(entity_id, subscription_id, callback),
Effect::ModelNotification { model_id } => {
self.handle_model_notification_effect(model_id)
}
Effect::ViewNotification { window_id, view_id } => {
self.handle_view_notification_effect(window_id, view_id)
}
Effect::GlobalNotification { type_id } => {
self.handle_global_notification_effect(type_id)
}
Effect::Deferred {
callback,
after_window_update,
@ -2186,15 +2209,19 @@ impl MutableAppContext {
callback(self)
}
}
Effect::ModelRelease { model_id, model } => {
self.handle_entity_release_effect(model_id, model.as_any())
}
Effect::ViewRelease { view_id, view } => {
self.handle_entity_release_effect(view_id, view.as_any())
}
Effect::Focus { window_id, view_id } => {
self.handle_focus_effect(window_id, view_id);
}
Effect::FocusObservation {
view_id,
subscription_id,
@ -2202,6 +2229,7 @@ impl MutableAppContext {
} => {
self.handle_focus_observation_effect(view_id, subscription_id, callback)
}
Effect::ResizeWindow { window_id } => {
if let Some(window) = self.cx.windows.get_mut(&window_id) {
window
@ -2209,6 +2237,7 @@ impl MutableAppContext {
.get_or_insert(WindowInvalidation::default());
}
}
Effect::WindowActivationObservation {
window_id,
subscription_id,
@ -2218,10 +2247,17 @@ impl MutableAppContext {
subscription_id,
callback,
),
Effect::ActivateWindow {
window_id,
is_active,
} => self.handle_window_activation_effect(window_id, is_active),
Effect::FullscreenWindow {
window_id,
is_fullscreen,
} => self.handle_fullscreen_effect(window_id, is_fullscreen),
Effect::RefreshWindows => {
refreshing = true;
}
@ -2294,6 +2330,13 @@ impl MutableAppContext {
.push_back(Effect::ResizeWindow { window_id });
}
fn window_was_fullscreen_changed(&mut self, window_id: usize, is_fullscreen: bool) {
self.pending_effects.push_back(Effect::FullscreenWindow {
window_id,
is_fullscreen,
});
}
fn window_changed_active_status(&mut self, window_id: usize, is_active: bool) {
self.pending_effects.push_back(Effect::ActivateWindow {
window_id,
@ -2608,13 +2651,36 @@ impl MutableAppContext {
}
}
fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) {
fn handle_fullscreen_effect(&mut self, window_id: usize, is_fullscreen: bool) {
//Short circuit evaluation if we're already g2g
if self
.cx
.windows
.get(&window_id)
.map(|w| w.is_active)
.map_or(false, |cur_active| cur_active == active)
.map(|w| w.is_fullscreen == is_fullscreen)
.unwrap_or(false)
{
return;
}
self.update(|this| {
let window = this.cx.windows.get_mut(&window_id)?;
window.is_fullscreen = is_fullscreen;
// self.emit_event(entity_id, payload);
Some(())
});
}
fn handle_window_activation_effect(&mut self, window_id: usize, active: bool) {
//Short circuit evaluation if we're already g2g
if self
.cx
.windows
.get(&window_id)
.map(|w| w.is_active == active)
.unwrap_or(false)
{
return;
}
@ -2622,6 +2688,8 @@ impl MutableAppContext {
self.update(|this| {
let window = this.cx.windows.get_mut(&window_id)?;
window.is_active = active;
//Handle focus
let view_id = window.focused_view_id?;
if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
if active {
@ -2632,6 +2700,7 @@ impl MutableAppContext {
this.cx.views.insert((window_id, view_id), view);
}
//Deliver events
let callbacks = this
.window_activation_observations
.lock()
@ -2640,6 +2709,7 @@ impl MutableAppContext {
for (id, callback) in callbacks {
if let Some(mut callback) = callback {
let alive = callback(active, this);
//Put entry back
if alive {
match this
.window_activation_observations
@ -3072,6 +3142,7 @@ struct Window {
root_view: AnyViewHandle,
focused_view_id: Option<usize>,
is_active: bool,
is_fullscreen: bool,
invalidation: Option<WindowInvalidation>,
}
@ -3138,6 +3209,10 @@ pub enum Effect {
ResizeWindow {
window_id: usize,
},
FullscreenWindow {
window_id: usize,
is_fullscreen: bool,
},
ActivateWindow {
window_id: usize,
is_active: bool,
@ -3256,6 +3331,14 @@ impl Debug for Effect {
.field("window_id", window_id)
.field("is_active", is_active)
.finish(),
Effect::FullscreenWindow {
window_id,
is_fullscreen,
} => f
.debug_struct("Effect::FullscreenWindow")
.field("window_id", window_id)
.field("is_fullscreen", is_fullscreen)
.finish(),
Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(),
Effect::WindowShouldCloseSubscription { window_id, .. } => f
.debug_struct("Effect::WindowShouldCloseSubscription")
@ -4032,6 +4115,10 @@ impl<'a, V: View> RenderContext<'a, V> {
WeakViewHandle::new(self.window_id, self.view_id)
}
pub fn window_id(&self) -> usize {
self.window_id
}
pub fn view_id(&self) -> usize {
self.view_id
}

View file

@ -112,6 +112,7 @@ pub trait Window: WindowContext {
fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>);
fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>);
fn on_resize(&mut self, callback: Box<dyn FnMut()>);
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>);
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>);
fn on_close(&mut self, callback: Box<dyn FnOnce()>);
fn set_input_handler(&mut self, input_handler: Box<dyn InputHandler>);

View file

@ -128,6 +128,14 @@ unsafe fn build_classes() {
sel!(windowDidResize:),
window_did_resize as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidEnterFullScreen:),
window_did_enter_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidExitFullScreen:),
window_did_exit_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidBecomeKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
@ -276,6 +284,7 @@ struct WindowState {
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
activate_callback: Option<Box<dyn FnMut(bool)>>,
resize_callback: Option<Box<dyn FnMut()>>,
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
should_close_callback: Option<Box<dyn FnMut() -> bool>>,
close_callback: Option<Box<dyn FnOnce()>>,
input_handler: Option<Box<dyn InputHandler>>,
@ -368,6 +377,7 @@ impl Window {
should_close_callback: None,
close_callback: None,
activate_callback: None,
fullscreen_callback: None,
input_handler: None,
pending_key_down: None,
performed_key_equivalent: false,
@ -467,6 +477,10 @@ impl platform::Window for Window {
self.0.as_ref().borrow_mut().resize_callback = Some(callback);
}
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>) {
self.0.as_ref().borrow_mut().fullscreen_callback = Some(callback);
}
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>) {
self.0.as_ref().borrow_mut().should_close_callback = Some(callback);
}
@ -908,6 +922,24 @@ extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) {
window_state.as_ref().borrow().move_traffic_light();
}
extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
window_fullscreen_changed(this, true);
}
extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
window_fullscreen_changed(this, false);
}
fn window_fullscreen_changed(this: &Object, is_fullscreen: bool) {
let window_state = unsafe { get_window_state(this) };
let mut window_state_borrow = window_state.as_ref().borrow_mut();
if let Some(mut callback) = window_state_borrow.fullscreen_callback.take() {
drop(window_state_borrow);
callback(is_fullscreen);
window_state.borrow_mut().fullscreen_callback = Some(callback);
}
}
extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id) {
let is_active = if selector == sel!(windowDidBecomeKey:) {
true

View file

@ -37,6 +37,7 @@ pub struct Window {
event_handlers: Vec<Box<dyn FnMut(super::Event) -> bool>>,
resize_handlers: Vec<Box<dyn FnMut()>>,
close_handlers: Vec<Box<dyn FnOnce()>>,
fullscreen_handlers: Vec<Box<dyn FnMut(bool)>>,
pub(crate) active_status_change_handlers: Vec<Box<dyn FnMut(bool)>>,
pub(crate) should_close_handler: Option<Box<dyn FnMut() -> bool>>,
pub(crate) title: Option<String>,
@ -199,6 +200,7 @@ impl Window {
close_handlers: Default::default(),
should_close_handler: Default::default(),
active_status_change_handlers: Default::default(),
fullscreen_handlers: Default::default(),
scale_factor: 1.0,
current_scene: None,
title: None,
@ -253,6 +255,10 @@ impl super::Window for Window {
self.active_status_change_handlers.push(callback);
}
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>) {
self.fullscreen_handlers.push(callback)
}
fn on_resize(&mut self, callback: Box<dyn FnMut()>) {
self.resize_handlers.push(callback);
}