From 19e4385dad94089388165df9e7d354a9b2ecc453 Mon Sep 17 00:00:00 2001
From: Bruce Mitchener <bruce.mitchener@gmail.com>
Date: Tue, 23 Apr 2024 21:12:04 +0700
Subject: [PATCH] Update dev-dependencies: cocoa, glam, winit.

---
 Cargo.toml                    |   6 +-
 examples/circle/main.rs       | 165 +++++++++++++-------------
 examples/mesh-shader/main.rs  | 106 +++++++++--------
 examples/raytracing/main.rs   |  58 +++++-----
 examples/shader-dylib/main.rs |  56 ++++-----
 examples/texture/Cargo.toml   |   4 +-
 examples/texture/src/main.rs  |  85 +++++++-------
 examples/window/main.rs       | 212 ++++++++++++++++++----------------
 8 files changed, 361 insertions(+), 331 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 6a3d426b..1165da08 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,12 +34,12 @@ paste = "1"
 version = "0.2.4"
 
 [dev-dependencies]
-cocoa = "0.24.0"
+cocoa = "0.25.0"
 cty = "0.2.1"
-winit = "0.27"
+winit = "0.29"
 sema = "0.1.4"
 png = "0.17"
-glam = "0.22"
+glam = "0.27"
 rand = "0.8"
 
 [[example]]
diff --git a/examples/circle/main.rs b/examples/circle/main.rs
index ed17a734..7124a589 100644
--- a/examples/circle/main.rs
+++ b/examples/circle/main.rs
@@ -3,7 +3,7 @@ use metal::*;
 use winit::{
     event::{Event, WindowEvent},
     event_loop::{ControlFlow, EventLoop},
-    platform::macos::WindowExtMacOS,
+    raw_window_handle::{HasWindowHandle, RawWindowHandle},
 };
 
 use cocoa::{appkit::NSView, base::id as cocoa_id};
