Fix LSP server staying alive when closing preview window

* Provide an internal behavior parameter to run_event_loop() that we can use
from the preview to not quit when the last window was closed.
* Fix Drop for the winit event loop GraphicsWindow to drop the backend window correctly
  when unmapping, not when the graphics window dies. Otherwise QuitOnLastWindowClosed doesn't work.
This commit is contained in:
Simon Hausmann 2021-04-06 12:11:55 +02:00
parent b81803774b
commit 1e4921de13
9 changed files with 55 additions and 24 deletions

View file

@ -34,7 +34,8 @@ pub unsafe extern "C" fn sixtyfps_component_window_init(out: *mut ComponentWindo
#[no_mangle]
pub unsafe extern "C" fn sixtyfps_run_event_loop() {
crate::backend().run_event_loop();
crate::backend()
.run_event_loop(sixtyfps_corelib::backend::EventLoopQuitBehavior::QuitOnLastWindowClosed);
}
#[no_mangle]

View file

@ -241,7 +241,8 @@ pub fn create_window() -> re_exports::ComponentWindow {
/// events from the windowing system in order to render to the screen
/// and react to user input.
pub fn run_event_loop() {
sixtyfps_rendering_backend_default::backend().run_event_loop();
sixtyfps_rendering_backend_default::backend()
.run_event_loop(sixtyfps_corelib::backend::EventLoopQuitBehavior::QuitOnLastWindowClosed);
}
/// This trait describes the common public API of a strongly referenced SixtyFPS component,

View file

@ -15,6 +15,14 @@ use std::path::Path;
use crate::window::ComponentWindow;
/// Behavior describing how the event loop should terminate.
pub enum EventLoopQuitBehavior {
/// Terminate the event loop when the last window was closed.
QuitOnLastWindowClosed,
/// Keep the event loop running until [`Backend::quit_event_loop()`] is called.
QuitOnlyExplicitly,
}
/// Interface implemented by backends
pub trait Backend: Send + Sync {
/// Instentiate a window for a component.
@ -22,7 +30,7 @@ pub trait Backend: Send + Sync {
fn create_window(&'static self) -> ComponentWindow;
/// Spins an event loop and renders the visible windows.
fn run_event_loop(&'static self);
fn run_event_loop(&'static self, behavior: EventLoopQuitBehavior);
/// Exits the event loop.
fn quit_event_loop(&'static self);

View file

@ -744,7 +744,9 @@ impl ComponentInstance {
/// and [`Self::hide`].
pub fn run(&self) {
self.show();
sixtyfps_rendering_backend_default::backend().run_event_loop();
sixtyfps_rendering_backend_default::backend().run_event_loop(
sixtyfps_corelib::backend::EventLoopQuitBehavior::QuitOnLastWindowClosed,
);
self.hide();
}
@ -837,7 +839,8 @@ pub enum CallCallbackError {
/// events from the windowing system in order to render to the screen
/// and react to user input.
pub fn run_event_loop() {
sixtyfps_rendering_backend_default::backend().run_event_loop();
sixtyfps_rendering_backend_default::backend()
.run_event_loop(sixtyfps_corelib::backend::EventLoopQuitBehavior::QuitOnLastWindowClosed);
}
/// This module constains a few function use by tests

View file

@ -159,7 +159,7 @@ pub enum CustomEvent {
/// Runs the event loop and renders the items in the provided `component` in its
/// own window.
#[allow(unused_mut)] // mut need changes for wasm
pub fn run() {
pub fn run(quit_behavior: sixtyfps_corelib::backend::EventLoopQuitBehavior) {
use winit::event::Event;
use winit::event_loop::{ControlFlow, EventLoopWindowTarget};
@ -193,8 +193,25 @@ pub fn run() {
match event {
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => *control_flow = winit::event_loop::ControlFlow::Exit,
window_id,
} => {
ALL_WINDOWS
.with(|windows| {
windows.borrow().get(&window_id).and_then(|weakref| weakref.upgrade())
})
.map(|window_rc| {
window_rc.hide();
});
match quit_behavior {
corelib::backend::EventLoopQuitBehavior::QuitOnLastWindowClosed => {
let window_count = ALL_WINDOWS.with(|windows| windows.borrow().len());
if window_count == 0 {
*control_flow = winit::event_loop::ControlFlow::Exit;
}
}
corelib::backend::EventLoopQuitBehavior::QuitOnlyExplicitly => {}
}
}
winit::event::Event::RedrawRequested(id) => {
corelib::animations::update_animations();
ALL_WINDOWS.with(|windows| {

View file

@ -257,17 +257,6 @@ impl GraphicsWindow {
}
}
impl Drop for GraphicsWindow {
fn drop(&mut self) {
match &*self.map_state.borrow() {
GraphicsWindowBackendState::Unmapped => {}
GraphicsWindowBackendState::Mapped(mw) => {
crate::eventloop::unregister_window(mw.backend.borrow().window().id());
}
}
}
}
impl GraphicsWindow {
/// Draw the items of the specified `component` in the given window.
pub fn draw(self: Rc<Self>) {
@ -534,6 +523,12 @@ struct MappedWindow {
constraints: Cell<corelib::layout::LayoutInfo>,
}
impl Drop for MappedWindow {
fn drop(&mut self) {
crate::eventloop::unregister_window(self.backend.borrow().window().id());
}
}
enum GraphicsWindowBackendState {
Unmapped,
Mapped(MappedWindow),

View file

@ -1483,8 +1483,8 @@ impl sixtyfps_corelib::backend::Backend for Backend {
ComponentWindow(window)
}
fn run_event_loop(&'static self) {
crate::eventloop::run();
fn run_event_loop(&'static self, behavior: sixtyfps_corelib::backend::EventLoopQuitBehavior) {
crate::eventloop::run(behavior);
}
fn quit_event_loop(&'static self) {

View file

@ -111,14 +111,19 @@ impl sixtyfps_corelib::backend::Backend for Backend {
}
}
fn run_event_loop(&'static self) {
fn run_event_loop(&'static self, _behavior: sixtyfps_corelib::backend::EventLoopQuitBehavior) {
#[cfg(not(no_qt))]
{
let quit_on_last_window_closed = match _behavior {
sixtyfps_corelib::backend::EventLoopQuitBehavior::QuitOnLastWindowClosed => true,
sixtyfps_corelib::backend::EventLoopQuitBehavior::QuitOnlyExplicitly => false,
};
// Schedule any timers with Qt that were set up before this event loop start.
crate::qt_window::timer_event();
use cpp::cpp;
cpp! {unsafe [] {
cpp! {unsafe [quit_on_last_window_closed as "bool"] {
ensure_initialized();
qApp->setQuitOnLastWindowClosed(quit_on_last_window_closed);
qApp->exec();
} }
};

View file

@ -50,7 +50,8 @@ pub fn run_in_ui_thread(f: Box<dyn FnOnce() + Send>) {
}
pub fn start_ui_event_loop() {
sixtyfps_interpreter::run_event_loop();
sixtyfps_rendering_backend_default::backend()
.run_event_loop(sixtyfps_corelib::backend::EventLoopQuitBehavior::QuitOnlyExplicitly);
}
pub fn quit_ui_event_loop() {