Skip to content

Commit

Permalink
feat: Reopen event support for macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
I-Info committed Feb 19, 2024
1 parent c4310af commit 527aa3e
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
61 changes: 61 additions & 0 deletions examples/reopen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#![allow(clippy::single_match)]

use std::collections::HashMap;

use simple_logger::SimpleLogger;
use winit::{
event::{Event, WindowEvent},
event_loop::{EventLoop, EventLoopWindowTarget},
window::{Window, WindowId},
};

#[path = "util/fill.rs"]
mod fill;

fn new_window(event_loop: &EventLoopWindowTarget, windows: &mut HashMap<WindowId, Window>) {
let window = Window::new(event_loop).unwrap();
println!("Opened a new window: {:?}", window.id());
windows.insert(window.id(), window);
}

fn main() -> Result<(), impl std::error::Error> {
SimpleLogger::new().init().unwrap();
let event_loop = EventLoop::new().unwrap();

let mut windows = HashMap::new();
new_window(&event_loop, &mut windows);

event_loop.run(move |event, elwt| {
if let Event::WindowEvent { event, window_id } = event {
match event {
WindowEvent::CloseRequested => {
println!("Window {window_id:?} has received the signal to close");

// This drops the window, causing it to close.
windows.remove(&window_id);

// Keep the event loop running on macOS, even if all windows are closed.
#[cfg(not(target_os = "macos"))]
if windows.is_empty() {
elwt.exit();
}
}
WindowEvent::RedrawRequested => {
if let Some(window) = windows.get(&window_id) {
fill::fill_window(window);
}
}
_ => (),
}
} else if let Event::Reopen {
has_visible_windows,
} = event
{
println!("Reopen event: has_visible_windows={}", has_visible_windows);
// If there are no visible windows, open a new one.
if !has_visible_windows {
new_window(elwt, &mut windows);
}
}
})
}
24 changes: 24 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,25 @@ pub enum Event<T: 'static> {
///
/// - **macOS / Wayland / Windows / Orbital:** Unsupported.
MemoryWarning,

/// Emitted when the application has received a reopen request from OS.
///
/// ## Platform-specific
///
/// ### macOS
///
/// On macOS, the `Reopen` event is emitted in response to an [`applicationShouldHandleReopen`]
/// callback, which is typically called when the user clicks on the application's icon in the Dock.
/// The application should create a new window if it doesn't have any, or bring the
/// existing windows to the front. [has_visible_windows] is `true` if the application has
/// at least one visible window.
///
/// [`applicationShouldHandleReopen`]: https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428638-applicationshouldhandlereopen
///
/// ### Others
///
/// - **Android / iOS / Web / Wayland / Windows / Orbital:** Unsupported.
Reopen { has_visible_windows: bool },
}

impl<T> Event<T> {
Expand All @@ -269,6 +288,11 @@ impl<T> Event<T> {
Suspended => Ok(Suspended),
Resumed => Ok(Resumed),
MemoryWarning => Ok(MemoryWarning),
Reopen {
has_visible_windows,
} => Ok(Reopen {
has_visible_windows,
}),
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/platform_impl/macos/app_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ declare_class!(
// TODO: Notify every window that it will be destroyed, like done in iOS?
self.internal_exit();
}

#[method(applicationShouldHandleReopen:hasVisibleWindows:)]
fn should_handle_reopen(&self, _sender: &Option<&AnyObject>, has_visible_windows: bool) -> bool {
trace_scope!("applicationShouldHandleReopen:hasVisibleWindows:");

self.handle_event(Event::Reopen{ has_visible_windows });
// return true to preserve the default behavior, such as showing the minimized window.
true
}

}
);

Expand Down

0 comments on commit 527aa3e

Please sign in to comment.