@@ -33,7 +33,7 @@ pub struct AAPLVertex {
 
 fn main() {
     // Create a window for viewing the content
-    let event_loop = EventLoop::new();
+    let event_loop = EventLoop::new().unwrap();
     let size = winit::dpi::LogicalSize::new(800, 600);
 
     let window = winit::window::WindowBuilder::new()
@@ -100,9 +100,11 @@ fn main() {
     layer.set_presents_with_transaction(false);
 
     unsafe {
-        let view = window.ns_view() as cocoa_id;
-        view.setWantsLayer(YES);
-        view.setLayer(mem::transmute(layer.as_ref()));
+        if let Ok(RawWindowHandle::AppKit(rw)) = window.window_handle().map(|wh| wh.as_raw()) {
+            let view = rw.ns_view.as_ptr() as cocoa_id;
+            view.setWantsLayer(YES);
+            view.setLayer(mem::transmute(layer.as_ref()));
+        }
     }
 
     let draw_size = window.inner_size();
@@ -119,80 +121,87 @@ fn main() {
         )
     };
 
-    event_loop.run(move |event, _, control_flow| {
-        autoreleasepool(|| {
-            // ControlFlow::Wait pauses the event loop if no events are available to process.
-            // This is ideal for non-game applications that only update in response to user
-            // input, and uses significantly less power/CPU time than ControlFlow::Poll.
-            *control_flow = ControlFlow::Wait;
-
-            match event {
-                Event::WindowEvent {
-                    event: WindowEvent::CloseRequested,
-                    ..
-                } => {
-                    println!("The close button was pressed; stopping");
-                    *control_flow = ControlFlow::Exit
-                }
-                Event::MainEventsCleared => {
-                    // Queue a RedrawRequested event.
-                    window.request_redraw();
-                }
-                Event::RedrawRequested(_) => {
-                    // It's preferrable to render in this event rather than in MainEventsCleared, since
-                    // rendering in here allows the program to gracefully handle redraws requested
-                    // by the OS.
-                    let drawable = match layer.next_drawable() {
-                        Some(drawable) => drawable,
-                        None => return,
-                    };
-
-                    // Create a new command buffer for each render pass to the current drawable
-                    let command_buffer = command_queue.new_command_buffer();
-
-                    // Obtain a renderPassDescriptor generated from the view's drawable textures.
-                    let render_pass_descriptor = RenderPassDescriptor::new();
-                    handle_render_pass_color_attachment(
-                        &render_pass_descriptor,
-                        drawable.texture(),
-                    );
-                    handle_render_pass_sample_buffer_attachment(
-                        &render_pass_descriptor,
-                        &counter_sample_buffer,
-                    );
-
-                    // Create a render command encoder.
-                    let encoder =
-                        command_buffer.new_render_command_encoder(&render_pass_descriptor);
-                    encoder.set_render_pipeline_state(&pipeline_state);
-                    // Pass in the parameter data.
-                    encoder.set_vertex_buffer(0, Some(&vbuf), 0);
-                    // Draw the triangles which will eventually form the circle.
-                    encoder.draw_primitives(MTLPrimitiveType::TriangleStrip, 0, 1080);
-                    encoder.end_encoding();
-
-                    resolve_samples_into_buffer(
-                        &command_buffer,
-                        &counter_sample_buffer,
-                        &destination_buffer,
-                    );
-
-                    // Schedule a present once the framebuffer is complete using the current drawable.
-                    command_buffer.present_drawable(&drawable);
-
-                    // Finalize rendering here & push the command buffer to the GPU.
-                    command_buffer.commit();
-                    command_buffer.wait_until_completed();
-
-                    let mut cpu_end = 0;
-                    let mut gpu_end = 0;
-                    device.sample_timestamps(&mut cpu_end, &mut gpu_end);
-                    handle_timestamps(&destination_buffer, cpu_start, cpu_end, gpu_start, gpu_end);
+    event_loop
+        .run(move |event, event_loop| {
+            autoreleasepool(|| {
+                // ControlFlow::Wait pauses the event loop if no events are available to process.
+                // This is ideal for non-game applications that only update in response to user
+                // input, and uses significantly less power/CPU time than ControlFlow::Poll.
+                event_loop.set_control_flow(ControlFlow::Wait);
+
+                match event {
+                    Event::AboutToWait => window.request_redraw(),
+                    Event::WindowEvent { event, .. } => {
+                        match event {
+                            WindowEvent::CloseRequested => {
+                                println!("The close button was pressed; stopping");
+                                event_loop.exit();
+                            }
+                            WindowEvent::RedrawRequested => {
+                                // It's preferrable to render in this event rather than in MainEventsCleared, since
+                                // rendering in here allows the program to gracefully handle redraws requested
+                                // by the OS.
+                                let drawable = match layer.next_drawable() {
+                                    Some(drawable) => drawable,
+                                    None => return,
+                                };
+
+                                // Create a new command buffer for each render pass to the current drawable
+                                let command_buffer = command_queue.new_command_buffer();
+
+                                // Obtain a renderPassDescriptor generated from the view's drawable textures.
+                                let render_pass_descriptor = RenderPassDescriptor::new();
+                                handle_render_pass_color_attachment(
+                                    &render_pass_descriptor,
+                                    drawable.texture(),
+                                );
+                                handle_render_pass_sample_buffer_attachment(
+                                    &render_pass_descriptor,
+                                    &counter_sample_buffer,
+                                );
+
+                                // Create a render command encoder.
+                                let encoder = command_buffer
+                                    .new_render_command_encoder(&render_pass_descriptor);
+                                encoder.set_render_pipeline_state(&pipeline_state);
+                                // Pass in the parameter data.
+                                encoder.set_vertex_buffer(0, Some(&vbuf), 0);
+                                // Draw the triangles which will eventually form the circle.
+                                encoder.draw_primitives(MTLPrimitiveType::TriangleStrip, 0, 1080);
+                                encoder.end_encoding();
+
+                                resolve_samples_into_buffer(
+                                    &command_buffer,
+                                    &counter_sample_buffer,
+                                    &destination_buffer,
+                                );
+
+                                // Schedule a present once the framebuffer is complete using the current drawable.
+                                command_buffer.present_drawable(&drawable);
+
+                                // Finalize rendering here & push the command buffer to the GPU.
+                                command_buffer.commit();
+                                command_buffer.wait_until_completed();
+
+                                let mut cpu_end = 0;
+                                let mut gpu_end = 0;
+                                device.sample_timestamps(&mut cpu_end, &mut gpu_end);
+                                handle_timestamps(
+                                    &destination_buffer,
+                                    cpu_start,
+                                    cpu_end,
+                                    gpu_start,
+                                    gpu_end,
+                                );
+                            }
+                            _ => (),
+                        }
+                    }
+                    _ => (),
                 }
-                _ => (),
-            }
-        });
-    });
+            });
+        })
+        .unwrap();
 }
 
 // If we want to draw a circle, we need to draw it out of the three primitive
diff --git a/examples/mesh-shader/main.rs b/examples/mesh-shader/main.rs
index 8edb30ce..df8f5929 100644
--- a/examples/mesh-shader/main.rs
+++ b/examples/mesh-shader/main.rs
@@ -6,11 +6,11 @@ use core_graphics_types::geometry::CGSize;
 use metal::*;
 use objc::{rc::autoreleasepool, runtime::YES};
 use std::mem;
-use winit::platform::macos::WindowExtMacOS;
 
 use winit::{
     event::{Event, WindowEvent},
     event_loop::ControlFlow,
+    raw_window_handle::{HasWindowHandle, RawWindowHandle},
 };
 
 fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) {
@@ -23,13 +23,13 @@ fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture:
 }
 
 fn main() {
-    let events_loop = winit::event_loop::EventLoop::new();
+    let event_loop = winit::event_loop::EventLoop::new().unwrap();
     let size = winit::dpi::LogicalSize::new(800, 600);
 
     let window = winit::window::WindowBuilder::new()
         .with_inner_size(size)
         .with_title("Metal Mesh Shader Example".to_string())
-        .build(&events_loop)
+        .build(&event_loop)
         .unwrap();
 
     let device = Device::system_default().expect("no device found");
@@ -40,9 +40,11 @@ fn main() {
     layer.set_presents_with_transaction(false);
 
     unsafe {
-        let view = window.ns_view() as cocoa_id;
-        view.setWantsLayer(YES);
-        view.setLayer(mem::transmute(layer.as_ref()));
+        if let Ok(RawWindowHandle::AppKit(rw)) = window.window_handle().map(|wh| wh.as_raw()) {
+            let view = rw.ns_view.as_ptr() as cocoa_id;
+            view.setWantsLayer(YES);
+            view.setLayer(mem::transmute(layer.as_ref()));
+        }
     }
 
     let draw_size = window.inner_size();
@@ -70,49 +72,57 @@ fn main() {
 
     let command_queue = device.new_command_queue();
 
-    events_loop.run(move |event, _, control_flow| {
-        autoreleasepool(|| {
-            *control_flow = ControlFlow::Poll;
+    event_loop
+        .run(move |event, event_loop| {
+            autoreleasepool(|| {
+                event_loop.set_control_flow(ControlFlow::Poll);
 
-            match event {
-                Event::WindowEvent { event, .. } => match event {
-                    WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
-                    WindowEvent::Resized(size) => {
-                        layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));
+                match event {
+                    Event::AboutToWait => {
+                        window.request_redraw();
                     }
-                    _ => (),
-                },
-                Event::MainEventsCleared => {
-                    window.request_redraw();
+                    Event::WindowEvent { event, .. } => match event {
+                        WindowEvent::CloseRequested => event_loop.exit(),
+                        WindowEvent::Resized(size) => {
+                            layer.set_drawable_size(CGSize::new(
+                                size.width as f64,
+                                size.height as f64,
+                            ));
+                        }
+                        WindowEvent::RedrawRequested => {
+                            let drawable = match layer.next_drawable() {
+                                Some(drawable) => drawable,
+                                None => return,
+                            };
+
+                            let render_pass_descriptor = RenderPassDescriptor::new();
+
+                            prepare_render_pass_descriptor(
+                                &render_pass_descriptor,
+                                drawable.texture(),
+                            );
+
+                            let command_buffer = command_queue.new_command_buffer();
+                            let encoder =
+                                command_buffer.new_render_command_encoder(&render_pass_descriptor);
+
+                            encoder.set_render_pipeline_state(&pipeline_state);
+                            encoder.draw_mesh_threads(
+                                MTLSize::new(1, 1, 1),
+                                MTLSize::new(1, 1, 1),
+                                MTLSize::new(1, 1, 1),
+                            );
+
+                            encoder.end_encoding();
+
+                            command_buffer.present_drawable(&drawable);
+                            command_buffer.commit();
+                        }
+                        _ => (),
+                    },
+                    _ => {}
                 }
-                Event::RedrawRequested(_) => {
-                    let drawable = match layer.next_drawable() {
-                        Some(drawable) => drawable,
-                        None => return,
-                    };
-
-                    let render_pass_descriptor = RenderPassDescriptor::new();
-
-                    prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture());
-
-                    let command_buffer = command_queue.new_command_buffer();
-                    let encoder =
-                        command_buffer.new_render_command_encoder(&render_pass_descriptor);
-
-                    encoder.set_render_pipeline_state(&pipeline_state);
-                    encoder.draw_mesh_threads(
-                        MTLSize::new(1, 1, 1),
-                        MTLSize::new(1, 1, 1),
-                        MTLSize::new(1, 1, 1),
-                    );
-
-                    encoder.end_encoding();
-
-                    command_buffer.present_drawable(&drawable);
-                    command_buffer.commit();
-                }
-                _ => {}
-            }
-        });
-    });
+            });
+        })
+        .unwrap();
 }
diff --git a/examples/raytracing/main.rs b/examples/raytracing/main.rs
index 68eaf3df..4c4aed12 100644
--- a/examples/raytracing/main.rs
+++ b/examples/raytracing/main.rs
@@ -8,7 +8,7 @@ use std::mem;
 use winit::{
     event::{Event, WindowEvent},
     event_loop::ControlFlow,
-    platform::macos::WindowExtMacOS,
+    raw_window_handle::{HasWindowHandle, RawWindowHandle},
 };
 
 pub mod camera;
@@ -31,13 +31,13 @@ fn find_raytracing_supporting_device() -> Device {
 }
 
 fn main() {
-    let events_loop = winit::event_loop::EventLoop::new();
+    let event_loop = winit::event_loop::EventLoop::new().unwrap();
     let size = winit::dpi::LogicalSize::new(800, 600);
 
     let window = winit::window::WindowBuilder::new()
         .with_inner_size(size)
         .with_title("Metal Raytracing Example".to_string())
-        .build(&events_loop)
+        .build(&event_loop)
         .unwrap();
 
     let device = find_raytracing_supporting_device();
@@ -48,9 +48,11 @@ fn main() {
     layer.set_presents_with_transaction(false);
 
     unsafe {
-        let view = window.ns_view() as cocoa_id;
-        view.setWantsLayer(YES);
-        view.setLayer(mem::transmute(layer.as_ref()));
+        if let Ok(RawWindowHandle::AppKit(rw)) = window.window_handle().map(|wh| wh.as_raw()) {
+            let view = rw.ns_view.as_ptr() as cocoa_id;
+            view.setWantsLayer(YES);
+            view.setLayer(mem::transmute(layer.as_ref()));
+        }
     }
 
     let draw_size = window.inner_size();
@@ -60,28 +62,28 @@ fn main() {
     let mut renderer = renderer::Renderer::new(device);
     renderer.window_resized(cg_size);
 
-    events_loop.run(move |event, _, control_flow| {
-        autoreleasepool(|| {
-            *control_flow = ControlFlow::Poll;
+    event_loop
+        .run(move |event, event_loop| {
+            autoreleasepool(|| {
+                event_loop.set_control_flow(ControlFlow::Poll);
 
-            match event {
-                Event::WindowEvent { event, .. } => match event {
-                    WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
-                    WindowEvent::Resized(size) => {
-                        let size = CGSize::new(size.width as f64, size.height as f64);
-                        layer.set_drawable_size(size);
-                        renderer.window_resized(size);
-                    }
-                    _ => (),
-                },
-                Event::MainEventsCleared => {
-                    window.request_redraw();
-                }
-                Event::RedrawRequested(_) => {
-                    renderer.draw(&layer);
+                match event {
+                    Event::AboutToWait => window.request_redraw(),
+                    Event::WindowEvent { event, .. } => match event {
+                        WindowEvent::CloseRequested => event_loop.exit(),
+                        WindowEvent::Resized(size) => {
+                            let size = CGSize::new(size.width as f64, size.height as f64);
+                            layer.set_drawable_size(size);
+                            renderer.window_resized(size);
+                        }
+                        WindowEvent::RedrawRequested => {
+                            renderer.draw(&layer);
+                        }
+                        _ => (),
+                    },
+                    _ => {}
                 }
-                _ => {}
-            }
-        });
-    });
+            });
+        })
+        .unwrap();
 }
diff --git a/examples/shader-dylib/main.rs b/examples/shader-dylib/main.rs
index 60b6aa0d..8dd2582c 100644
--- a/examples/shader-dylib/main.rs
+++ b/examples/shader-dylib/main.rs
@@ -7,7 +7,7 @@ use objc::{rc::autoreleasepool, runtime::YES};
 use winit::{
     event::{Event, WindowEvent},
     event_loop::ControlFlow,
-    platform::macos::WindowExtMacOS,
+    raw_window_handle::{HasWindowHandle, RawWindowHandle},
 };
 
 use std::mem;
@@ -43,9 +43,11 @@ impl App {
         layer.set_presents_with_transaction(false);
         layer.set_framebuffer_only(false);
         unsafe {
-            let view = window.ns_view() as cocoa_id;
-            view.setWantsLayer(YES);
-            view.setLayer(mem::transmute(layer.as_ref()));
+            if let Ok(RawWindowHandle::AppKit(rw)) = window.window_handle().map(|wh| wh.as_raw()) {
+                let view = rw.ns_view.as_ptr() as cocoa_id;
+                view.setWantsLayer(YES);
+                view.setLayer(mem::transmute(layer.as_ref()));
+            }
         }
         let draw_size = window.inner_size();
         layer.set_drawable_size(CGSize::new(draw_size.width as f64, draw_size.height as f64));
@@ -141,37 +143,37 @@ impl App {
 }
 
 fn main() {
-    let events_loop = winit::event_loop::EventLoop::new();
+    let event_loop = winit::event_loop::EventLoop::new().unwrap();
     let size = winit::dpi::LogicalSize::new(800, 600);
 
     let window = winit::window::WindowBuilder::new()
         .with_inner_size(size)
         .with_title("Metal Shader Dylib Example".to_string())
-        .build(&events_loop)
+        .build(&event_loop)
         .unwrap();
 
     let mut app = App::new(&window);
 
-    events_loop.run(move |event, _, control_flow| {
-        autoreleasepool(|| {
-            *control_flow = ControlFlow::Poll;
-
-            match event {
-                Event::WindowEvent { event, .. } => match event {
-                    WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
-                    WindowEvent::Resized(size) => {
-                        app.resize(size.width, size.height);
-                    }
-                    _ => (),
-                },
-                Event::MainEventsCleared => {
-                    window.request_redraw();
-                }
-                Event::RedrawRequested(_) => {
-                    app.draw();
+    event_loop
+        .run(move |event, event_loop| {
+            autoreleasepool(|| {
+                event_loop.set_control_flow(ControlFlow::Poll);
+
+                match event {
+                    Event::AboutToWait => window.request_redraw(),
+                    Event::WindowEvent { event, .. } => match event {
+                        WindowEvent::CloseRequested => event_loop.exit(),
+                        WindowEvent::Resized(size) => {
+                            app.resize(size.width, size.height);
+                        }
+                        WindowEvent::RedrawRequested => {
+                            app.draw();
+                        }
+                        _ => (),
+                    },
+                    _ => {}
                 }
-                _ => {}
-            }
-        });
-    });
+            });
+        })
+        .unwrap();
 }
diff --git a/examples/texture/Cargo.toml b/examples/texture/Cargo.toml
index 8af54a9a..5dfdaece 100644
--- a/examples/texture/Cargo.toml
+++ b/examples/texture/Cargo.toml
@@ -10,11 +10,11 @@ bindgen = { version = "0.60", default-features = false, features = ["logging", "
 
 [dependencies]
 core-graphics-types = "0.1"
-cocoa = "0.24"
+cocoa = "0.25"
 core-graphics = "0.22"
 png = "0.17"
 metal = { path = "../../" }
-winit = "0.27"
+winit = "0.29"
 
 [dependencies.objc]
 version = "0.2.4"
diff --git a/examples/texture/src/main.rs b/examples/texture/src/main.rs
index de7a4765..34839030 100644
--- a/examples/texture/src/main.rs
+++ b/examples/texture/src/main.rs
@@ -1,14 +1,15 @@
 //! Renders a textured quad to a window and adjusts the GPU buffer that contains the viewport's
 //! height and width whenever the window is resized.
 
+use std::mem;
 use std::path::PathBuf;
 
 use cocoa::{appkit::NSView, base::id as cocoa_id};
 use core_graphics_types::geometry::CGSize;
-use objc::rc::autoreleasepool;
+use objc::{rc::autoreleasepool, runtime::YES};
 use winit::dpi::LogicalSize;
 use winit::event_loop::{ControlFlow, EventLoop};
-use winit::platform::macos::WindowExtMacOS;
+use winit::raw_window_handle::{HasWindowHandle, RawWindowHandle};
 use winit::window::Window;
 
 use metal::{
@@ -31,7 +32,7 @@ const INITIAL_WINDOW_HEIGHT: u32 = 600;
 const PIXEL_FORMAT: MTLPixelFormat = MTLPixelFormat::BGRA8Unorm;
 
 fn main() {
-    let event_loop = EventLoop::new();
+    let event_loop = EventLoop::new().unwrap();
     let window = init_window(&event_loop);
 
     let device = Device::system_default().expect("No device found");
@@ -57,27 +58,40 @@ fn main() {
     let pipeline_state = prepare_pipeline_state(&device, &library);
     let command_queue = device.new_command_queue();
 
-    event_loop.run(move |event, _, control_flow| {
-        autoreleasepool(|| {
-            *control_flow = ControlFlow::Poll;
-
-            match event {
-                Event::WindowEvent { event, .. } => {
-                    handle_window_event(event, control_flow, &layer, &viewport_size_buffer)
+    event_loop
+        .run(move |event, event_loop| {
+            autoreleasepool(|| {
+                event_loop.set_control_flow(ControlFlow::Poll);
+
+                match event {
+                    Event::AboutToWait => window.request_redraw(),
+                    Event::WindowEvent { event, .. } => match event {
+                        WindowEvent::CloseRequested => event_loop.exit(),
+                        WindowEvent::Resized(size) => {
+                            layer.set_drawable_size(CGSize::new(
+                                size.width as f64,
+                                size.height as f64,
+                            ));
+                            update_viewport_size_buffer(
+                                &viewport_size_buffer,
+                                (size.width, size.height),
+                            );
+                        }
+                        WindowEvent::RedrawRequested => redraw(
+                            &layer,
+                            &pipeline_state,
+                            &command_queue,
+                            &vertex_buffer,
+                            &viewport_size_buffer,
+                            &texture_to_render,
+                        ),
+                        _ => {}
+                    },
+                    _ => {}
                 }
-                Event::MainEventsCleared => window.request_redraw(),
-                Event::RedrawRequested(_) => redraw(
-                    &layer,
-                    &pipeline_state,
-                    &command_queue,
-                    &vertex_buffer,
-                    &viewport_size_buffer,
-                    &texture_to_render,
-                ),
-                _ => {}
-            }
-        });
-    });
+            });
+        })
+        .unwrap();
 }
 
 // The `TexturedVertex` type is generated by `build.rs` by parsing `shader_types.h`
@@ -174,9 +188,11 @@ fn get_window_layer(window: &Window, device: &Device) -> MetalLayer {
     ));
 
     unsafe {
-        let view = window.ns_view() as cocoa_id;
-        view.setWantsLayer(true as _);
-        view.setLayer(std::mem::transmute(layer.as_ref()));
+        if let Ok(RawWindowHandle::AppKit(rw)) = window.window_handle().map(|wh| wh.as_raw()) {
+            let view = rw.ns_view.as_ptr() as cocoa_id;
+            view.setWantsLayer(YES);
+            view.setLayer(mem::transmute(layer.as_ref()));
+        }
     }
 
     layer
@@ -206,23 +222,6 @@ fn prepare_pipeline_state(device: &Device, library: &Library) -> RenderPipelineS
         .unwrap()
 }
 
-fn handle_window_event(
-    event: WindowEvent,
-    control_flow: &mut ControlFlow,
-    layer: &MetalLayerRef,
-    viewport_size_buffer: &Buffer,
-) {
-    match event {
-        WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
-        WindowEvent::Resized(size) => {
-            layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));
-
-            update_viewport_size_buffer(viewport_size_buffer, (size.width, size.height));
-        }
-        _ => {}
-    }
-}
-
 fn update_viewport_size_buffer(viewport_size_buffer: &Buffer, size: (u32, u32)) {
     let contents = viewport_size_buffer.contents();
     let viewport_size: [u32; 2] = [size.0, size.1];
diff --git a/examples/window/main.rs b/examples/window/main.rs
index 08936e82..0c9da3fe 100644
--- a/examples/window/main.rs
+++ b/examples/window/main.rs
@@ -13,11 +13,11 @@ use core_graphics_types::geometry::CGSize;
 use metal::*;
 use objc::{rc::autoreleasepool, runtime::YES};
 use std::mem;
-use winit::platform::macos::WindowExtMacOS;
 
 use winit::{
     event::{Event, WindowEvent},
     event_loop::ControlFlow,
+    raw_window_handle::{HasWindowHandle, RawWindowHandle},
 };
 
 #[repr(C)]
@@ -85,13 +85,13 @@ fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture:
 }
 
 fn main() {
-    let events_loop = winit::event_loop::EventLoop::new();
+    let event_loop = winit::event_loop::EventLoop::new().unwrap();
     let size = winit::dpi::LogicalSize::new(800, 600);
 
     let window = winit::window::WindowBuilder::new()
         .with_inner_size(size)
         .with_title("Metal Window Example".to_string())
-        .build(&events_loop)
+        .build(&event_loop)
         .unwrap();
 
     let device = Device::system_default().expect("no device found");
@@ -102,9 +102,11 @@ fn main() {
     layer.set_presents_with_transaction(false);
 
     unsafe {
-        let view = window.ns_view() as cocoa_id;
-        view.setWantsLayer(YES);
-        view.setLayer(mem::transmute(layer.as_ref()));
+        if let Ok(RawWindowHandle::AppKit(rw)) = window.window_handle().map(|wh| wh.as_raw()) {
+            let view = rw.ns_view.as_ptr() as cocoa_id;
+            view.setWantsLayer(YES);
+            view.setLayer(mem::transmute(layer.as_ref()));
+        }
     }
 
     let draw_size = window.inner_size();
@@ -161,101 +163,107 @@ fn main() {
         MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
     );
 
-    events_loop.run(move |event, _, control_flow| {
-        autoreleasepool(|| {
-            *control_flow = ControlFlow::Poll;
-
-            match event {
-                Event::WindowEvent { event, .. } => match event {
-                    WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
-                    WindowEvent::Resized(size) => {
-                        layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));
-                    }
-                    _ => (),
-                },
-                Event::MainEventsCleared => {
-                    window.request_redraw();
+    event_loop
+        .run(move |event, event_loop| {
+            autoreleasepool(|| {
+                event_loop.set_control_flow(ControlFlow::Poll);
+
+                match event {
+                    Event::AboutToWait => window.request_redraw(),
+                    Event::WindowEvent { event, .. } => match event {
+                        WindowEvent::CloseRequested => event_loop.exit(),
+                        WindowEvent::Resized(size) => {
+                            layer.set_drawable_size(CGSize::new(
+                                size.width as f64,
+                                size.height as f64,
+                            ));
+                        }
+                        WindowEvent::RedrawRequested => {
+                            let p = vbuf.contents();
+                            let vertex_data = [
+                                0.0f32,
+                                0.5,
+                                1.0,
+                                0.0,
+                                0.0,
+                                -0.5 + (r.cos() / 2. + 0.5),
+                                -0.5,
+                                0.0,
+                                1.0,
+                                0.0,
+                                0.5 - (r.cos() / 2. + 0.5),
+                                -0.5,
+                                0.0,
+                                0.0,
+                                1.0,
+                            ];
+
+                            unsafe {
+                                std::ptr::copy(
+                                    vertex_data.as_ptr(),
+                                    p as *mut f32,
+                                    (vertex_data.len() * mem::size_of::<f32>()) as usize,
+                                );
+                            }
+
+                            vbuf.did_modify_range(crate::NSRange::new(
+                                0 as u64,
+                                (vertex_data.len() * mem::size_of::<f32>()) as u64,
+                            ));
+
+                            let drawable = match layer.next_drawable() {
+                                Some(drawable) => drawable,
+                                None => return,
+                            };
+
+                            let render_pass_descriptor = RenderPassDescriptor::new();
+
+                            prepare_render_pass_descriptor(
+                                &render_pass_descriptor,
+                                drawable.texture(),
+                            );
+
+                            let command_buffer = command_queue.new_command_buffer();
+                            let encoder =
+                                command_buffer.new_render_command_encoder(&render_pass_descriptor);
+
+                            encoder.set_scissor_rect(MTLScissorRect {
+                                x: 20,
+                                y: 20,
+                                width: 100,
+                                height: 100,
+                            });
+                            encoder.set_render_pipeline_state(&clear_rect_pipeline_state);
+                            encoder.set_vertex_buffer(0, Some(&clear_rect_buffer), 0);
+                            encoder.draw_primitives_instanced(
+                                metal::MTLPrimitiveType::TriangleStrip,
+                                0,
+                                4,
+                                1,
+                            );
+                            let physical_size = window.inner_size();
+                            encoder.set_scissor_rect(MTLScissorRect {
+                                x: 0,
+                                y: 0,
+                                width: physical_size.width as _,
+                                height: physical_size.height as _,
+                            });
+
+                            encoder.set_render_pipeline_state(&triangle_pipeline_state);
+                            encoder.set_vertex_buffer(0, Some(&vbuf), 0);
+                            encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 3);
+                            encoder.end_encoding();
+
+                            command_buffer.present_drawable(&drawable);
+                            command_buffer.commit();
+
+                            r += 0.01f32;
+                        }
+                        _ => (),
+                    },
+                    _ => {}
                 }
-                Event::RedrawRequested(_) => {
-                    let p = vbuf.contents();
-                    let vertex_data = [
-                        0.0f32,
-                        0.5,
-                        1.0,
-                        0.0,
-                        0.0,
-                        -0.5 + (r.cos() / 2. + 0.5),
-                        -0.5,
-                        0.0,
-                        1.0,
-                        0.0,
-                        0.5 - (r.cos() / 2. + 0.5),
-                        -0.5,
-                        0.0,
-                        0.0,
-                        1.0,
-                    ];
-
-                    unsafe {
-                        std::ptr::copy(
-                            vertex_data.as_ptr(),
-                            p as *mut f32,
-                            (vertex_data.len() * mem::size_of::<f32>()) as usize,
-                        );
-                    }
-
-                    vbuf.did_modify_range(crate::NSRange::new(
-                        0 as u64,
-                        (vertex_data.len() * mem::size_of::<f32>()) as u64,
-                    ));
-
-                    let drawable = match layer.next_drawable() {
-                        Some(drawable) => drawable,
-                        None => return,
-                    };
-
-                    let render_pass_descriptor = RenderPassDescriptor::new();
-
-                    prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture());
-
-                    let command_buffer = command_queue.new_command_buffer();
-                    let encoder =
-                        command_buffer.new_render_command_encoder(&render_pass_descriptor);
-
-                    encoder.set_scissor_rect(MTLScissorRect {
-                        x: 20,
-                        y: 20,
-                        width: 100,
-                        height: 100,
-                    });
-                    encoder.set_render_pipeline_state(&clear_rect_pipeline_state);
-                    encoder.set_vertex_buffer(0, Some(&clear_rect_buffer), 0);
-                    encoder.draw_primitives_instanced(
-                        metal::MTLPrimitiveType::TriangleStrip,
-                        0,
-                        4,
-                        1,
-                    );
-                    let physical_size = window.inner_size();
-                    encoder.set_scissor_rect(MTLScissorRect {
-                        x: 0,
-                        y: 0,
-                        width: physical_size.width as _,
-                        height: physical_size.height as _,
-                    });
-
-                    encoder.set_render_pipeline_state(&triangle_pipeline_state);
-                    encoder.set_vertex_buffer(0, Some(&vbuf), 0);
-                    encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 3);
-                    encoder.end_encoding();
-
-                    command_buffer.present_drawable(&drawable);
-                    command_buffer.commit();
-
-                    r += 0.01f32;
-                }
-                _ => {}
-            }
-        });
-    });
+            });
+        })
+        .unwrap();
 }