Skip to content

Commit

Permalink
Fix AppKitWindowHandle missing NSView
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuckal777 committed Dec 18, 2022
1 parent 31e830e commit fb65495
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 12 deletions.
7 changes: 4 additions & 3 deletions examples/raw-window-handle-with-wgpu/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ extern crate sdl2;
extern crate wgpu;

use std::borrow::Cow;
use wgpu::{SurfaceError, SurfaceTexture};
use wgpu::SurfaceError;

use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Keycode;
Expand All @@ -19,6 +19,7 @@ fn main() -> Result<(), String> {
.window("Raw Window Handle Example", 800, 600)
.position_centered()
.resizable()
.metal_view()
.build()
.map_err(|e| e.to_string())?;
let (width, height) = window.size();
Expand Down Expand Up @@ -138,10 +139,10 @@ fn main() -> Result<(), String> {
}
}

let mut frame = match surface.get_current_texture() {
let frame = match surface.get_current_texture() {
Ok(frame) => frame,
Err(err) => {
let reason = match (err) {
let reason = match err {
SurfaceError::Timeout => "Timeout",
SurfaceError::Outdated => "Outdated",
SurfaceError::Lost => "Lost",
Expand Down
12 changes: 8 additions & 4 deletions src/sdl2/raw_window_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ unsafe impl HasRawWindowHandle for Window {

let mut handle = AppKitWindowHandle::empty();
handle.ns_window = unsafe { wm_info.info.cocoa }.window as *mut libc::c_void;
handle.ns_view = 0 as *mut libc::c_void; // consumer of RawWindowHandle should determine this
handle.ns_view = if self.context().metal_view.is_null() {
panic!("metal_view not initialized, please call WindowBuilder::metal_view() when building the window");
} else {
self.context().metal_view
};

RawWindowHandle::AppKit(handle)
}
Expand Down Expand Up @@ -130,7 +134,7 @@ unsafe impl HasRawDisplayHandle for Window {
// since SDL_GetWindowWMInfo will fail on emscripten
if cfg!(target_os = "emscripten") {
use self::raw_window_handle::WebDisplayHandle;
let mut handle = WebDisplayHandle::empty();
let handle = WebDisplayHandle::empty();
return RawDisplayHandle::Web(handle);
}

Expand Down Expand Up @@ -187,7 +191,7 @@ unsafe impl HasRawDisplayHandle for Window {
#[cfg(target_os = "macos")]
SDL_SYSWM_COCOA => {
use self::raw_window_handle::AppKitDisplayHandle;
let mut handle = AppKitDisplayHandle::empty();
let handle = AppKitDisplayHandle::empty();
RawDisplayHandle::AppKit(handle)
}
#[cfg(any(target_os = "ios"))]
Expand All @@ -204,7 +208,7 @@ unsafe impl HasRawDisplayHandle for Window {

let mut handle = AndroidDisplayHandle::empty();
handle.a_native_window =
unsafe { wm_info.info.android }.window as *mut libc::c_void;
unsafe { wm_info.info.android }.window as *mut libc::c_void;

RawDisplayHandle::Android(handle)
}
Expand Down
32 changes: 27 additions & 5 deletions src/sdl2/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,23 +547,30 @@ impl GLContext {
pub struct WindowContext {
subsystem: VideoSubsystem,
raw: *mut sys::SDL_Window,
pub(crate) metal_view: sys::SDL_MetalView,
}

impl Drop for WindowContext {
#[inline]
#[doc(alias = "SDL_DestroyWindow")]
fn drop(&mut self) {
unsafe { sys::SDL_DestroyWindow(self.raw) };
unsafe {
if !self.metal_view.is_null() {
sys::SDL_Metal_DestroyView(self.metal_view);
}
sys::SDL_DestroyWindow(self.raw)
};
}
}

impl WindowContext {
#[inline]
/// Unsafe if the `*mut SDL_Window` is used after the `WindowContext` is dropped
pub unsafe fn from_ll(subsystem: VideoSubsystem, raw: *mut sys::SDL_Window) -> WindowContext {
pub unsafe fn from_ll(subsystem: VideoSubsystem, raw: *mut sys::SDL_Window, metal_view: sys::SDL_MetalView) -> WindowContext {
WindowContext {
subsystem: subsystem.clone(),
raw,
metal_view,
}
}
}
Expand Down Expand Up @@ -1098,6 +1105,7 @@ pub struct WindowBuilder {
x: WindowPos,
y: WindowPos,
window_flags: u32,
create_metal_view: bool,
/// The window builder cannot be built on a non-main thread, so prevent cross-threaded moves and references.
/// `!Send` and `!Sync`,
subsystem: VideoSubsystem,
Expand All @@ -1114,6 +1122,7 @@ impl WindowBuilder {
y: WindowPos::Undefined,
window_flags: 0,
subsystem: v.clone(),
create_metal_view: false,
}
}

Expand Down Expand Up @@ -1143,11 +1152,16 @@ impl WindowBuilder {
raw_height,
self.window_flags,
);
let mut metal_view = 0 as sys::SDL_MetalView;
#[cfg(target_os="macos")]
if self.create_metal_view {
metal_view = sys::SDL_Metal_CreateView(raw);
}

if raw.is_null() {
Err(SdlError(get_error()))
} else {
Ok(Window::from_ll(self.subsystem.clone(), raw))
Ok(Window::from_ll(self.subsystem.clone(), raw, metal_view))
}
}
}
Expand Down Expand Up @@ -1243,6 +1257,14 @@ impl WindowBuilder {
self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_ALLOW_HIGHDPI as u32;
self
}

/// Create a SDL_MetalView when constructing the window.
/// This is required when using the raw_window_handle feature on MacOS.
/// Has no effect no other platforms.
pub fn metal_view(&mut self) -> &mut WindowBuilder {
self.create_metal_view = true;
self
}
}

impl From<Window> for CanvasBuilder {
Expand All @@ -1261,8 +1283,8 @@ impl Window {
}

#[inline]
pub unsafe fn from_ll(subsystem: VideoSubsystem, raw: *mut sys::SDL_Window) -> Window {
let context = WindowContext::from_ll(subsystem, raw);
pub unsafe fn from_ll(subsystem: VideoSubsystem, raw: *mut sys::SDL_Window, metal_view: sys::SDL_MetalView) -> Window {
let context = WindowContext::from_ll(subsystem, raw, metal_view);
context.into()
}

Expand Down

0 comments on commit fb65495

Please sign in to comment.