winit_surface_window

Crates.iowinit_surface_window
lib.rswinit_surface_window
version0.2.0
created_at2025-08-09 13:24:36.14754+00
updated_at2025-08-23 04:21:51.118188+00
descriptionA 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
id1787930
size164,904
DJ.W (wapznw)

documentation

README

winit_surface_window

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.

Features

  • Create SurfaceWindow from Android Surface objects
  • Compatible with raw-window-handle for integration with various graphics libraries
  • Deep integration with winit event loop
  • Thread-safe implementation
  • Support for Android Presentation API for multi-display management

Core Components

Window Management

Winit Integration

  • winit_ext - Winit event loop extensions (requires winit-integration feature)

Usage

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

Complete Usage Example

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();
}

API Reference

Core Types

SurfaceWindow

The 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();

PresentationWindow

Android 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 (requires winit-integration feature)

EventLoopInitExt

EventLoop 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)?;

ActiveEventLoopPresentationExt

Extension 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()?;

Build Configuration

Android Target

# Basic build
cargo build --target aarch64-linux-android

# Enable Winit integration
cargo build --target aarch64-linux-android --features winit-integration

Important Notes

  1. Thread Safety: All Presentation-related operations must be executed on the main UI thread.
  2. Initialization Timing: Ensure Presentation initialization in Event::Resumed event, not in RedrawRequested.
  3. Resource Cleanup: Always call presentation.dismiss() when the application closes to clean up resources.
  4. Android Version: Requires Android API level 23+ support.
  5. Permission Requirements: May require SYSTEM_ALERT_WINDOW permission for secondary display.

License

This project is licensed under either of

at your option.

Commit count: 0

cargo fmt