#events #winit #floem #loops #cross-platform #fork #unofficial

floem-winit

Unofficial winit fork for Floem

1 unstable release

0.29.4 Jan 12, 2024

#457 in GUI

Download history 103/week @ 2024-01-10 73/week @ 2024-01-17 62/week @ 2024-01-24 57/week @ 2024-01-31 156/week @ 2024-02-07 351/week @ 2024-02-14 485/week @ 2024-02-21 317/week @ 2024-02-28 424/week @ 2024-03-06 390/week @ 2024-03-13 377/week @ 2024-03-20 368/week @ 2024-03-27 190/week @ 2024-04-03

1,385 downloads per month
Used in 6 crates (2 directly)

Apache-2.0

2MB
42K SLoC

You are probably looking for the real winit crate.

Floem depends on winit changes that haven't been upstreamed. To make Floem publishable on crates.io, all its dependencies have to be published there - hence this unofficial crate.


lib.rs:

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

Building windows

Before you can build 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();

Once this is done, there are two ways to create a Window:

The first method is the simplest and will give you default values for everything. The second method allows you to customize the way your Window will look and behave by modifying the fields of the WindowBuilder object before you create the 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 also create and handle your own custom Event::UserEvents, if desired.

You can retrieve events by calling EventLoop::run(). 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 Event::LoopExiting.

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 [^1]. See that method's documentation for more reasons about why it's discouraged beyond compatibility reasons.

use winit::{
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::WindowBuilder,
};

let event_loop = EventLoop::new().unwrap();
let window = WindowBuilder::new().build(&event_loop).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);

event_loop.run(move |event, elwt| {
    match event {
        Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => {
            println!("The close button was pressed; stopping");
            elwt.exit();
        },
        Event::AboutToWait => {
            // Application update code.

            // 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.
            window.request_redraw();
        },
        Event::WindowEvent {
            event: 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.
        },
        _ => ()
    }
});

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.

[^1]: EventLoopExtPumpEvents::pump_events() is only available on Windows, macOS, Android, X11 and Wayland.

Dependencies

~0.3–24MB
~359K SLoC