winit-core/ime: add more purposes and content hints

Also move IME example into `ime.rs` thus making IME integrations more
easily comprehendible.

Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
DorotaC 2025-09-06 06:27:55 +02:00 committed by GitHub
parent 014fb68a26
commit 6de5041a94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 554 additions and 182 deletions

1
examples Symbolic link
View file

@ -0,0 +1 @@
winit/examples

File diff suppressed because it is too large Load diff

View file

@ -1,129 +0,0 @@
#[cfg(any(x11_platform, macos_platform, windows_platform))]
#[allow(deprecated)]
fn main() -> Result<(), impl std::error::Error> {
use std::collections::HashMap;
use winit::application::ApplicationHandler;
use winit::dpi::{LogicalPosition, LogicalSize, Position};
use winit::event::{ElementState, KeyEvent, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::raw_window_handle::HasRawWindowHandle;
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[derive(Debug)]
struct WindowData {
window: Box<dyn Window>,
color: u32,
}
impl WindowData {
fn new(window: Box<dyn Window>, color: u32) -> Self {
Self { window, color }
}
}
#[derive(Default, Debug)]
struct Application {
parent_window_id: Option<WindowId>,
windows: HashMap<WindowId, WindowData>,
}
impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let attributes = WindowAttributes::default()
.with_title("parent window")
.with_position(Position::Logical(LogicalPosition::new(0.0, 0.0)))
.with_surface_size(LogicalSize::new(640.0f32, 480.0f32));
let window = event_loop.create_window(attributes).unwrap();
println!("Parent window id: {:?})", window.id());
self.parent_window_id = Some(window.id());
self.windows.insert(window.id(), WindowData::new(window, 0xffbbbbbb));
}
fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
window_id: winit::window::WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::CloseRequested => {
self.windows.clear();
event_loop.exit();
},
WindowEvent::PointerEntered { device_id: _, .. } => {
// On x11, println when the cursor entered in a window even if the child window
// is created by some key inputs.
// the child windows are always placed at (0, 0) with size (200, 200) in the
// parent window, so we also can see this log when we move
// the cursor around (200, 200) in parent window.
println!("cursor entered in the window {window_id:?}");
},
WindowEvent::KeyboardInput {
event: KeyEvent { state: ElementState::Pressed, .. },
..
} => {
let child_index = self.windows.len() - 1;
let child_color =
0xff000000 + 3_u32.pow((child_index + 2).rem_euclid(16) as u32);
let parent_window = self.windows.get(&self.parent_window_id.unwrap()).unwrap();
let child_window =
spawn_child_window(parent_window.window.as_ref(), event_loop, child_index);
let child_id = child_window.id();
println!("Child window created with id: {child_id:?}");
self.windows.insert(child_id, WindowData::new(child_window, child_color));
},
WindowEvent::RedrawRequested => {
if let Some(window) = self.windows.get(&window_id) {
if window_id == self.parent_window_id.unwrap() {
fill::fill_window(window.window.as_ref());
} else {
fill::fill_window_with_color(window.window.as_ref(), window.color);
}
}
},
_ => (),
}
}
}
fn spawn_child_window(
parent: &dyn Window,
event_loop: &dyn ActiveEventLoop,
child_count: usize,
) -> Box<dyn Window> {
let parent = parent.raw_window_handle().unwrap();
// As child count increases, x goes from 0*128 to 5*128 and then repeats
let x: f64 = child_count.rem_euclid(5) as f64 * 128.0;
// After 5 windows have been put side by side horizontally, a new row starts
let y: f64 = (child_count / 5) as f64 * 96.0;
let mut window_attributes = WindowAttributes::default()
.with_title("child window")
.with_surface_size(LogicalSize::new(128.0f32, 96.0))
.with_position(Position::Logical(LogicalPosition::new(x, y)))
.with_visible(true);
// `with_parent_window` is unsafe. Parent window must be a valid window.
window_attributes = unsafe { window_attributes.with_parent_window(Some(parent)) };
event_loop.create_window(window_attributes).unwrap()
}
let event_loop = EventLoop::new().unwrap();
event_loop.run_app(Application::default())
}
#[cfg(not(any(x11_platform, macos_platform, windows_platform)))]
fn main() {
panic!(
"This example is supported only on x11, macOS, and Windows, with the `rwh_06` feature \
enabled."
);
}

View file

