Crate winit

source
Expand description

Winit is a cross-platform window creation and event loop management library.

§Building windows

Before you can create a Window, you first need to build an EventLoop. This is done with the EventLoop::new() function.

use winit::event_loop::EventLoop;
let event_loop = EventLoop::new().unwrap();

Then you create a Window with create_window.

§Event handling

Once a Window has been created, it will generate different events. A Window object can generate WindowEvents when certain input events occur, such as a cursor moving over the window or a key getting pressed while the window is focused. Devices can generate DeviceEvents, which contain unfiltered event data that isn’t specific to a certain window. Some user activity, like mouse movement, can generate both a WindowEvent and a DeviceEvent.

You can retrieve events by calling EventLoop::run_app(). This function will dispatch events for every Window that was created with that particular EventLoop, and will run until exit() is used, at which point exiting() is called.

Winit no longer uses a EventLoop::poll_events() -> impl Iterator<Event>-based event loop model, since that can’t be implemented properly on some platforms (e.g Web, iOS) and works poorly on most other platforms. However, this model can be re-implemented to an extent with EventLoopExtPumpEvents::pump_app_events() 1. See that method’s documentation for more reasons about why it’s discouraged beyond compatibility reasons.

use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::window::{Window, WindowId, WindowAttributes};

#[derive(Default)]
struct App {
    window: Option<Box<dyn Window>>,
}

impl ApplicationHandler for App {
    fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
        self.window = Some(event_loop.create_window(WindowAttributes::default()).unwrap());
    }

    fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, id: WindowId, event: WindowEvent) {
        match event {
            WindowEvent::CloseRequested => {
                println!("The close button was pressed; stopping");
                event_loop.exit();
            },
            WindowEvent::RedrawRequested => {
                // Redraw the application.
                //
                // It's preferable for applications that do not render continuously to render in
                // this event rather than in AboutToWait, since rendering in here allows
                // the program to gracefully handle redraws requested by the OS.

                // Draw.

                // Queue a RedrawRequested event.
                //
                // You only need to call this if you've determined that you need to redraw in
                // applications which do not always need to. Applications that redraw continuously
                // can render here instead.
                self.window.as_ref().unwrap().request_redraw();
            }
            _ => (),
        }
    }
}

let event_loop = EventLoop::new().unwrap();

// ControlFlow::Poll continuously runs the event loop, even if the OS hasn't
// dispatched any events. This is ideal for games and similar applications.
event_loop.set_control_flow(ControlFlow::Poll);

// 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);

let mut app = App::default();
event_loop.run_app(&mut app);

WindowEvent has a WindowId member. In multi-window environments, it should be compared to the value returned by Window::id() to determine which Window dispatched the event.

§Drawing on the window

Winit doesn’t directly provide any methods for drawing on a Window. However, it allows you to retrieve the raw handle of the window and display (see the platform module and/or the raw_window_handle and raw_display_handle methods), which in turn allows you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics.

Note that many platforms will display garbage data in the window’s client area if the application doesn’t render anything to the window by the time the desktop compositor is ready to display the window to the user. If you notice this happening, you should create the window with visible set to false and explicitly make the window visible only once you’re ready to render into it.

§UI scaling

UI scaling is important, go read the docs for the dpi crate for an introduction.

All of Winit’s functions return physical types, but can take either logical or physical coordinates as input, allowing you to use the most convenient coordinate system for your particular application.

Winit will dispatch a ScaleFactorChanged event whenever a window’s scale factor has changed. This can happen if the user drags their window from a standard-resolution monitor to a high-DPI monitor or if the user changes their DPI settings. This allows you to rescale your application’s UI elements and adjust how the platform changes the window’s size to reflect the new scale factor. If a window hasn’t received a ScaleFactorChanged event, its scale factor can be found by calling window.scale_factor().

§Cargo Features

