Skip to content

Commit

Permalink
Terminate app run loop on Windows when all windows have closed.
Browse files Browse the repository at this point in the history
  • Loading branch information
xStrom committed Apr 17, 2020
1 parent d8b6e14 commit 3b3c4e7
Show file tree
Hide file tree
Showing 20 changed files with 467 additions and 63 deletions.
7 changes: 4 additions & 3 deletions druid-shell/examples/perftest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use time::Instant;
use piet_common::kurbo::{Line, Rect};
use piet_common::{Color, FontBuilder, Piet, RenderContext, Text, TextLayoutBuilder};

use druid_shell::{Application, KeyEvent, WinHandler, WindowBuilder, WindowHandle};
use druid_shell::{AppState, Application, KeyEvent, WinHandler, WindowBuilder, WindowHandle};

const BG_COLOR: Color = Color::rgb8(0x27, 0x28, 0x22);
const FG_COLOR: Color = Color::rgb8(0xf0, 0xf0, 0xea);
Expand Down Expand Up @@ -116,8 +116,9 @@ impl WinHandler for PerfTest {
}

fn main() {
let mut app = Application::new(None);
let mut builder = WindowBuilder::new();
let state = AppState::new();
let mut app = Application::new(state.clone(), None);
let mut builder = WindowBuilder::new(state);
let perf_test = PerfTest {
size: Default::default(),
handle: Default::default(),
Expand Down
9 changes: 5 additions & 4 deletions druid-shell/examples/shello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use druid_shell::kurbo::{Line, Rect, Vec2};
use druid_shell::piet::{Color, RenderContext};

use druid_shell::{
Application, Cursor, FileDialogOptions, FileSpec, HotKey, KeyEvent, KeyModifiers, Menu,
MouseEvent, SysMods, TimerToken, WinHandler, WindowBuilder, WindowHandle,
AppState, Application, Cursor, FileDialogOptions, FileSpec, HotKey, KeyEvent, KeyModifiers,
Menu, MouseEvent, SysMods, TimerToken, WinHandler, WindowBuilder, WindowHandle,
};

const BG_COLOR: Color = Color::rgb8(0x27, 0x28, 0x22);
Expand Down Expand Up @@ -129,8 +129,9 @@ fn main() {
menubar.add_dropdown(Menu::new(), "Application", true);
menubar.add_dropdown(file_menu, "&File", true);

let mut app = Application::new(None);
let mut builder = WindowBuilder::new();
let state = AppState::new();
let mut app = Application::new(state.clone(), None);
let mut builder = WindowBuilder::new(state);
builder.set_handler(Box::new(HelloState::default()));
builder.set_title("Hello example");
builder.set_menu(menubar);
Expand Down
35 changes: 33 additions & 2 deletions druid-shell/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

//! The top-level application type.
use std::sync::atomic::{AtomicBool, Ordering};

use crate::clipboard::Clipboard;
use crate::platform::application as platform;

Expand All @@ -36,14 +38,43 @@ pub trait AppHandler {
fn command(&mut self, id: u32) {}
}

/// The top level application state.
///
/// This helps the application track all the state that it has created,
/// which it later needs to clean up.
#[derive(Clone)]
pub struct AppState(pub(crate) platform::AppState);

impl AppState {
/// Create a new `AppState` instance.
pub fn new() -> AppState {
AppState(platform::AppState::new())
}
}

//TODO: we may want to make the user create an instance of this (Application::global()?)
//but for now I'd like to keep changes minimal.
/// The top level application object.
pub struct Application(platform::Application);

// Used to ensure only one Application instance is ever created.
// This may change in the future.
// For more information see https://github.com/xi-editor/druid/issues/771
static APPLICATION_CREATED: AtomicBool = AtomicBool::new(false);

impl Application {
pub fn new(handler: Option<Box<dyn AppHandler>>) -> Application {
Application(platform::Application::new(handler))
/// Create a new `Application`.
///
/// It takes the application `state` and a `handler` which will be used to inform of events.
///
/// Right now only one application can be created. See [druid#771] for discussion.
///
/// [druid#771]: https://github.com/xi-editor/druid/issues/771
pub fn new(state: AppState, handler: Option<Box<dyn AppHandler>>) -> Application {
if APPLICATION_CREATED.compare_and_swap(false, true, Ordering::AcqRel) {
panic!("The Application instance has already been created.");
}
Application(platform::Application::new(state.0, handler))
}

/// Start the runloop.
Expand Down
2 changes: 1 addition & 1 deletion druid-shell/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mod mouse;
mod platform;
mod window;

pub use application::{AppHandler, Application};
pub use application::{AppHandler, AppState, Application};
pub use clipboard::{Clipboard, ClipboardFormat, FormatId};
pub use common_util::Counter;
pub use dialog::{FileDialogOptions, FileInfo, FileSpec};
Expand Down
11 changes: 10 additions & 1 deletion druid-shell/src/platform/gtk/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,19 @@ thread_local!(
static GTK_APPLICATION: RefCell<Option<GtkApplication>> = RefCell::new(None);
);

#[derive(Clone)]
pub struct AppState;

pub struct Application;

impl AppState {
pub(crate) fn new() -> AppState {
AppState
}
}

impl Application {
pub fn new(_handler: Option<Box<dyn AppHandler>>) -> Application {
pub fn new(_state: AppState, _handler: Option<Box<dyn AppHandler>>) -> Application {
// TODO: we should give control over the application ID to the user
let application = GtkApplication::new(
Some("com.github.xi-editor.druid"),
Expand Down
4 changes: 2 additions & 2 deletions druid-shell/src/platform/gtk/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use gtk::{AccelGroup, ApplicationWindow};
use crate::kurbo::{Point, Size, Vec2};
use crate::piet::{Piet, RenderContext};

use super::application::with_application;
use super::application::{with_application, AppState};
use super::dialog;
use super::menu::Menu;
use super::util::assert_main_thread;
Expand Down Expand Up @@ -111,7 +111,7 @@ pub(crate) struct WindowState {
}

impl WindowBuilder {
pub fn new() -> WindowBuilder {
pub fn new(_app_state: AppState) -> WindowBuilder {
WindowBuilder {
handler: None,
title: String::new(),
Expand Down
11 changes: 10 additions & 1 deletion druid-shell/src/platform/mac/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,21 @@ use crate::application::AppHandler;

static APP_HANDLER_IVAR: &str = "druidAppHandler";

#[derive(Clone)]
pub struct AppState;

pub struct Application {
ns_app: id,
}

impl AppState {
pub(crate) fn new() -> AppState {
AppState
}
}

impl Application {
pub fn new(handler: Option<Box<dyn AppHandler>>) -> Application {
pub fn new(_state: AppState, handler: Option<Box<dyn AppHandler>>) -> Application {
util::assert_main_thread();
unsafe {
let _pool = NSAutoreleasePool::new(nil);
Expand Down
3 changes: 2 additions & 1 deletion druid-shell/src/platform/mac/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use log::{error, info};
use crate::kurbo::{Point, Size, Vec2};
use crate::piet::{Piet, RenderContext};

use super::application::AppState;
use super::dialog;
use super::menu::Menu;
use super::util::{assert_main_thread, make_nsstring};
Expand Down Expand Up @@ -104,7 +105,7 @@ struct ViewState {
}

impl WindowBuilder {
pub fn new() -> WindowBuilder {
pub fn new(_app_state: AppState) -> WindowBuilder {
WindowBuilder {
handler: None,
title: String::new(),
Expand Down
11 changes: 10 additions & 1 deletion druid-shell/src/platform/web/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,19 @@
use super::clipboard::Clipboard;
use crate::application::AppHandler;

#[derive(Clone)]
pub struct AppState;

pub struct Application;

impl AppState {
pub(crate) fn new() -> AppState {
AppState
}
}

impl Application {
pub fn new(_handler: Option<Box<dyn AppHandler>>) -> Application {
pub fn new(_state: AppState, _handler: Option<Box<dyn AppHandler>>) -> Application {
Application
}

Expand Down
3 changes: 2 additions & 1 deletion druid-shell/src/platform/web/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::kurbo::{Point, Size, Vec2};

use crate::piet::RenderContext;

use super::application::AppState;
use super::error::Error;
use super::keycodes::key_to_text;
use super::menu::Menu;
Expand Down Expand Up @@ -296,7 +297,7 @@ fn setup_web_callbacks(window_state: &Rc<WindowState>) {
}

impl WindowBuilder {
pub fn new() -> WindowBuilder {
pub fn new(_app_state: AppState) -> WindowBuilder {
WindowBuilder {
handler: None,
title: String::new(),
Expand Down
Loading

0 comments on commit 3b3c4e7

Please sign in to comment.