@ -1,146 +0,0 @@
#![allow(clippy::single_match)]
use std::thread;
#[cfg(not(web_platform))]
use std::time;
use ::tracing::{info, warn};
#[cfg(web_platform)]
use web_time as time;
use winit::application::ApplicationHandler;
use winit::event::{ElementState, KeyEvent, StartCause, WindowEvent};
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::keyboard::{Key, NamedKey};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[path = "util/tracing.rs"]
mod tracing;
const WAIT_TIME: time::Duration = time::Duration::from_millis(100);
const POLL_SLEEP_TIME: time::Duration = time::Duration::from_millis(100);
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
enum Mode {
#[default]
Wait,
WaitUntil,
Poll,
}
fn main() -> Result<(), impl std::error::Error> {
#[cfg(web_platform)]
console_error_panic_hook::set_once();
tracing::init();
info!("Press '1' to switch to Wait mode.");
info!("Press '2' to switch to WaitUntil mode.");
info!("Press '3' to switch to Poll mode.");
info!("Press 'R' to toggle request_redraw() calls.");
info!("Press 'Esc' to close the window.");
let event_loop = EventLoop::new().unwrap();
event_loop.run_app(ControlFlowDemo::default())
}
#[derive(Default, Debug)]
struct ControlFlowDemo {
mode: Mode,
request_redraw: bool,
wait_cancelled: bool,
close_requested: bool,
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for ControlFlowDemo {
fn new_events(&mut self, _event_loop: &dyn ActiveEventLoop, cause: StartCause) {
info!("new_events: {cause:?}");
self.wait_cancelled = match cause {
StartCause::WaitCancelled { .. } => self.mode == Mode::WaitUntil,
_ => false,
}
}
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = WindowAttributes::default().with_title(
"Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.",
);
self.window = Some(event_loop.create_window(window_attributes).unwrap());
}
fn window_event(
&mut self,
_event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
info!("{event:?}");
match event {
WindowEvent::CloseRequested => {
self.close_requested = true;
},
WindowEvent::KeyboardInput {
event: KeyEvent { logical_key: key, state: ElementState::Pressed, .. },
..
} => match key.as_ref() {
// WARNING: Consider using `key_without_modifiers()` if available on your platform.
// See the `key_binding` example
Key::Character("1") => {
self.mode = Mode::Wait;
warn!("mode: {:?}", self.mode);
},
Key::Character("2") => {
self.mode = Mode::WaitUntil;
warn!("mode: {:?}", self.mode);
},
Key::Character("3") => {
self.mode = Mode::Poll;
warn!("mode: {:?}", self.mode);
},
Key::Character("r") => {
self.request_redraw = !self.request_redraw;
warn!("request_redraw: {}", self.request_redraw);
},
Key::Named(NamedKey::Escape) => {
self.close_requested = true;
},
_ => (),
},
WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap();
window.pre_present_notify();
fill::fill_window(window.as_ref());
},
_ => (),
}
}
fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) {
if self.request_redraw && !self.wait_cancelled && !self.close_requested {
self.window.as_ref().unwrap().request_redraw();
}
match self.mode {
Mode::Wait => event_loop.set_control_flow(ControlFlow::Wait),
Mode::WaitUntil => {
if !self.wait_cancelled {
event_loop
.set_control_flow(ControlFlow::WaitUntil(time::Instant::now() + WAIT_TIME));
}
},
Mode::Poll => {
thread::sleep(POLL_SLEEP_TIME);
event_loop.set_control_flow(ControlFlow::Poll);
},
};
if self.close_requested {
event_loop.exit();
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -1,65 +0,0 @@
use std::error::Error;
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[path = "util/tracing.rs"]
mod tracing;
fn main() -> Result<(), Box<dyn Error>> {
tracing::init();
let event_loop = EventLoop::new()?;
let app = Application::new();
Ok(event_loop.run_app(app)?)
}
/// Application state and event handling.
#[derive(Debug)]
struct Application {
window: Option<Box<dyn Window>>,
}
impl Application {
fn new() -> Self {
Self { window: None }
}
}
impl ApplicationHandler for Application {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes =
WindowAttributes::default().with_title("Drag and drop files on me!");
self.window = Some(event_loop.create_window(window_attributes).unwrap());
}
fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
match event {
WindowEvent::DragLeft { .. }
| WindowEvent::DragEntered { .. }
| WindowEvent::DragMoved { .. }
| WindowEvent::DragDropped { .. } => {
println!("{event:?}");
},
WindowEvent::RedrawRequested => {
let window = self.window.as_ref().unwrap();
window.pre_present_notify();
fill::fill_window(window.as_ref());
},
WindowEvent::CloseRequested => {
event_loop.exit();
},
_ => {},
}
}
}

