Add 'WindowEvent::Occluded(bool)'

This commits and an event to track window occlusion state,
which could help optimize rendering downstream.
This commit is contained in:
trimental 2022-07-06 18:46:25 +00:00 committed by GitHub
parent 4b10993970
commit e289f30e5d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 3 deletions

View file

@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre
# Unreleased # Unreleased
- Added `WindowEvent::Occluded(bool)`, currently implemented on macOS and X11.
- On X11, fix events for caps lock key not being sent - On X11, fix events for caps lock key not being sent
- Build docs on `docs.rs` for iOS and Android as well. - Build docs on `docs.rs` for iOS and Android as well.
- **Breaking:** Removed the `WindowAttributes` struct, since all its functionality is accessible from `WindowBuilder`. - **Breaking:** Removed the `WindowAttributes` struct, since all its functionality is accessible from `WindowBuilder`.

View file

@ -372,6 +372,15 @@ pub enum WindowEvent<'a> {
/// ///
/// At the moment this is only supported on Windows. /// At the moment this is only supported on Windows.
ThemeChanged(Theme), ThemeChanged(Theme),
/// The window has been occluded (completely hidden from view).
///
/// This is different to window visibility as it depends on whether the window is closed,
/// minimised, set invisible, or fully occluded by another window.
///
/// Platform-specific behavior:
/// - **iOS / Android / Web / Wayland / Windows :** Unsupported.
Occluded(bool),
} }
impl Clone for WindowEvent<'static> { impl Clone for WindowEvent<'static> {
@ -461,6 +470,7 @@ impl Clone for WindowEvent<'static> {
ScaleFactorChanged { .. } => { ScaleFactorChanged { .. } => {
unreachable!("Static event can't be about scale factor changing") unreachable!("Static event can't be about scale factor changing")
} }
Occluded(occluded) => Occluded(*occluded),
}; };
} }
} }
@ -546,6 +556,7 @@ impl<'a> WindowEvent<'a> {
Touch(touch) => Some(Touch(touch)), Touch(touch) => Some(Touch(touch)),
ThemeChanged(theme) => Some(ThemeChanged(theme)), ThemeChanged(theme) => Some(ThemeChanged(theme)),
ScaleFactorChanged { .. } => None, ScaleFactorChanged { .. } => None,
Occluded(occluded) => Some(Occluded(occluded)),
} }
} }
} }

View file

@ -531,8 +531,13 @@ impl<T: 'static> EventProcessor<T> {
ffi::VisibilityNotify => { ffi::VisibilityNotify => {
let xev: &ffi::XVisibilityEvent = xev.as_ref(); let xev: &ffi::XVisibilityEvent = xev.as_ref();
let xwindow = xev.window; let xwindow = xev.window;
callback(Event::WindowEvent {
self.with_window(xwindow, |window| window.visibility_notify()); window_id: mkwid(xwindow),
event: WindowEvent::Occluded(xev.state == ffi::VisibilityFullyObscured),
});
self.with_window(xwindow, |window| {
window.visibility_notify();
});
} }
ffi::Expose => { ffi::Expose => {

View file

@ -5,7 +5,7 @@ use std::{
}; };
use cocoa::{ use cocoa::{
appkit::{self, NSApplicationPresentationOptions, NSView, NSWindow}, appkit::{self, NSApplicationPresentationOptions, NSView, NSWindow, NSWindowOcclusionState},
base::{id, nil}, base::{id, nil},
foundation::NSUInteger, foundation::NSUInteger,
}; };
@ -220,6 +220,10 @@ static WINDOW_DELEGATE_CLASS: Lazy<WindowDelegateClass> = Lazy::new(|| unsafe {
sel!(windowDidFailToEnterFullScreen:), sel!(windowDidFailToEnterFullScreen:),
window_did_fail_to_enter_fullscreen as extern "C" fn(&Object, Sel, id), window_did_fail_to_enter_fullscreen as extern "C" fn(&Object, Sel, id),
); );
decl.add_method(
sel!(windowDidChangeOcclusionState:),
window_did_change_occlusion_state as extern "C" fn(&Object, Sel, id),
);
decl.add_ivar::<*mut c_void>("winitState"); decl.add_ivar::<*mut c_void>("winitState");
WindowDelegateClass(decl.register()) WindowDelegateClass(decl.register())
@ -554,3 +558,18 @@ extern "C" fn window_did_fail_to_enter_fullscreen(this: &Object, _: Sel, _: id)
} }
}); });
} }
// Invoked when the occlusion state of the window changes
extern "C" fn window_did_change_occlusion_state(this: &Object, _: Sel, _: id) {
trace_scope!("windowDidChangeOcclusionState:");
unsafe {
with_state(this, |state| {
state.emit_event(WindowEvent::Occluded(
!state
.ns_window
.occlusionState()
.contains(NSWindowOcclusionState::NSWindowOcclusionStateVisible),
))
});
}
}