Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions winit-appkit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ objc2-app-kit = { workspace = true, features = [
"NSTrackingArea",
"NSToolbar",
"NSView",
"NSVisualEffectView",
"NSWindow",
"NSWindowScripting",
"NSWindowTabGroup",
Expand Down
13 changes: 0 additions & 13 deletions winit-appkit/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

use std::ffi::c_void;

use objc2::ffi::NSInteger;
use objc2::runtime::AnyObject;
use objc2_core_foundation::{CFString, CFUUID, cf_type};
use objc2_core_graphics::CGDirectDisplayID;

Expand All @@ -28,17 +26,6 @@ unsafe extern "C" {
pub fn CGDisplayGetDisplayIDFromUUID(uuid: &CFUUID) -> CGDirectDisplayID;
}

#[link(name = "CoreGraphics", kind = "framework")]
unsafe extern "C" {
// Wildly used private APIs; Apple uses them for their Terminal.app.
pub fn CGSMainConnectionID() -> *mut AnyObject;
pub fn CGSSetWindowBackgroundBlurRadius(
connection_id: *mut AnyObject,
window_id: NSInteger,
radius: i64,
) -> i32;
}

#[repr(transparent)]
pub struct TISInputSource(std::ffi::c_void);

Expand Down
1 change: 1 addition & 0 deletions winit-appkit/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ define_class!(
#[unsafe(super(NSView, NSResponder, NSObject))]
#[ivars = ViewState]
#[name = "WinitView"]
#[derive(Debug)]
pub(super) struct WinitView;

/// This documentation attribute makes rustfmt work for some reason?
Expand Down
59 changes: 41 additions & 18 deletions winit-appkit/src/window_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ use objc2::{
};
use objc2_app_kit::{
NSAppKitVersionNumber, NSAppKitVersionNumber10_12, NSAppearance, NSAppearanceCustomization,
NSAppearanceNameAqua, NSApplication, NSApplicationPresentationOptions, NSBackingStoreType,
NSColor, NSDraggingDestination, NSDraggingInfo, NSRequestUserAttentionType, NSScreen,
NSToolbar, NSView, NSViewFrameDidChangeNotification, NSWindow, NSWindowButton,
NSWindowDelegate, NSWindowLevel, NSWindowOcclusionState, NSWindowOrderingMode,
NSWindowSharingType, NSWindowStyleMask, NSWindowTabbingMode, NSWindowTitleVisibility,
NSWindowToolbarStyle,
NSAppearanceNameAqua, NSApplication, NSApplicationPresentationOptions,
NSAutoresizingMaskOptions, NSBackingStoreType, NSColor, NSDraggingDestination, NSDraggingInfo,
NSRequestUserAttentionType, NSScreen, NSToolbar, NSView, NSViewFrameDidChangeNotification,
NSVisualEffectBlendingMode, NSVisualEffectMaterial, NSVisualEffectState, NSVisualEffectView,
NSWindow, NSWindowButton, NSWindowDelegate, NSWindowLevel, NSWindowOcclusionState,
NSWindowOrderingMode, NSWindowSharingType, NSWindowStyleMask, NSWindowTabbingMode,
NSWindowTitleVisibility, NSWindowToolbarStyle,
};
#[allow(deprecated)]
use objc2_app_kit::{NSFilenamesPboardType, NSWindowFullScreenButton};
Expand Down Expand Up @@ -55,7 +56,6 @@ use winit_core::window::{

use super::app_state::AppState;
use super::cursor::{CustomCursor, cursor_from_icon};
use super::ffi;
use super::monitor::{self, MonitorHandle, flip_window_screen_coordinates, get_display_id};
use super::util::cgerr;
use super::view::WinitView;
Expand All @@ -69,6 +69,8 @@ pub(crate) struct State {

window: Retained<NSWindow>,

view: Retained<WinitView>,

// During `windowDidResize`, we use this to only send Moved if the position changed.
//
// This is expressed in desktop coordinates, and flipped to match Winit's coordinate system.
Expand Down Expand Up @@ -779,6 +781,12 @@ impl WindowDelegate {
let window = new_window(app_state, &attrs, &macos_attrs, mtm)
.ok_or_else(|| os_error!("couldn't create `NSWindow`"))?;

let view: Retained<WinitView> = window
.contentView()
.expect("window should have a content view")
.downcast()
.expect("content view should be a `WinitView`");

match attrs.parent_window() {
Some(rwh_06::RawWindowHandle::AppKit(handle)) => {
// SAFETY: Caller ensures the pointer is valid or NULL
Expand Down Expand Up @@ -817,6 +825,7 @@ impl WindowDelegate {
let delegate = mtm.alloc().set_ivars(State {
app_state: Rc::clone(app_state),
window: window.retain(),
view,
previous_position: Cell::new(flip_window_screen_coordinates(window.frame())),
previous_scale_factor: Cell::new(scale_factor),
surface_resize_increments: Cell::new(surface_resize_increments),
Expand Down Expand Up @@ -888,8 +897,7 @@ impl WindowDelegate {

#[track_caller]
pub(super) fn view(&self) -> Retained<WinitView> {
// The view inside WinitWindow should always be set and be `WinitView`.
self.window().contentView().unwrap().downcast().unwrap()
self.ivars().view.clone()
}

#[track_caller]
Expand Down Expand Up @@ -970,16 +978,31 @@ impl WindowDelegate {
}

pub fn set_blur(&self, blur: bool) {
// NOTE: in general we want to specify the blur radius, but the choice of 80
// should be a reasonable default.
let radius = if blur { 80 } else { 0 };
let window_number = self.window().windowNumber();
unsafe {
ffi::CGSSetWindowBackgroundBlurRadius(
ffi::CGSMainConnectionID(),
window_number,
radius,
let window = self.window();
let view = self.view();
let currently_blurred = window
.contentView()
.is_some_and(|content| content.downcast::<NSVisualEffectView>().is_ok());
if blur == currently_blurred {
return;
}

if blur {
let mtm = MainThreadMarker::from(self);
let effect_view = NSVisualEffectView::new(mtm);
effect_view.setBlendingMode(NSVisualEffectBlendingMode::BehindWindow);
effect_view.setState(NSVisualEffectState::Active);
effect_view.setMaterial(NSVisualEffectMaterial::WindowBackground);

window.setContentView(Some(&effect_view));
view.setFrame(effect_view.bounds());
view.setAutoresizingMask(
NSAutoresizingMaskOptions::ViewWidthSizable
| NSAutoresizingMaskOptions::ViewHeightSizable,
);
effect_view.addSubview(&view);
} else {
window.setContentView(Some(&view));
}
}

Expand Down
2 changes: 2 additions & 0 deletions winit/src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,5 @@ changelog entry.
- On macOS, fix borderless game presentation options not sticking after switching spaces.
- On macOS, fix IME being locked on (regardless of requests to disable) after being enabled once.
- On macOS, fix a panic and incorrect cursor position in Ime::Preedit when the preedit string contains special characters (ie. emojis) caused by incorrect UTF-16 to UTF-8 offset conversion.
- On macOS fix private `CGSSetWindowBackgroundBlurRadius` call causing App Store rejection, `NSVisualEffectView` replacement.

Loading