View file

@ -1,80 +0,0 @@
#![allow(clippy::single_match)]
// Limit this example to only compatible platforms.
#[cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform, android_platform,))]
fn main() -> std::process::ExitCode {
use std::process::ExitCode;
use std::thread::sleep;
use std::time::Duration;
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::pump_events::{EventLoopExtPumpEvents, PumpStatus};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[derive(Default, Debug)]
struct PumpDemo {
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for PumpDemo {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = WindowAttributes::default().with_title("A fantastic window!");
self.window = Some(event_loop.create_window(window_attributes).unwrap());
}
fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
println!("{event:?}");
let window = match self.window.as_ref() {
Some(window) => window,
None => return,
};
match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
fill::fill_window(window.as_ref());
window.request_redraw();
},
_ => (),
}
}
}
let mut event_loop = EventLoop::new().unwrap();
tracing_subscriber::fmt::init();
let mut app = PumpDemo::default();
loop {
let timeout = Some(Duration::ZERO);
let status = event_loop.pump_app_events(timeout, &mut app);
if let PumpStatus::Exit(exit_code) = status {
break ExitCode::from(exit_code as u8);
}
// Sleep for 1/60 second to simulate application work
//
// Since `pump_events` doesn't block it will be important to
// throttle the loop in the app somehow.
println!("Update()");
sleep(Duration::from_millis(16));
}
}
#[cfg(any(ios_platform, web_platform, orbital_platform))]
fn main() {
println!("This platform doesn't support pump_events.");
}

View file

@ -1,99 +0,0 @@
#![allow(clippy::single_match)]
// Limit this example to only compatible platforms.
#[cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform,))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
use std::time::Duration;
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::run_on_demand::EventLoopExtRunOnDemand;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[derive(Default, Debug)]
struct App {
idx: usize,
window_id: Option<WindowId>,
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for App {
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
if let Some(window) = self.window.as_ref() {
window.request_redraw();
}
}
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let window_attributes = WindowAttributes::default()
.with_title("Fantastic window number one!")
.with_surface_size(winit::dpi::LogicalSize::new(128.0, 128.0));
let window = event_loop.create_window(window_attributes).unwrap();
self.window_id = Some(window.id());
self.window = Some(window);
}
fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
if event == WindowEvent::Destroyed && self.window_id == Some(window_id) {
println!(
"--------------------------------------------------------- Window {} Destroyed",
self.idx
);
self.window_id = None;
event_loop.exit();
return;
}
let window = match self.window.as_mut() {
Some(window) => window,
None => return,
};
match event {
WindowEvent::CloseRequested => {
println!(
"--------------------------------------------------------- Window {} \
CloseRequested",
self.idx
);
fill::cleanup_window(window.as_ref());
self.window = None;
},
WindowEvent::RedrawRequested => {
fill::fill_window(window.as_ref());
},
_ => (),
}
}
}
tracing_subscriber::fmt::init();
let mut event_loop = EventLoop::new().unwrap();
let mut app = App { idx: 1, ..Default::default() };
event_loop.run_app_on_demand(&mut app)?;
println!("--------------------------------------------------------- Finished first loop");
println!("--------------------------------------------------------- Waiting 5 seconds");
std::thread::sleep(Duration::from_secs(5));
app.idx += 1;
event_loop.run_app_on_demand(&mut app)?;
println!("--------------------------------------------------------- Finished second loop");
Ok(())
}
#[cfg(not(any(windows_platform, macos_platform, x11_platform, wayland_platform,)))]
fn main() {
println!("This example is not supported on this platform");
}

View file

