From 0479cdf4e43c7e1aa2b600214fc189de090720ea Mon Sep 17 00:00:00 2001 From: Krishna Ayyalasomayajula Date: Sun, 31 May 2026 22:39:05 -0500 Subject: [PATCH] docs: complete application lifecycle and final validation pass --- docs/01-rainbow-triangle.md | 44 +++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/docs/01-rainbow-triangle.md b/docs/01-rainbow-triangle.md index cabca70..8da2dde 100644 --- a/docs/01-rainbow-triangle.md +++ b/docs/01-rainbow-triangle.md @@ -90,7 +90,8 @@ use pollster::block_on; use std::sync::Arc; use winit::application::ApplicationHandler; use winit::dpi::LogicalSize; -use winit::event::WindowEvent; +use winit::event::{WindowEvent, ElementState, KeyEvent}; +use winit::event::keyboard::KeyCode; use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; use winit::window::{Window, WindowId}; @@ -136,21 +137,29 @@ impl ApplicationHandler<()> for App { } } - fn window_event( - &mut self, - event_loop_ctl: &ActiveEventLoop, - _window_id: WindowId, - event: WindowEvent, - ) { - let Some(state) = self.state.as_mut() else { return }; - let Some(window) = self.window.as_ref() else { return }; - + fn window_event(&mut self, event_loop: &ActiveEventLoop, _window_id: WindowId, event: WindowEvent) { match event { - WindowEvent::Resized(size) => state.resize(size), - WindowEvent::CloseRequested { .. } => event_loop_ctl.exit(), + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + event: KeyEvent { + state: ElementState::Pressed, + logical_key: KeyCode::Escape, + .. + }, + .. + } => { + event_loop.exit(); + } + WindowEvent::Resized(physical_size) => { + if let Some(state) = &mut self.state { + state.resize(*physical_size); + } + } WindowEvent::RedrawRequested => { - state.render(); - window.request_redraw(); + if let Some(state) = &mut self.state { + state.render(); + } + self.window.as_ref().unwrap().request_redraw(); } _ => {} } @@ -177,6 +186,13 @@ impl ApplicationHandler<()> for App { > > winit supports `ControlFlow::Poll` (continuous redraw) and `ControlFlow::Wait` (idle until next event). A graphics application needs a steady render loop. `Poll` tells winit to keep firing `RedrawRequested` events. We re-queue ourselves inside the handler via `window.request_redraw()`, matching the wgpu swapchain presentation rhythm. +> **WHY: `ControlFlow` Poll vs Wait — the CPU usage tradeoff** +> +> - `ControlFlow::Poll` keeps the render loop running continuously. winit fires `RedrawRequested` as fast as possible, giving you a tight loop ideal for games and animation. The downside: it consumes 100% of one CPU core because the event loop never sleeps. +> - `ControlFlow::Wait` blocks the event loop until a new event arrives. This is dramatically more CPU-efficient since the loop sleeps between frames. However, it requires explicit `request_redraw()` calls to trigger rendering — without them, the window stays static. +> - For this tutorial, `ControlFlow::Poll` is used for simplicity: you don't need to reason about when to request redraws. A real application would almost always use `ControlFlow::Wait` with targeted `request_redraw()` calls to avoid wasting CPU cycles. +> - The `request_redraw()` call in the `RedrawRequested` handler works with both modes, but has different semantics: under `Poll` it keeps the loop going (which is already happening anyway), while under `Wait` it's the sole mechanism that wakes the event loop for the next frame. + **Why `request_redraw()`:** After presenting a frame to the display, we ask winit to schedule the next `RedrawRequested` frame. This creates an explicit render loop: render → present → request redraw → render → repeat. The rate is