Window handling library in pure Rust
OwnedDisplayHandle
type for allowing safe display handle usage outside of
trivial cases.ApplicationHandler<T>
trait which mimics Event<T>
.WindowBuilder::with_cursor
and Window::set_cursor
which takes a
CursorIcon
or CustomCursor
.Sync
implementation for EventLoopProxy<T: Send>
.Window::default_attributes
to get default WindowAttributes
.EventLoop::builder
to get EventLoopBuilder
without export.CustomCursor::from_rgba
to allow creating cursor images from RGBA data.CustomCursorExtWebSys::from_url
to allow loading cursor images from URLs.CustomCursorExtWebSys::from_animation
to allow creating animated
cursors from other CustomCursor
s.{Active,}EventLoop::create_custom_cursor
to load custom cursor image sources.ActiveEventLoop::create_window
and EventLoop::create_window
.CustomCursor
which could be set via Window::set_cursor
, implemented on
Windows, macOS, X11, Wayland, and Web.Event.preventDefault()
on Window
.PinchGesture
, DoubleTapGesture
, PanGesture
and RotationGesture
.UIGestureRecognizerDelegate
for fine grained control of gesture recognizers.with_title_text_color
, and with_corner_preference
on
WindowAttributesExtWindows
.AnyThread
API to access window handle off the main thread.1.65
to 1.70
.sctk-adwaita
to 0.9.0
, which changed system library
crates. This change is a cascading breaking change, you must do breaking
change as well, even if you don't expose winit.TouchpadMagnify
to PinchGesture
.SmartMagnify
to DoubleTapGesture
.TouchpadRotate
to RotationGesture
.EventLoopWindowTarget
to ActiveEventLoop
.platform::x11::XWindowType
to platform::x11::WindowType
.VideoMode
to VideoModeHandle
to represent that it doesn't hold
static data.Debug
formatting of WindowId
more concise.dpi
types to its own crate, and re-export it from the root crate.log
with tracing
, use log
feature on tracing
to restore old
behavior.EventLoop::with_user_event
now returns EventLoopBuilder
.HandleError::Unavailable
when a window handle is not available.RawWindowHandle::WebCanvas
instead of RawWindowHandle::Web
.HandleError::Unavailable
when a window handle is not available.HandleError::Unavailable
when a window handle is not available.WS_CAPTION
, WS_BORDER
, and WS_EX_WINDOWEDGE
styles
for child windows without decorations.ndk
to 0.9.0
and android-activity
to 0.6.0
,
and remove unused direct dependency on ndk-sys
.Deprecate EventLoop::run
, use EventLoop::run_app
.
Deprecate EventLoopExtRunOnDemand::run_on_demand
, use EventLoop::run_app_on_demand
.
Deprecate EventLoopExtPumpEvents::pump_events
, use EventLoopExtPumpEvents::pump_app_events
.
The new app
APIs accept a newly added ApplicationHandler<T>
instead of
Fn
. The semantics are mostly the same, given that the capture list of the
closure is your new State
. Consider the following code:
use winit::event::Event;
use winit::event_loop::EventLoop;
use winit::window::Window;
struct MyUserEvent;
let event_loop = EventLoop::<MyUserEvent>::with_user_event().build().unwrap();
let window = event_loop.create_window(Window::default_attributes()).unwrap();
let mut counter = 0;
let _ = event_loop.run(move |event, event_loop| {
match event {
Event::AboutToWait => {
window.request_redraw();
counter += 1;
}
Event::WindowEvent { window_id, event } => {
// Handle window event.
}
Event::UserEvent(event) => {
// Handle user event.
}
Event::DeviceEvent { device_id, event } => {
// Handle device event.
}
_ => (),
}
});
To migrate this code, you should move all the captured values into some
newtype State
and implement ApplicationHandler
for this type. Finally,
we move particular match event
arms into methods on ApplicationHandler
,
for example:
use winit::application::ApplicationHandler;
use winit::event::{Event, WindowEvent, DeviceEvent, DeviceId};
use winit::event_loop::{EventLoop, ActiveEventLoop};
use winit::window::{Window, WindowId};
struct MyUserEvent;
struct State {
window: Window,
counter: i32,
}
impl ApplicationHandler<MyUserEvent> for State {
fn user_event(&mut self, event_loop: &ActiveEventLoop, user_event: MyUserEvent) {
// Handle user event.
}
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
// Your application got resumed.
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) {
// Handle window event.
}
fn device_event(&mut self, event_loop: &ActiveEventLoop, device_id: DeviceId, event: DeviceEvent) {
// Handle device event.
}
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
self.window.request_redraw();
self.counter += 1;
}
}
let event_loop = EventLoop::<MyUserEvent>::with_user_event().build().unwrap();
#[allow(deprecated)]
let window = event_loop.create_window(Window::default_attributes()).unwrap();
let mut state = State { window, counter: 0 };
let _ = event_loop.run_app(&mut state);
Please submit your feedback after migrating in this issue.
Deprecate Window::set_cursor_icon
, use Window::set_cursor
.
Remove Window::new
, use ActiveEventLoop::create_window
instead.
You now have to create your windows inside the actively running event loop
(usually the new_events(cause: StartCause::Init)
or resumed()
events),
and can no longer do it before the application has properly launched.
This change is done to fix many long-standing issues on iOS and macOS, and
will improve things on Wayland once fully implemented.
To ease migration, we provide the deprecated EventLoop::create_window
that
will allow you to bypass this restriction in this release.
Using the migration example from above, you can change your code as follows:
use winit::application::ApplicationHandler;
use winit::event::{Event, WindowEvent, DeviceEvent, DeviceId};
use winit::event_loop::{EventLoop, ActiveEventLoop};
use winit::window::{Window, WindowId};
#[derive(Default)]
struct State {
// Use an `Option` to allow the window to not be available until the
// application is properly running.
window: Option<Window>,
counter: i32,
}
impl ApplicationHandler for State {
// This is a common indicator that you can create a window.
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) {
// `unwrap` is fine, the window will always be available when
// receiving a window event.
let window = self.window.as_ref().unwrap();
// Handle window event.
}
fn device_event(&mut self, event_loop: &ActiveEventLoop, device_id: DeviceId, event: DeviceEvent) {
// Handle window event.
}
fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
if let Some(window) = self.window.as_ref() {
window.request_redraw();
self.counter += 1;
}
}
}
let event_loop = EventLoop::new().unwrap();
let mut state = State::default();
let _ = event_loop.run_app(&mut state);
Remove Deref
implementation for EventLoop
that gave EventLoopWindowTarget
.
Remove WindowBuilder
in favor of WindowAttributes
.
Remove Generic parameter T
from ActiveEventLoop
.
Remove EventLoopBuilder::with_user_event
, use EventLoop::with_user_event
.
Remove Redundant EventLoopError::AlreadyRunning
.
Remove WindowAttributes::fullscreen
and expose as field directly.
On X11, remove platform::x11::XNotSupported
export.
text
and text_with_all_modifiers
not being None
during compose.ControlFlow::Wait
and ControlFlow::WaitUntil
.Occluded
event handling._XSETTINGS_SETTINGS
update.Focused(false)
being send when other seats still have window focused.Window::set_{min,max}_inner_size
not always applied.WAYLAND_SOCKET
not used when detecting platform.logical_key
and text
not reported in KeyEvent
.KeyEventExtModifierSupplement
.NamedKey
when possible.set_cursor_grab
.set_cursor_visible
.drag_window
.drag_resize_window
.set_transparent
.set_visible
.is_visible
.set_resizable
.is_resizable
.set_maximized
.is_maximized
.set_decorations
.is_decorated
.set_window_level
.DeviceEvent::MouseMotion
.AboutToWait
.NotSupported
error not propagated when creating event loop.ArrowLeft
.ModifiersChanged
not sent from xdotool-like inputWindow::request_inner_size
being overwritten by resize.Window::inner_size
not using the correct rounding.Xft.dpi
reload during runtime.