@ -1,156 +0,0 @@
//! Fill the window buffer with a solid color.
//!
//! Launching a window without drawing to it has unpredictable results varying from platform to
//! platform. In order to have well-defined examples, this module provides an easy way to
//! fill the window buffer with a solid color.
//!
//! The `softbuffer` crate is used, largely because of its ease of use. `glutin` or `wgpu` could
//! also be used to fill the window buffer, but they are more complicated to use.
#[allow(unused_imports)]
pub use platform::cleanup_window;
#[allow(unused_imports)]
pub use platform::fill_window;
#[allow(unused_imports)]
pub use platform::fill_window_with_animated_color;
#[allow(unused_imports)]
pub use platform::fill_window_with_color;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
mod platform {
use std::cell::RefCell;
use std::collections::HashMap;
use std::mem;
use std::mem::ManuallyDrop;
use std::num::NonZeroU32;
#[cfg(all(not(android_platform), not(web_platform)))]
use std::time::Instant;
use softbuffer::{Context, Surface};
#[cfg(all(web_platform, not(android_platform)))]
use web_time::Instant;
use winit::window::{Window, WindowId};
thread_local! {
// NOTE: You should never do things like that, create context and drop it before
// you drop the event loop. We do this for brevity to not blow up examples. We use
// ManuallyDrop to prevent destructors from running.
//
// A static, thread-local map of graphics contexts to open windows.
static GC: ManuallyDrop<RefCell<Option<GraphicsContext>>> = const { ManuallyDrop::new(RefCell::new(None)) };
}
/// The graphics context used to draw to a window.
struct GraphicsContext {
/// The global softbuffer context.
context: RefCell<Context<&'static dyn Window>>,
/// The hash map of window IDs to surfaces.
surfaces: HashMap<WindowId, Surface<&'static dyn Window, &'static dyn Window>>,
}
impl GraphicsContext {
fn new(w: &dyn Window) -> Self {
Self {
context: RefCell::new(
Context::new(unsafe {
mem::transmute::<&'_ dyn Window, &'static dyn Window>(w)
})
.expect("Failed to create a softbuffer context"),
),
surfaces: HashMap::new(),
}
}
fn create_surface(
&mut self,
window: &dyn Window,
) -> &mut Surface<&'static dyn Window, &'static dyn Window> {
self.surfaces.entry(window.id()).or_insert_with(|| {
Surface::new(&self.context.borrow(), unsafe {
mem::transmute::<&'_ dyn Window, &'static dyn Window>(window)
})
.expect("Failed to create a softbuffer surface")
})
}
fn destroy_surface(&mut self, window: &dyn Window) {
self.surfaces.remove(&window.id());
}
}
pub fn fill_window_with_color(window: &dyn Window, color: u32) {
GC.with(|gc| {
let size = window.surface_size();
let (Some(width), Some(height)) =
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
else {
return;
};
// Either get the last context used or create a new one.
let mut gc = gc.borrow_mut();
let surface =
gc.get_or_insert_with(|| GraphicsContext::new(window)).create_surface(window);
// Fill a buffer with a solid color
surface.resize(width, height).expect("Failed to resize the softbuffer surface");
let mut buffer = surface.buffer_mut().expect("Failed to get the softbuffer buffer");
buffer.fill(color);
buffer.present().expect("Failed to present the softbuffer buffer");
})
}
#[allow(dead_code)]
pub fn fill_window(window: &dyn Window) {
fill_window_with_color(window, 0xff181818);
}
#[allow(dead_code)]
pub fn fill_window_with_animated_color(window: &dyn Window, start: Instant) {
let time = start.elapsed().as_secs_f32() * 1.5;
let blue = (time.sin() * 255.0) as u32;
let green = ((time.cos() * 255.0) as u32) << 8;
let red = ((1.0 - time.sin() * 255.0) as u32) << 16;
let color = red | green | blue;
fill_window_with_color(window, color);
}
#[allow(dead_code)]
pub fn cleanup_window(window: &dyn Window) {
GC.with(|gc| {
let mut gc = gc.borrow_mut();
if let Some(context) = gc.as_mut() {
context.destroy_surface(window);
}
});
}
}
#[cfg(any(target_os = "android", target_os = "ios"))]
mod platform {
#[allow(dead_code)]
pub fn fill_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms.
}
#[allow(dead_code)]
pub fn fill_window_with_color(_window: &dyn winit::window::Window, _color: u32) {
// No-op on mobile platforms.
}
#[allow(dead_code)]
pub fn fill_window_with_animated_color(
_window: &dyn winit::window::Window,
_start: std::time::Instant,
) {
// No-op on mobile platforms.
}
#[allow(dead_code)]
pub fn cleanup_window(_window: &dyn winit::window::Window) {
// No-op on mobile platforms.
}
}