Winit provides the following Cargo features:

  • x11 (enabled by default): On Unix platforms, enables the X11 backend.
  • wayland (enabled by default): On Unix platforms, enables the Wayland backend.
  • rwh_06: Implement raw-window-handle v0.6 traits.
  • serde: Enables serialization/deserialization of certain types with Serde.
  • mint: Enables mint (math interoperability standard types) conversions.

See the platform module for documentation on platform-specific cargo features.

§Platform/Architecture Support

Platform support on winit has two tiers: Tier 1 and Tier 2.

  • Tier 1 is guaranteed to work. Targets in this tier are actively tested both in CI and by maintainers.
  • Tier 2 is guaranteed to build. Code compilation is tested in CI, but deeper testing is not done.

Please open an issue if you would like to add a Tier 2 target, or if you would like a Tier 2 target moved to Tier 1.

§Tier 1 Targets

Target NameTarget TripleAPIs
32-Bit x86 Windows with MSVCi686-pc-windows-msvcWin32
64-Bit x86 Windows with MSVCx86_64-pc-windows-msvcWin32
32-Bit x86 Windows with glibci686-pc-windows-gnuWin32
64-Bit x86 Windows with glibcx86_64-pc-windows-gnuWin32
32-Bit x86 Linux with glibci686-unknown-linux-gnuX11, Wayland
64-Bit x86 Linux with glibcx86_64-unknown-linux-gnuX11, Wayland
64-Bit ARM Androidaarch64-linux-androidAndroid
64-Bit x86 Redox OSx86_64-unknown-redoxOrbital
32-Bit x86 Redox OSi686-unknown-redoxOrbital
64-Bit ARM Redox OSaarch64-unknown-redoxOrbital
64-bit x64 macOSx86_64-apple-darwinAppKit
64-bit ARM macOSaarch64-apple-darwinAppKit
32-bit Wasm Web browserwasm32-unknown-unknownwasm-bindgen

§Tier 2 Targets

Target NameTarget TripleAPIs
64-Bit ARM Windows with MSVCaarch64-pc-windows-msvcWin32
32-Bit x86 Windows 7 with MSVCi686-win7-windows-msvcWin32
64-Bit x86 Windows 7 with MSVCx86_64-win7-windows-msvcWin32
64-bit x86 Linux with Muslx86_64-unknown-linux-muslX11, Wayland
64-bit x86 Linux with 32-bit glibcx86_64-unknown-linux-gnux32X11, Wayland
64-bit x86 Androidx86_64-linux-androidAndroid
64-bit x64 iOSx86_64-apple-iosUIKit
64-bit ARM iOSaarch64-apple-iosUIKit
64-bit ARM Mac Catalystaarch64-apple-ios-macabiUIKit
32-bit x86 Androidi686-linux-androidAndroid
64-bit x86 FreeBSDx86_64-unknown-freebsdX11, Wayland
64-bit x86 NetBSDx86_64-unknown-netbsdX11
32-bit x86 Linux with Musli686-unknown-linux-muslX11, Wayland
64-bit RISC-V Linux with glibcriscv64gc-unknown-linux-gnuX11, Wayland
64-bit ARM Linux with glibcaarch64-unknown-linux-gnuX11, Wayland
64-bit ARM Linux with Muslaarch64-unknown-linux-muslX11, Wayland
64-bit PowerPC Linux with glibcpowerpc64le-unknown-linux-gnuX11, Wayland
32-Bit ARM Linux with glibcarmv5te-unknown-linux-gnueabiX11, Wayland
64-Bit Linux on IBM Supercomputerss390x-unknown-linux-gnuX11, Wayland
32-bit ARM Androidarm-linux-androideabiAndroid
64-bit SPARC Linux with glibcsparc64-unknown-linux-gnuX11, Wayland

  1. EventLoopExtPumpEvents::pump_app_events() is only available on Windows, macOS, Android, X11 and Wayland. 

Re-exports§

  • pub use rwh_06 as raw_window_handle;

Modules§