mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-10 04:58:34 +00:00
Provides a workaround for missing monitor initialization in platform backends like imgui-winit-support. Without proper monitor initialization, Dear ImGui throws "Platform init didn't setup Monitors list?" assertion. - Add monitor_init_fix module with initialization utilities - Support single and multi-monitor configurations - Add unit tests and examples - Document workaround usage Co-Authored-By: Elias Stepanik <eliasstepanik@proton.me>
179 lines
5.7 KiB
Markdown
179 lines
5.7 KiB
Markdown
# Monitor Initialization Fix Summary
|
|
|
|
## Issue Identified
|
|
|
|
When viewport support is enabled in imgui-rs, Dear ImGui throws an assertion error:
|
|
```
|
|
"Platform init didn't setup Monitors list?"
|
|
```
|
|
|
|
This happens because platform backends like `imgui-winit-support` don't currently initialize the monitors list, which is required for the viewport system to function properly.
|
|
|
|
## Root Cause
|
|
|
|
1. **Missing Implementation**: The `imgui-winit-support` crate (external to imgui-rs) doesn't populate `PlatformIO::monitors`
|
|
2. **Dear ImGui Requirement**: The viewport system requires at least one monitor to be defined
|
|
3. **Timing Critical**: Monitors must be initialized BEFORE any viewport operations
|
|
|
|
## Solution Implemented
|
|
|
|
Since `imgui-winit-support` is an external crate, we've created a workaround module `monitor_init_fix` that allows users to manually initialize monitors.
|
|
|
|
### Usage
|
|
|
|
```rust
|
|
use imgui::*;
|
|
|
|
// Create and configure context
|
|
let mut ctx = Context::create();
|
|
ctx.io_mut().config_flags |= ConfigFlags::VIEWPORTS_ENABLE;
|
|
|
|
// Apply viewport fix (from previous issue)
|
|
viewport_issue_fix::apply_viewport_fix(&mut ctx);
|
|
|
|
// Initialize monitors BEFORE first new_frame()
|
|
monitor_init_fix::init_single_monitor(&mut ctx, 1920.0, 1080.0, 1.0);
|
|
|
|
// Or for multiple monitors:
|
|
monitor_init_fix::init_monitors(&mut ctx, &[
|
|
monitor_init_fix::MonitorData {
|
|
position: [0.0, 0.0],
|
|
size: [1920.0, 1080.0],
|
|
work_pos: [0.0, 0.0],
|
|
work_size: [1920.0, 1040.0], // Excluding taskbar
|
|
dpi_scale: 1.0,
|
|
},
|
|
monitor_init_fix::MonitorData {
|
|
position: [1920.0, 0.0],
|
|
size: [1920.0, 1080.0],
|
|
work_pos: [1920.0, 0.0],
|
|
work_size: [1920.0, 1080.0],
|
|
dpi_scale: 1.0,
|
|
},
|
|
]);
|
|
```
|
|
|
|
## Implementation Details
|
|
|
|
### Module Structure
|
|
- `monitor_init_fix.rs` - Main implementation
|
|
- Uses `PlatformIO::monitors` ImVector
|
|
- Provides convenience functions for common cases
|
|
|
|
### Key Functions
|
|
1. `init_monitors()` - Initialize with custom monitor data
|
|
2. `init_single_monitor()` - Quick single monitor setup
|
|
3. `clear_monitors()` - Clear all monitors
|
|
4. `monitors_initialized()` - Check if monitors are set
|
|
5. `monitor_count()` - Get number of monitors
|
|
|
|
### Integration with Winit
|
|
|
|
If you're using winit, you can enumerate real monitors:
|
|
|
|
```rust
|
|
use winit::event_loop::EventLoop;
|
|
use winit::dpi::{PhysicalPosition, PhysicalSize};
|
|
|
|
let event_loop = EventLoop::new();
|
|
let monitors: Vec<monitor_init_fix::MonitorData> = event_loop
|
|
.available_monitors()
|
|
.map(|monitor| {
|
|
let PhysicalPosition { x, y } = monitor.position();
|
|
let PhysicalSize { width, height } = monitor.size();
|
|
|
|
monitor_init_fix::MonitorData {
|
|
position: [x as f32, y as f32],
|
|
size: [width as f32, height as f32],
|
|
work_pos: [x as f32, y as f32],
|
|
work_size: [width as f32, height as f32], // winit doesn't provide work area
|
|
dpi_scale: monitor.scale_factor() as f32,
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
monitor_init_fix::init_monitors(&mut ctx, &monitors);
|
|
```
|
|
|
|
## Files Added/Modified
|
|
|
|
### New Files
|
|
- `imgui/src/monitor_init_fix.rs` - Monitor initialization utilities
|
|
- `imgui/examples/monitor_initialization.rs` - Usage example
|
|
- `imgui/tests/monitor_init_test.rs` - Unit tests
|
|
- `imgui/tests/monitor_viewport_integration_test.rs` - Integration tests
|
|
|
|
### Modified Files
|
|
- `imgui/src/lib.rs` - Added `pub mod monitor_init_fix`
|
|
|
|
## Known Limitations
|
|
|
|
1. **Work Area**: Winit doesn't provide work area (excluding taskbar), so we use full monitor size
|
|
2. **Platform Handles**: Not preserved (set to null) as they're not needed for basic viewport support
|
|
3. **Hot-plug Support**: Monitor changes require manual re-initialization
|
|
|
|
## Complete Example
|
|
|
|
```rust
|
|
use imgui::*;
|
|
|
|
fn main() {
|
|
let mut ctx = Context::create();
|
|
|
|
// Configure for viewports
|
|
ctx.io_mut().config_flags |= ConfigFlags::VIEWPORTS_ENABLE;
|
|
ctx.io_mut().display_size = [1280.0, 720.0];
|
|
ctx.io_mut().delta_time = 1.0 / 60.0;
|
|
ctx.fonts().build_rgba32_texture();
|
|
|
|
// Apply fixes
|
|
viewport_issue_fix::apply_viewport_fix(&mut ctx);
|
|
monitor_init_fix::init_single_monitor(&mut ctx, 1920.0, 1080.0, 1.0);
|
|
|
|
// Set platform backend
|
|
ctx.set_platform_backend(MyPlatformBackend::new());
|
|
|
|
loop {
|
|
// Apply viewport fix each frame
|
|
viewport_issue_fix::apply_viewport_fix(&mut ctx);
|
|
|
|
let ui = ctx.new_frame();
|
|
|
|
// Windows can now be dragged outside!
|
|
ui.window("Draggable")
|
|
.size([300.0, 200.0], Condition::FirstUseEver)
|
|
.build(|| {
|
|
ui.text("Drag me outside!");
|
|
});
|
|
|
|
let draw_data = ctx.render();
|
|
// ... render draw_data ...
|
|
|
|
ctx.update_platform_windows();
|
|
ctx.render_platform_windows_default();
|
|
}
|
|
}
|
|
```
|
|
|
|
## Testing
|
|
|
|
Run the tests with:
|
|
```bash
|
|
cargo test --features docking monitor
|
|
```
|
|
|
|
Run the example:
|
|
```bash
|
|
cargo run --example monitor_initialization --features docking
|
|
```
|
|
|
|
## Future Improvements
|
|
|
|
1. **Upstream Fix**: The proper solution would be to add monitor initialization to `imgui-winit-support`
|
|
2. **Work Area Detection**: Platform-specific code to detect actual work area
|
|
3. **Auto-initialization**: Integrate with platform backend setup
|
|
4. **Monitor Events**: Handle display configuration changes automatically
|
|
|
|
## Summary
|
|
|
|
This workaround successfully enables viewport support by manually initializing the monitors list. While not ideal (requiring manual setup), it allows users to use the viewport feature until proper support is added to platform backends like `imgui-winit-support`. |