View file

@ -1,25 +0,0 @@
#[cfg(not(web_platform))]
pub fn init() {
use tracing_subscriber::filter::{EnvFilter, LevelFilter};
tracing_subscriber::fmt()
.with_env_filter(
EnvFilter::builder().with_default_directive(LevelFilter::INFO.into()).from_env_lossy(),
)
.init();
}
#[cfg(web_platform)]
pub fn init() {
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
tracing_subscriber::registry()
.with(
tracing_subscriber::fmt::layer()
.with_ansi(false)
.without_time()
.with_writer(tracing_web::MakeWebConsoleWriter::new()),
)
.init();
}

View file

@ -1,84 +0,0 @@
//! Simple winit window example.
use std::error::Error;
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
#[cfg(web_platform)]
use winit::platform::web::WindowAttributesWeb;
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[path = "util/tracing.rs"]
mod tracing;
#[derive(Default, Debug)]
struct App {
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for App {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
#[cfg(not(web_platform))]
let window_attributes = WindowAttributes::default();
#[cfg(web_platform)]
let window_attributes = WindowAttributes::default()
.with_platform_attributes(Box::new(WindowAttributesWeb::default().with_append(true)));
self.window = match event_loop.create_window(window_attributes) {
Ok(window) => Some(window),
Err(err) => {
eprintln!("error creating window: {err}");
event_loop.exit();
return;
},
}
}
fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, _: WindowId, event: WindowEvent) {
println!("{event:?}");
match event {
WindowEvent::CloseRequested => {
println!("Close was requested; stopping");
event_loop.exit();
},
WindowEvent::SurfaceResized(_) => {
self.window.as_ref().expect("resize event without a window").request_redraw();
},
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.
let window = self.window.as_ref().expect("redraw request without a window");
// Notify that you're about to draw.
window.pre_present_notify();
// Draw.
fill::fill_window(window.as_ref());
// For contiguous redraw loop you can request a redraw from here.
// window.request_redraw();
},
_ => (),
}
}
}
fn main() -> Result<(), Box<dyn Error>> {
#[cfg(web_platform)]
console_error_panic_hook::set_once();
tracing::init();
let event_loop = EventLoop::new()?;
// For alternative loop run options see `pump_events` and `run_on_demand` examples.
event_loop.run_app(App::default())?;
Ok(())
}

View file

@ -1,71 +0,0 @@
//! A demonstration of embedding a winit window in an existing X11 application.
use std::error::Error;
#[cfg(x11_platform)]
fn main() -> Result<(), Box<dyn Error>> {
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::platform::x11::WindowAttributesX11;
use winit::window::{Window, WindowAttributes, WindowId};
#[path = "util/fill.rs"]
mod fill;
#[derive(Debug)]
pub struct XEmbedDemo {
parent_window_id: u32,
window: Option<Box<dyn Window>>,
}
impl ApplicationHandler for XEmbedDemo {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let mut window_attributes = WindowAttributes::default()
.with_title("An embedded window!")
.with_surface_size(winit::dpi::LogicalSize::new(128.0, 128.0));
let x11_attrs =
WindowAttributesX11::default().with_embed_parent_window(self.parent_window_id);
window_attributes = window_attributes.with_platform_attributes(Box::new(x11_attrs));
self.window = Some(event_loop.create_window(window_attributes).unwrap());
}
fn window_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
_window_id: WindowId,
event: WindowEvent,
) {
let window = self.window.as_ref().unwrap();
match event {
WindowEvent::CloseRequested => event_loop.exit(),
WindowEvent::RedrawRequested => {
window.pre_present_notify();
fill::fill_window(window.as_ref());
},
_ => (),
}
}
fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) {
self.window.as_ref().unwrap().request_redraw();
}
}
// First argument should be a 32-bit X11 window ID.
let parent_window_id = std::env::args()
.nth(1)
.ok_or("Expected a 32-bit X11 window ID as the first argument.")?
.parse::<u32>()?;
tracing_subscriber::fmt::init();
let event_loop = EventLoop::new()?;
Ok(event_loop.run_app(XEmbedDemo { parent_window_id, window: None })?)
}
#[cfg(not(x11_platform))]
fn main() -> Result<(), Box<dyn Error>> {
println!("This example is only supported on X11 platforms.");
Ok(())
}