| Crates.io | winit_surface_window |
| lib.rs | winit_surface_window |
| version | 0.2.0 |
| created_at | 2025-08-09 13:24:36.14754+00 |
| updated_at | 2025-08-23 04:21:51.118188+00 |
| description | A helper library to use existing Android Surfaces (like Presentations) as windows within the Rust ecosystem, compatible with raw-window-handle. |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1787930 |
| size | 164,904 |
A helper library for using existing Android Surfaces (like Presentations) as windows within the Rust ecosystem, compatible with raw-window-handle.
This library allows you to create a window from an existing Android Surface object, which is particularly useful when working with Android Presentation APIs or other scenarios where you need to render to a secondary display or a specific surface.
SurfaceWindow from Android Surface objectsraw-window-handle for integration with various graphics librariesSurfaceWindow - Core window abstraction, created from Android SurfacePresentationWindow - Android Presentation window managementwinit_ext - Winit event loop extensions (requires winit-integration feature)Add this to your Cargo.toml:
[dependencies]
winit_surface_window = { path = "path/to/winit_surface_window" }
# Enable feature support
[features]
winit-integration = ["winit_surface_window/winit-integration"] # Winit integration support
Here's a complete example using winit event loop:
use android_activity::AndroidApp;
use winit::event_loop::{EventLoop, EventLoopBuilder};
use winit::platform::android::EventLoopBuilderExtAndroid;
use winit::window::WindowAttributes;
use winit_surface_window::{
ActiveEventLoopPresentationExt, EventLoopInitExt, PresentationWindow
};
#[no_mangle]
fn android_main(app: AndroidApp) {
android_logger::init_once(
android_logger::Config::default().with_max_level(log::LevelFilter::Debug),
);
let event_loop: EventLoop<()> = EventLoopBuilder::new()
.with_android_app(app.clone())
.build()
.unwrap();
let mut window = None;
let mut presentation_window: Option<PresentationWindow> = None;
let mut presentation_initialized = false;
event_loop.run(move |event, event_loop| match event {
winit::event::Event::WindowEvent { event, .. } => match event {
winit::event::WindowEvent::CloseRequested => {
// Clean up Presentation resources
if let Some(mut presentation) = presentation_window.take() {
let _ = presentation.dismiss();
}
presentation_window = None;
presentation_initialized = false;
event_loop.exit();
}
winit::event::WindowEvent::RedrawRequested => {
// Perform rendering operations
if let Some(presentation) = &presentation_window {
if let Some(surface_window) = presentation.surface_window() {
// Add your rendering code here
println!("Rendering to surface: {}x{}",
surface_window.width(), surface_window.height());
}
}
}
_ => (),
},
winit::event::Event::Resumed => {
// Create main window
let win = event_loop
.create_window(WindowAttributes::default())
.unwrap();
window = Some(win);
// Initialize Presentation in Resumed event
if !presentation_initialized {
// Add delay to ensure Activity is fully ready
std::thread::sleep(std::time::Duration::from_millis(500));
// Initialize Presentation system
match event_loop.init_presentation_android_app(&app) {
Ok(_) => {
println!("Presentation system initialized successfully");
// List available displays
if let Ok(displays) = event_loop.get_available_displays() {
println!("Available displays: {:?}", displays);
}
// Create Presentation
match event_loop.create_presentation_on_secondary_display(10000) {
Ok(presentation) => {
println!("Presentation created successfully!");
// Get SurfaceWindow for rendering
if let Some(surface_window) = presentation.surface_window() {
println!("SurfaceWindow available: {}x{}",
surface_window.width(), surface_window.height());
}
presentation_window = Some(presentation);
}
Err(err) => {
println!("Failed to create presentation: {}", err);
}
}
presentation_initialized = true;
}
Err(err) => {
println!("Failed to initialize presentation system: {}", err);
}
}
}
}
winit::event::Event::AboutToWait => {
std::thread::sleep(std::time::Duration::from_millis(16));
if let Some(window) = &window {
window.request_redraw();
}
}
_ => (),
}).unwrap();
}
SurfaceWindowThe main struct representing an Android Surface as a window. Implements HasRawWindowHandle and HasRawDisplayHandle for compatibility with various graphics libraries.
// Create window from Android Surface
let surface_window = unsafe { SurfaceWindow::from_surface(&mut env, surface)? };
// Get window dimensions
let width = surface_window.width();
let height = surface_window.height();
PresentationWindowAndroid Presentation window manager for creating windows on secondary displays or specific displays.
// Create Presentation on secondary display
let presentation = PresentationWindow::new_on_secondary_display(5000)?;
// Create Presentation on specific display
let presentation = PresentationWindow::new_on_display(1, 5000)?;
// Get available display list
let displays = PresentationWindow::get_available_displays()?;
// Get underlying SurfaceWindow
if let Some(surface_window) = presentation.surface_window() {
// Perform rendering operations
}
winit-integration feature)EventLoopInitExtEventLoop extension for initializing the Presentation system.
// Initialize using AndroidApp
event_loop.init_presentation_android_app(&app)?;
// Initialize using NativeActivity
event_loop.init_presentation_system_ndk(&activity)?;
ActiveEventLoopPresentationExtExtension for creating Presentations within event handlers.
// Create Presentation on secondary display
let presentation = event_loop.create_presentation_on_secondary_display(5000)?;
// Create Presentation on specific display
let presentation = event_loop.create_presentation_on_display(1, 5000)?;
// Get available displays
let displays = event_loop.get_available_displays()?;
# Basic build
cargo build --target aarch64-linux-android
# Enable Winit integration
cargo build --target aarch64-linux-android --features winit-integration
Event::Resumed event, not in RedrawRequested.presentation.dismiss() when the application closes to clean up resources.SYSTEM_ALERT_WINDOW permission for secondary display.This project is licensed under either of
at your option.