From ca05418cb449dadaabf014487c5c965908dfcbdd Mon Sep 17 00:00:00 2001 From: Robin Quint Date: Sat, 18 Nov 2023 11:29:23 +0100 Subject: [PATCH] Updated winit, glutin and glium dependencies --- Cargo.toml | 3 + imgui-examples/Cargo.toml | 2 +- imgui-examples/examples/support/mod.rs | 125 +++-- imgui-glium-renderer/Cargo.toml | 7 +- .../examples/glium_01_basic.rs | 175 +++--- imgui-glium-renderer/src/lib.rs | 4 +- imgui-glow-renderer/Cargo.toml | 5 +- imgui-glow-renderer/examples/glow_01_basic.rs | 191 ++++--- .../examples/glow_02_triangle.rs | 113 ++-- .../examples/glow_03_triangle_gles.rs | 120 +++-- .../examples/glow_04_custom_textures.rs | 122 +++-- .../examples/glow_05_framebufferobject.rs | 205 ++++--- imgui-glow-renderer/examples/utils/mod.rs | 95 +++- .../Cargo.toml | 6 +- .../examples/viewports_basic.rs | 146 ++--- .../src/lib.rs | 507 +++++++++--------- imgui-winit-support/Cargo.toml | 2 +- imgui-winit-support/src/lib.rs | 323 ++++++----- 18 files changed, 1214 insertions(+), 937 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f0438d14a..0f2bb30ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,6 @@ members = [ package.rust-version = "1.70" resolver = "2" + +[patch.crates-io] +glium = { git="https://github.com/glium/glium" } diff --git a/imgui-examples/Cargo.toml b/imgui-examples/Cargo.toml index 93c432dba..09db78b03 100644 --- a/imgui-examples/Cargo.toml +++ b/imgui-examples/Cargo.toml @@ -10,7 +10,7 @@ publish = false [dev-dependencies] copypasta = "0.8" -glium = { version = "0.32.1", default-features = true } +glium = { version = "0.33.0", default-features = true } image = "0.23" imgui = { path = "../imgui", features = ["tables-api"] } imgui-glium-renderer = { path = "../imgui-glium-renderer" } diff --git a/imgui-examples/examples/support/mod.rs b/imgui-examples/examples/support/mod.rs index 44e88259a..65c4b361e 100644 --- a/imgui-examples/examples/support/mod.rs +++ b/imgui-examples/examples/support/mod.rs @@ -1,10 +1,11 @@ -use glium::glutin; -use glium::glutin::event::{Event, WindowEvent}; -use glium::glutin::event_loop::{ControlFlow, EventLoop}; -use glium::glutin::window::WindowBuilder; -use glium::{Display, Surface}; +use glium::glutin::surface::WindowSurface; +use glium::Surface; use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui}; use imgui_glium_renderer::Renderer; +use imgui_winit_support::winit::dpi::LogicalSize; +use imgui_winit_support::winit::event::{Event, WindowEvent}; +use imgui_winit_support::winit::event_loop::EventLoop; +use imgui_winit_support::winit::window::{Window, WindowBuilder}; use imgui_winit_support::{HiDpiMode, WinitPlatform}; use std::path::Path; use std::time::Instant; @@ -13,7 +14,8 @@ mod clipboard; pub struct System { pub event_loop: EventLoop<()>, - pub display: glium::Display, + pub window: Window, + pub display: glium::Display, pub imgui: Context, pub platform: WinitPlatform, pub renderer: Renderer, @@ -25,13 +27,14 @@ pub fn init(title: &str) -> System { Some(file_name) => file_name.to_str().unwrap(), None => title, }; - let event_loop = EventLoop::new(); - let context = glutin::ContextBuilder::new().with_vsync(true); + let event_loop = EventLoop::new().expect("Failed to create EventLoop"); + let builder = WindowBuilder::new() - .with_title(title.to_owned()) - .with_inner_size(glutin::dpi::LogicalSize::new(1024f64, 768f64)); - let display = - Display::new(builder, context, &event_loop).expect("Failed to initialize display"); + .with_title(title) + .with_inner_size(LogicalSize::new(1024, 768)); + let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() + .set_window_builder(builder) + .build(&event_loop); let mut imgui = Context::create(); imgui.set_ini_filename(None); @@ -44,9 +47,6 @@ pub fn init(title: &str) -> System { let mut platform = WinitPlatform::init(&mut imgui); { - let gl_window = display.gl_window(); - let window = gl_window.window(); - let dpi_mode = if let Ok(factor) = std::env::var("IMGUI_EXAMPLE_FORCE_DPI_FACTOR") { // Allow forcing of HiDPI factor for debugging purposes match factor.parse::() { @@ -57,7 +57,7 @@ pub fn init(title: &str) -> System { HiDpiMode::Default }; - platform.attach_window(imgui.io_mut(), window, dpi_mode); + platform.attach_window(imgui.io_mut(), &window, dpi_mode); } // Fixed font size. Note imgui_winit_support uses "logical @@ -103,6 +103,7 @@ pub fn init(title: &str) -> System { System { event_loop, + window, display, imgui, platform, @@ -115,6 +116,7 @@ impl System { pub fn main_loop(self, mut run_ui: F) { let System { event_loop, + window, display, mut imgui, mut platform, @@ -123,46 +125,57 @@ impl System { } = self; let mut last_frame = Instant::now(); - event_loop.run(move |event, _, control_flow| match event { - Event::NewEvents(_) => { - let now = Instant::now(); - imgui.io_mut().update_delta_time(now - last_frame); - last_frame = now; - } - Event::MainEventsCleared => { - let gl_window = display.gl_window(); - platform - .prepare_frame(imgui.io_mut(), gl_window.window()) - .expect("Failed to prepare frame"); - gl_window.window().request_redraw(); - } - Event::RedrawRequested(_) => { - let ui = imgui.frame(); - - let mut run = true; - run_ui(&mut run, ui); - if !run { - *control_flow = ControlFlow::Exit; + event_loop + .run(move |event, window_target| match event { + Event::NewEvents(_) => { + let now = Instant::now(); + imgui.io_mut().update_delta_time(now - last_frame); + last_frame = now; } - - let gl_window = display.gl_window(); - let mut target = display.draw(); - target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); - platform.prepare_render(ui, gl_window.window()); - let draw_data = imgui.render(); - renderer - .render(&mut target, draw_data) - .expect("Rendering failed"); - target.finish().expect("Failed to swap buffers"); - } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, - event => { - let gl_window = display.gl_window(); - platform.handle_event(imgui.io_mut(), gl_window.window(), &event); - } - }) + Event::AboutToWait => { + platform + .prepare_frame(imgui.io_mut(), &window) + .expect("Failed to prepare frame"); + window.request_redraw(); + } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let ui = imgui.frame(); + + let mut run = true; + run_ui(&mut run, ui); + if !run { + window_target.exit(); + } + + let mut target = display.draw(); + target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); + platform.prepare_render(ui, &window); + let draw_data = imgui.render(); + renderer + .render(&mut target, draw_data) + .expect("Rendering failed"); + target.finish().expect("Failed to swap buffers"); + } + Event::WindowEvent { + event: WindowEvent::Resized(new_size), + .. + } => { + if new_size.width > 0 && new_size.height > 0 { + display.resize((new_size.width, new_size.height)); + } + platform.handle_event(imgui.io_mut(), &window, &event); + } + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => window_target.exit(), + event => { + platform.handle_event(imgui.io_mut(), &window, &event); + } + }) + .expect("EventLoop error"); } } diff --git a/imgui-glium-renderer/Cargo.toml b/imgui-glium-renderer/Cargo.toml index d96b7f09a..8122719bb 100644 --- a/imgui-glium-renderer/Cargo.toml +++ b/imgui-glium-renderer/Cargo.toml @@ -10,8 +10,13 @@ license = "MIT OR Apache-2.0" categories = ["gui", "rendering"] [dependencies] -glium = { version = "0.32.1", default-features = false } +glium = { version = "0.33.0", default-features = false } imgui = { version = "0.11.0", path = "../imgui" } [dev-dependencies] +glium = { version = "0.33.0", default-features = false, features = ["glutin_backend"] } imgui-winit-support = {path = "../imgui-winit-support"} +glutin = "0.31.1" +glutin-winit = "0.4.2" +winit = { version = "0.29.3", features = ["rwh_05"] } +raw-window-handle = "0.5.0" diff --git a/imgui-glium-renderer/examples/glium_01_basic.rs b/imgui-glium-renderer/examples/glium_01_basic.rs index 9c1fdb446..b57c41936 100644 --- a/imgui-glium-renderer/examples/glium_01_basic.rs +++ b/imgui-glium-renderer/examples/glium_01_basic.rs @@ -1,6 +1,18 @@ -use glium::glutin::event::{Event, WindowEvent}; -use glium::glutin::event_loop::{ControlFlow, EventLoop}; +use std::num::NonZeroU32; + use glium::Surface; +use glutin::{ + config::ConfigTemplateBuilder, + context::{ContextAttributesBuilder, NotCurrentGlContext}, + display::{GetGlDisplay, GlDisplay}, + surface::{SurfaceAttributesBuilder, WindowSurface}, +}; +use imgui_winit_support::winit::{dpi::LogicalSize, event_loop::EventLoop, window::WindowBuilder}; +use raw_window_handle::HasRawWindowHandle; +use winit::{ + event::{Event, WindowEvent}, + window::Window, +}; const TITLE: &str = "Hello, imgui-rs!"; @@ -8,8 +20,8 @@ fn main() { // Common setup for creating a winit window and imgui context, not specifc // to this renderer at all except that glutin is used to create the window // since it will give us access to a GL context - let (event_loop, display) = create_window(); - let (mut winit_platform, mut imgui_context) = imgui_init(&display); + let (event_loop, window, display) = create_window(); + let (mut winit_platform, mut imgui_context) = imgui_init(&window); // Create renderer from this crate let mut renderer = imgui_glium_renderer::Renderer::init(&mut imgui_context, &display) @@ -19,73 +31,112 @@ fn main() { let mut last_frame = std::time::Instant::now(); // Standard winit event loop - event_loop.run(move |event, _, control_flow| match event { - Event::NewEvents(_) => { - let now = std::time::Instant::now(); - imgui_context.io_mut().update_delta_time(now - last_frame); - last_frame = now; - } - Event::MainEventsCleared => { - let gl_window = display.gl_window(); - winit_platform - .prepare_frame(imgui_context.io_mut(), gl_window.window()) - .expect("Failed to prepare frame"); - gl_window.window().request_redraw(); - } - Event::RedrawRequested(_) => { - // Create frame for the all important `&imgui::Ui` - let ui = imgui_context.frame(); - - // Draw our example content - ui.show_demo_window(&mut true); - - // Setup for drawing - let gl_window = display.gl_window(); - let mut target = display.draw(); - - // Renderer doesn't automatically clear window - target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); - - // Perform rendering - winit_platform.prepare_render(ui, gl_window.window()); - let draw_data = imgui_context.render(); - renderer - .render(&mut target, draw_data) - .expect("Rendering failed"); - target.finish().expect("Failed to swap buffers"); - } - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, - event => { - let gl_window = display.gl_window(); - winit_platform.handle_event(imgui_context.io_mut(), gl_window.window(), &event); - } - }); + event_loop + .run(move |event, window_target| match event { + Event::NewEvents(_) => { + let now = std::time::Instant::now(); + imgui_context.io_mut().update_delta_time(now - last_frame); + last_frame = now; + } + Event::AboutToWait => { + winit_platform + .prepare_frame(imgui_context.io_mut(), &window) + .expect("Failed to prepare frame"); + window.request_redraw(); + } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + // Create frame for the all important `&imgui::Ui` + let ui = imgui_context.frame(); + + // Draw our example content + ui.show_demo_window(&mut true); + + // Setup for drawing + let mut target = display.draw(); + + // Renderer doesn't automatically clear window + target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); + + // Perform rendering + winit_platform.prepare_render(ui, &window); + let draw_data = imgui_context.render(); + renderer + .render(&mut target, draw_data) + .expect("Rendering failed"); + target.finish().expect("Failed to swap buffers"); + } + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => window_target.exit(), + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::Resized(new_size), + .. + } => { + if new_size.width > 0 && new_size.height > 0 { + display.resize((new_size.width, new_size.height)); + } + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } + event => { + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } + }) + .expect("EventLoop error"); } -fn create_window() -> (EventLoop<()>, glium::Display) { - let event_loop = EventLoop::new(); - let context = glium::glutin::ContextBuilder::new().with_vsync(true); - let builder = glium::glutin::window::WindowBuilder::new() - .with_title(TITLE.to_owned()) - .with_inner_size(glium::glutin::dpi::LogicalSize::new(1024f64, 768f64)); - let display = - glium::Display::new(builder, context, &event_loop).expect("Failed to initialize display"); - - (event_loop, display) +fn create_window() -> (EventLoop<()>, Window, glium::Display) { + let event_loop = EventLoop::new().expect("Failed to create EventLoop"); + + let window_builder = WindowBuilder::new() + .with_title(TITLE) + .with_inner_size(LogicalSize::new(1024, 768)); + + let (window, cfg) = glutin_winit::DisplayBuilder::new() + .with_window_builder(Some(window_builder)) + .build(&event_loop, ConfigTemplateBuilder::new(), |mut configs| { + configs.next().unwrap() + }) + .expect("Failed to create OpenGL window"); + let window = window.unwrap(); + + let context_attribs = ContextAttributesBuilder::new().build(Some(window.raw_window_handle())); + let context = unsafe { + cfg.display() + .create_context(&cfg, &context_attribs) + .expect("Failed to create OpenGL context") + }; + + let surface_attribs = SurfaceAttributesBuilder::::new().build( + window.raw_window_handle(), + NonZeroU32::new(1024).unwrap(), + NonZeroU32::new(768).unwrap(), + ); + let surface = unsafe { + cfg.display() + .create_window_surface(&cfg, &surface_attribs) + .expect("Failed to create OpenGL surface") + }; + + let context = context + .make_current(&surface) + .expect("Failed to make OpenGL context current"); + + let display = glium::Display::from_context_surface(context, surface) + .expect("Failed to create glium Display"); + + (event_loop, window, display) } -fn imgui_init(display: &glium::Display) -> (imgui_winit_support::WinitPlatform, imgui::Context) { +fn imgui_init(window: &Window) -> (imgui_winit_support::WinitPlatform, imgui::Context) { let mut imgui_context = imgui::Context::create(); imgui_context.set_ini_filename(None); let mut winit_platform = imgui_winit_support::WinitPlatform::init(&mut imgui_context); - let gl_window = display.gl_window(); - let window = gl_window.window(); - let dpi_mode = imgui_winit_support::HiDpiMode::Default; winit_platform.attach_window(imgui_context.io_mut(), window, dpi_mode); diff --git a/imgui-glium-renderer/src/lib.rs b/imgui-glium-renderer/src/lib.rs index 8cddd5541..4765a9d6d 100644 --- a/imgui-glium-renderer/src/lib.rs +++ b/imgui-glium-renderer/src/lib.rs @@ -113,7 +113,7 @@ impl glium::vertex::Vertex for GliumDrawVert { #[inline] fn build_bindings() -> glium::vertex::VertexFormat { use std::borrow::Cow::*; - Borrowed(&[ + &[ ( Borrowed("pos"), 0, @@ -135,7 +135,7 @@ impl glium::vertex::Vertex for GliumDrawVert { glium::vertex::AttributeType::U8U8U8U8, false, ), - ]) + ] } } diff --git a/imgui-glow-renderer/Cargo.toml b/imgui-glow-renderer/Cargo.toml index d719fe964..df00871c5 100644 --- a/imgui-glow-renderer/Cargo.toml +++ b/imgui-glow-renderer/Cargo.toml @@ -14,9 +14,12 @@ glow = "0.12.0" memoffset = "0.9" [dev-dependencies] -glutin = "0.29.1" +glutin = "0.31.1" +glutin-winit = "0.4.2" imgui-winit-support = { version = "0.11.0", path = "../imgui-winit-support" } image = "0.23" +raw-window-handle = "0.5.0" +winit = { version = "0.29.3", features = ["rwh_05"] } [features] # Features here are used to opt-out of compiling code that depends on certain diff --git a/imgui-glow-renderer/examples/glow_01_basic.rs b/imgui-glow-renderer/examples/glow_01_basic.rs index 1a34b0149..32b30ffc5 100644 --- a/imgui-glow-renderer/examples/glow_01_basic.rs +++ b/imgui-glow-renderer/examples/glow_01_basic.rs @@ -1,25 +1,36 @@ //! A basic self-contained example to get you from zero-to-demo-window as fast //! as possible. -use std::time::Instant; +use std::{num::NonZeroU32, time::Instant}; use glow::HasContext; -use glutin::{event_loop::EventLoop, WindowedContext}; -use imgui_winit_support::WinitPlatform; +use glutin::{ + config::ConfigTemplateBuilder, + context::{ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentContext}, + display::{GetGlDisplay, GlDisplay}, + surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface}, +}; +use imgui_winit_support::{ + winit::{ + dpi::LogicalSize, + event_loop::EventLoop, + window::{Window, WindowBuilder}, + }, + WinitPlatform, +}; +use raw_window_handle::HasRawWindowHandle; const TITLE: &str = "Hello, imgui-rs!"; -type Window = WindowedContext; - fn main() { // Common setup for creating a winit window and imgui context, not specifc // to this renderer at all except that glutin is used to create the window // since it will give us access to a GL context - let (event_loop, window) = create_window(); + let (event_loop, window, surface, context) = create_window(); let (mut winit_platform, mut imgui_context) = imgui_init(&window); // OpenGL context from glow - let gl = glow_context(&window); + let gl = glow_context(&context); // OpenGL renderer from this crate let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) @@ -28,70 +39,122 @@ fn main() { let mut last_frame = Instant::now(); // Standard winit event loop - event_loop.run(move |event, _, control_flow| { - match event { - glutin::event::Event::NewEvents(_) => { - let now = Instant::now(); - imgui_context - .io_mut() - .update_delta_time(now.duration_since(last_frame)); - last_frame = now; - } - glutin::event::Event::MainEventsCleared => { - winit_platform - .prepare_frame(imgui_context.io_mut(), window.window()) - .unwrap(); - window.window().request_redraw(); + event_loop + .run(move |event, window_target| { + match event { + winit::event::Event::NewEvents(_) => { + let now = Instant::now(); + imgui_context + .io_mut() + .update_delta_time(now.duration_since(last_frame)); + last_frame = now; + } + winit::event::Event::AboutToWait => { + winit_platform + .prepare_frame(imgui_context.io_mut(), &window) + .unwrap(); + window.request_redraw(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { + // The renderer assumes you'll be clearing the buffer yourself + unsafe { ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT) }; + + let ui = imgui_context.frame(); + ui.show_demo_window(&mut true); + + winit_platform.prepare_render(ui, &window); + let draw_data = imgui_context.render(); + + // This is the only extra render step to add + ig_renderer + .render(draw_data) + .expect("error rendering imgui"); + + surface + .swap_buffers(&context) + .expect("Failed to swap buffers"); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CloseRequested, + .. + } => { + window_target.exit(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::Resized(new_size), + .. + } => { + if new_size.width > 0 && new_size.height > 0 { + surface.resize( + &context, + NonZeroU32::new(new_size.width).unwrap(), + NonZeroU32::new(new_size.height).unwrap(), + ); + } + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } + event => { + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } } - glutin::event::Event::RedrawRequested(_) => { - // The renderer assumes you'll be clearing the buffer yourself - unsafe { ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT) }; + }) + .expect("EventLoop error"); +} - let ui = imgui_context.frame(); - ui.show_demo_window(&mut true); +fn create_window() -> ( + EventLoop<()>, + Window, + Surface, + PossiblyCurrentContext, +) { + let event_loop = EventLoop::new().unwrap(); - winit_platform.prepare_render(ui, window.window()); - let draw_data = imgui_context.render(); + let window_builder = WindowBuilder::new() + .with_title(TITLE) + .with_inner_size(LogicalSize::new(1024, 768)); + let (window, cfg) = glutin_winit::DisplayBuilder::new() + .with_window_builder(Some(window_builder)) + .build(&event_loop, ConfigTemplateBuilder::new(), |mut configs| { + configs.next().unwrap() + }) + .expect("Failed to create OpenGL window"); + + let window = window.unwrap(); + + let context_attribs = ContextAttributesBuilder::new().build(Some(window.raw_window_handle())); + let context = unsafe { + cfg.display() + .create_context(&cfg, &context_attribs) + .expect("Failed to create OpenGL context") + }; - // This is the only extra render step to add - ig_renderer - .render(draw_data) - .expect("error rendering imgui"); + let surface_attribs = SurfaceAttributesBuilder::::new() + .with_srgb(Some(true)) + .build( + window.raw_window_handle(), + NonZeroU32::new(1024).unwrap(), + NonZeroU32::new(768).unwrap(), + ); + let surface = unsafe { + cfg.display() + .create_window_surface(&cfg, &surface_attribs) + .expect("Failed to create OpenGL surface") + }; - window.swap_buffers().unwrap(); - } - glutin::event::Event::WindowEvent { - event: glutin::event::WindowEvent::CloseRequested, - .. - } => { - *control_flow = glutin::event_loop::ControlFlow::Exit; - } - event => { - winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event); - } - } - }); -} + let context = context + .make_current(&surface) + .expect("Failed to make OpenGL context current"); -fn create_window() -> (EventLoop<()>, Window) { - let event_loop = glutin::event_loop::EventLoop::new(); - let window = glutin::window::WindowBuilder::new() - .with_title(TITLE) - .with_inner_size(glutin::dpi::LogicalSize::new(1024, 768)); - let window = glutin::ContextBuilder::new() - .with_vsync(true) - .build_windowed(window, &event_loop) - .expect("could not create window"); - let window = unsafe { - window - .make_current() - .expect("could not make window context current") - }; - (event_loop, window) + (event_loop, window, surface, context) } -fn glow_context(window: &Window) -> glow::Context { - unsafe { glow::Context::from_loader_function(|s| window.get_proc_address(s).cast()) } +fn glow_context(context: &PossiblyCurrentContext) -> glow::Context { + unsafe { + glow::Context::from_loader_function_cstr(|s| context.display().get_proc_address(s).cast()) + } } fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) { @@ -101,7 +164,7 @@ fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) { let mut winit_platform = WinitPlatform::init(&mut imgui_context); winit_platform.attach_window( imgui_context.io_mut(), - window.window(), + window, imgui_winit_support::HiDpiMode::Rounded, ); diff --git a/imgui-glow-renderer/examples/glow_02_triangle.rs b/imgui-glow-renderer/examples/glow_02_triangle.rs index 512b84f0f..09e984b16 100644 --- a/imgui-glow-renderer/examples/glow_02_triangle.rs +++ b/imgui-glow-renderer/examples/glow_02_triangle.rs @@ -1,68 +1,89 @@ //! A basic example showing imgui rendering on top of a simple custom scene. -use std::time::Instant; +use std::{num::NonZeroU32, time::Instant}; mod utils; +use glutin::surface::GlSurface; use utils::Triangler; fn main() { - let (event_loop, window) = utils::create_window("Hello, triangle!", glutin::GlRequest::Latest); + let (event_loop, window, surface, context) = utils::create_window("Hello, triangle!", None); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); - let gl = utils::glow_context(&window); + let gl = utils::glow_context(&context); let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) .expect("failed to create renderer"); let tri_renderer = Triangler::new(ig_renderer.gl_context(), "#version 330"); let mut last_frame = Instant::now(); - event_loop.run(move |event, _, control_flow| { - match event { - glutin::event::Event::NewEvents(_) => { - let now = Instant::now(); - imgui_context - .io_mut() - .update_delta_time(now.duration_since(last_frame)); - last_frame = now; - } - glutin::event::Event::MainEventsCleared => { - winit_platform - .prepare_frame(imgui_context.io_mut(), window.window()) - .unwrap(); + event_loop + .run(move |event, window_target| { + match event { + winit::event::Event::NewEvents(_) => { + let now = Instant::now(); + imgui_context + .io_mut() + .update_delta_time(now.duration_since(last_frame)); + last_frame = now; + } + winit::event::Event::AboutToWait => { + winit_platform + .prepare_frame(imgui_context.io_mut(), &window) + .unwrap(); - window.window().request_redraw(); - } - glutin::event::Event::RedrawRequested(_) => { - // Render your custom scene, note we need to borrow the OpenGL - // context from the `AutoRenderer`, which takes ownership of it. - tri_renderer.render(ig_renderer.gl_context()); + window.request_redraw(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { + // Render your custom scene, note we need to borrow the OpenGL + // context from the `AutoRenderer`, which takes ownership of it. + tri_renderer.render(ig_renderer.gl_context()); - let ui = imgui_context.frame(); - ui.show_demo_window(&mut true); + let ui = imgui_context.frame(); + ui.show_demo_window(&mut true); - winit_platform.prepare_render(ui, window.window()); - let draw_data = imgui_context.render(); + winit_platform.prepare_render(ui, &window); + let draw_data = imgui_context.render(); - // Render imgui on top of it - ig_renderer - .render(draw_data) - .expect("error rendering imgui"); + // Render imgui on top of it + ig_renderer + .render(draw_data) + .expect("error rendering imgui"); - window.swap_buffers().unwrap(); - } - glutin::event::Event::WindowEvent { - event: glutin::event::WindowEvent::CloseRequested, - .. - } => { - *control_flow = glutin::event_loop::ControlFlow::Exit; - } - glutin::event::Event::LoopDestroyed => { - let gl = ig_renderer.gl_context(); - tri_renderer.destroy(gl); - } - event => { - winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event); + surface + .swap_buffers(&context) + .expect("Failed to swap buffers"); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CloseRequested, + .. + } => { + window_target.exit(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::Resized(new_size), + .. + } => { + if new_size.width > 0 && new_size.height > 0 { + surface.resize( + &context, + NonZeroU32::new(new_size.width).unwrap(), + NonZeroU32::new(new_size.height).unwrap(), + ); + } + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } + winit::event::Event::LoopExiting => { + let gl = ig_renderer.gl_context(); + tri_renderer.destroy(gl); + } + event => { + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } } - } - }); + }) + .expect("EventLoop error"); } diff --git a/imgui-glow-renderer/examples/glow_03_triangle_gles.rs b/imgui-glow-renderer/examples/glow_03_triangle_gles.rs index a63f1ee86..dcc4db4f8 100644 --- a/imgui-glow-renderer/examples/glow_03_triangle_gles.rs +++ b/imgui-glow-renderer/examples/glow_03_triangle_gles.rs @@ -4,19 +4,23 @@ //! Note this example uses `Renderer` rather than `AutoRenderer` and //! therefore requries more lifetime-management of the OpenGL context. -use std::time::Instant; +use std::{num::NonZeroU32, time::Instant}; mod utils; +use glutin::{ + context::{ContextApi, Version}, + surface::GlSurface, +}; use utils::Triangler; fn main() { - let (event_loop, window) = utils::create_window( + let (event_loop, window, surface, context) = utils::create_window( "Hello, triangle! (GLES 3.0)", - glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0)), + Some(ContextApi::Gles(Some(Version::new(3, 0)))), ); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); - let gl = utils::glow_context(&window); + let gl = utils::glow_context(&context); // When using `Renderer`, we need to create a texture map let mut texture_map = imgui_glow_renderer::SimpleTextureMap::default(); @@ -31,54 +35,74 @@ fn main() { let tri_renderer = Triangler::new(&gl, "#version 300 es\nprecision mediump float;"); let mut last_frame = Instant::now(); - event_loop.run(move |event, _, control_flow| { - match event { - glutin::event::Event::NewEvents(_) => { - let now = Instant::now(); - imgui_context - .io_mut() - .update_delta_time(now.duration_since(last_frame)); - last_frame = now; - } - glutin::event::Event::MainEventsCleared => { - winit_platform - .prepare_frame(imgui_context.io_mut(), window.window()) - .unwrap(); + event_loop + .run(move |event, window_target| { + match event { + winit::event::Event::NewEvents(_) => { + let now = Instant::now(); + imgui_context + .io_mut() + .update_delta_time(now.duration_since(last_frame)); + last_frame = now; + } + winit::event::Event::AboutToWait => { + winit_platform + .prepare_frame(imgui_context.io_mut(), &window) + .unwrap(); - window.window().request_redraw(); - } - glutin::event::Event::RedrawRequested(_) => { - // Draw custom scene - tri_renderer.render(&gl); + window.request_redraw(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { + // Draw custom scene + tri_renderer.render(&gl); - let ui = imgui_context.frame(); - ui.show_demo_window(&mut true); + let ui = imgui_context.frame(); + ui.show_demo_window(&mut true); - winit_platform.prepare_render(ui, window.window()); - let draw_data = imgui_context.render(); + winit_platform.prepare_render(ui, &window); + let draw_data = imgui_context.render(); - // Render imgui on top - ig_renderer - .render(&gl, &texture_map, draw_data) - .expect("error rendering imgui"); + // Render imgui on top + ig_renderer + .render(&gl, &texture_map, draw_data) + .expect("error rendering imgui"); - window.swap_buffers().unwrap(); - } - glutin::event::Event::WindowEvent { - event: glutin::event::WindowEvent::CloseRequested, - .. - } => { - *control_flow = glutin::event_loop::ControlFlow::Exit; - } - glutin::event::Event::LoopDestroyed => { - tri_renderer.destroy(&gl); - // Note, to be good citizens we should manually call destroy - // when the renderer does not own the GL context - ig_renderer.destroy(&gl); - } - event => { - winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event); + surface + .swap_buffers(&context) + .expect("Failed to swap buffers"); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CloseRequested, + .. + } => { + window_target.exit(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::Resized(new_size), + .. + } => { + if new_size.width > 0 && new_size.height > 0 { + surface.resize( + &context, + NonZeroU32::new(new_size.width).unwrap(), + NonZeroU32::new(new_size.height).unwrap(), + ); + } + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } + winit::event::Event::LoopExiting => { + tri_renderer.destroy(&gl); + // Note, to be good citizens we should manually call destroy + // when the renderer does not own the GL context + ig_renderer.destroy(&gl); + } + event => { + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } } - } - }); + }) + .expect("EventLoop error"); } diff --git a/imgui-glow-renderer/examples/glow_04_custom_textures.rs b/imgui-glow-renderer/examples/glow_04_custom_textures.rs index cf77110dd..2128ae363 100644 --- a/imgui-glow-renderer/examples/glow_04_custom_textures.rs +++ b/imgui-glow-renderer/examples/glow_04_custom_textures.rs @@ -5,13 +5,15 @@ //! OpenGL automatically converts colors to linear space before the shaders. //! The renderer assumes you set this internal format correctly like this. -use std::{io::Cursor, time::Instant}; +use std::{io::Cursor, num::NonZeroU32, time::Instant}; use glow::HasContext; +use glutin::surface::GlSurface; use image::{jpeg::JpegDecoder, ImageDecoder}; use imgui::Condition; use imgui_glow_renderer::Renderer; +use winit::event_loop::ControlFlow; #[allow(dead_code)] mod utils; @@ -19,9 +21,9 @@ mod utils; const LENNA_JPEG: &[u8] = include_bytes!("../../resources/Lenna.jpg"); fn main() { - let (event_loop, window) = utils::create_window("Custom textures", glutin::GlRequest::Latest); + let (event_loop, window, surface, context) = utils::create_window("Custom textures", None); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); - let gl = utils::glow_context(&window); + let gl = utils::glow_context(&context); // This time, we tell OpenGL this is an sRGB framebuffer and OpenGL will // do the conversion to sSGB space for us after the fragment shader. unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) }; @@ -35,55 +37,75 @@ fn main() { let textures_ui = TexturesUi::new(&gl, &mut textures); let mut last_frame = Instant::now(); - event_loop.run(move |event, _, control_flow| { - // Note we can potentially make the loop more efficient by - // changing the `Poll` (default) value to `ControlFlow::Wait` - // but be careful to test on all target platforms! - *control_flow = glutin::event_loop::ControlFlow::Poll; - - match event { - glutin::event::Event::NewEvents(_) => { - let now = Instant::now(); - imgui_context - .io_mut() - .update_delta_time(now.duration_since(last_frame)); - last_frame = now; - } - glutin::event::Event::MainEventsCleared => { - winit_platform - .prepare_frame(imgui_context.io_mut(), window.window()) - .unwrap(); - - window.window().request_redraw(); - } - glutin::event::Event::RedrawRequested(_) => { - unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }; - - let ui = imgui_context.frame(); - textures_ui.show(ui); - - winit_platform.prepare_render(ui, window.window()); - let draw_data = imgui_context.render(); - ig_renderer - .render(&gl, &textures, draw_data) - .expect("error rendering imgui"); + event_loop + .run(move |event, window_target| { + // Note we can potentially make the loop more efficient by + // changing the `Poll` (default) value to `ControlFlow::Wait` + // but be careful to test on all target platforms! + window_target.set_control_flow(ControlFlow::Poll); + + match event { + winit::event::Event::NewEvents(_) => { + let now = Instant::now(); + imgui_context + .io_mut() + .update_delta_time(now.duration_since(last_frame)); + last_frame = now; + } + winit::event::Event::AboutToWait => { + winit_platform + .prepare_frame(imgui_context.io_mut(), &window) + .unwrap(); - window.swap_buffers().unwrap(); - } - glutin::event::Event::WindowEvent { - event: glutin::event::WindowEvent::CloseRequested, - .. - } => { - *control_flow = glutin::event_loop::ControlFlow::Exit; - } - glutin::event::Event::LoopDestroyed => { - ig_renderer.destroy(&gl); - } - event => { - winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event); + window.request_redraw(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { + unsafe { gl.clear(glow::COLOR_BUFFER_BIT) }; + + let ui = imgui_context.frame(); + textures_ui.show(ui); + + winit_platform.prepare_render(ui, &window); + let draw_data = imgui_context.render(); + ig_renderer + .render(&gl, &textures, draw_data) + .expect("error rendering imgui"); + + surface + .swap_buffers(&context) + .expect("Failed to swap buffers"); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::Resized(new_size), + .. + } => { + if new_size.width > 0 && new_size.height > 0 { + surface.resize( + &context, + NonZeroU32::new(new_size.width).unwrap(), + NonZeroU32::new(new_size.height).unwrap(), + ); + } + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CloseRequested, + .. + } => { + window_target.exit(); + } + winit::event::Event::LoopExiting => { + ig_renderer.destroy(&gl); + } + event => { + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } } - } - }); + }) + .expect("EventLoop error"); } struct TexturesUi { diff --git a/imgui-glow-renderer/examples/glow_05_framebufferobject.rs b/imgui-glow-renderer/examples/glow_05_framebufferobject.rs index f85174500..b1b9e49fc 100644 --- a/imgui-glow-renderer/examples/glow_05_framebufferobject.rs +++ b/imgui-glow-renderer/examples/glow_05_framebufferobject.rs @@ -1,10 +1,11 @@ //! A basic example showing imgui rendering on top of a simple custom scene. -use std::{cell::RefCell, rc::Rc, time::Instant}; +use std::{cell::RefCell, num::NonZeroU32, rc::Rc, time::Instant}; mod utils; use glow::HasContext; +use glutin::surface::GlSurface; use utils::Triangler; struct UserData { @@ -16,9 +17,9 @@ struct UserData { const FBO_SIZE: i32 = 128; fn main() { - let (event_loop, window) = utils::create_window("Hello, FBO!", glutin::GlRequest::Latest); + let (event_loop, window, surface, context) = utils::create_window("Hello, FBO!", None); let (mut winit_platform, mut imgui_context) = utils::imgui_init(&window); - let gl = utils::glow_context(&window); + let gl = utils::glow_context(&context); let mut ig_renderer = imgui_glow_renderer::AutoRenderer::initialize(gl, &mut imgui_context) .expect("failed to create renderer"); @@ -55,96 +56,124 @@ fn main() { })); let mut last_frame = Instant::now(); - event_loop.run(move |event, _, control_flow| { - match event { - glutin::event::Event::NewEvents(_) => { - let now = Instant::now(); - imgui_context - .io_mut() - .update_delta_time(now.duration_since(last_frame)); - last_frame = now; - } - glutin::event::Event::MainEventsCleared => { - winit_platform - .prepare_frame(imgui_context.io_mut(), window.window()) - .unwrap(); - - window.window().request_redraw(); - } - glutin::event::Event::RedrawRequested(_) => { - // Render your custom scene, note we need to borrow the OpenGL - // context from the `AutoRenderer`, which takes ownership of it. - unsafe { - ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT); + event_loop + .run(move |event, window_target| { + match event { + winit::event::Event::NewEvents(_) => { + let now = Instant::now(); + imgui_context + .io_mut() + .update_delta_time(now.duration_since(last_frame)); + last_frame = now; } + winit::event::Event::AboutToWait => { + winit_platform + .prepare_frame(imgui_context.io_mut(), &window) + .unwrap(); - let ui = imgui_context.frame(); - ui.show_demo_window(&mut true); - ui.window("FBO").resizable(false).build(|| { - let pos = ui.cursor_screen_pos(); - ui.set_cursor_screen_pos([pos[0] + FBO_SIZE as f32, pos[1] + FBO_SIZE as f32]); - - let draws = ui.get_window_draw_list(); - let scale = ui.io().display_framebuffer_scale; - let dsp_size = ui.io().display_size; - draws - .add_callback({ - let data = Rc::clone(&data); - move || { - let data = data.borrow(); - let gl = &*data.gl; - unsafe { - let x = pos[0] * scale[0]; - let y = (dsp_size[1] - pos[1]) * scale[1]; - let dst_x0 = x as i32; - let dst_y0 = (y - FBO_SIZE as f32 * scale[1]) as i32; - let dst_x1 = (x + FBO_SIZE as f32 * scale[0]) as i32; - let dst_y1 = y as i32; - gl.scissor(dst_x0, dst_y0, dst_x1 - dst_x0, dst_y1 - dst_y0); - gl.enable(glow::SCISSOR_TEST); - gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(data.fbo)); - gl.blit_framebuffer( - 0, - 0, - FBO_SIZE, - FBO_SIZE, - dst_x0, - dst_y0, - dst_x1, - dst_y1, - glow::COLOR_BUFFER_BIT, - glow::NEAREST, - ); - gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None); + window.request_redraw(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::RedrawRequested, + .. + } => { + // Render your custom scene, note we need to borrow the OpenGL + // context from the `AutoRenderer`, which takes ownership of it. + unsafe { + ig_renderer.gl_context().clear(glow::COLOR_BUFFER_BIT); + } + + let ui = imgui_context.frame(); + ui.show_demo_window(&mut true); + ui.window("FBO").resizable(false).build(|| { + let pos = ui.cursor_screen_pos(); + ui.set_cursor_screen_pos([ + pos[0] + FBO_SIZE as f32, + pos[1] + FBO_SIZE as f32, + ]); + + let draws = ui.get_window_draw_list(); + let scale = ui.io().display_framebuffer_scale; + let dsp_size = ui.io().display_size; + draws + .add_callback({ + let data = Rc::clone(&data); + move || { + let data = data.borrow(); + let gl = &*data.gl; + unsafe { + let x = pos[0] * scale[0]; + let y = (dsp_size[1] - pos[1]) * scale[1]; + let dst_x0 = x as i32; + let dst_y0 = (y - FBO_SIZE as f32 * scale[1]) as i32; + let dst_x1 = (x + FBO_SIZE as f32 * scale[0]) as i32; + let dst_y1 = y as i32; + gl.scissor( + dst_x0, + dst_y0, + dst_x1 - dst_x0, + dst_y1 - dst_y0, + ); + gl.enable(glow::SCISSOR_TEST); + gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(data.fbo)); + gl.blit_framebuffer( + 0, + 0, + FBO_SIZE, + FBO_SIZE, + dst_x0, + dst_y0, + dst_x1, + dst_y1, + glow::COLOR_BUFFER_BIT, + glow::NEAREST, + ); + gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None); + } } - } - }) - .build(); - }); + }) + .build(); + }); - winit_platform.prepare_render(ui, window.window()); - let draw_data = imgui_context.render(); + winit_platform.prepare_render(ui, &window); + let draw_data = imgui_context.render(); - // Render imgui on top of it - ig_renderer - .render(draw_data) - .expect("error rendering imgui"); + // Render imgui on top of it + ig_renderer + .render(draw_data) + .expect("error rendering imgui"); - window.swap_buffers().unwrap(); - } - glutin::event::Event::WindowEvent { - event: glutin::event::WindowEvent::CloseRequested, - .. - } => { - *control_flow = glutin::event_loop::ControlFlow::Exit; - } - glutin::event::Event::LoopDestroyed => { - let gl = ig_renderer.gl_context(); - tri_renderer.destroy(gl); - } - event => { - winit_platform.handle_event(imgui_context.io_mut(), window.window(), &event); + surface + .swap_buffers(&context) + .expect("Failed to swap buffers"); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CloseRequested, + .. + } => { + window_target.exit(); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::Resized(new_size), + .. + } => { + if new_size.width > 0 && new_size.height > 0 { + surface.resize( + &context, + NonZeroU32::new(new_size.width).unwrap(), + NonZeroU32::new(new_size.height).unwrap(), + ); + } + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } + winit::event::Event::LoopExiting => { + let gl = ig_renderer.gl_context(); + tri_renderer.destroy(gl); + } + event => { + winit_platform.handle_event(imgui_context.io_mut(), &window, &event); + } } - } - }); + }) + .expect("EventLoop error"); } diff --git a/imgui-glow-renderer/examples/utils/mod.rs b/imgui-glow-renderer/examples/utils/mod.rs index 3f8399d56..b1a7b78bb 100644 --- a/imgui-glow-renderer/examples/utils/mod.rs +++ b/imgui-glow-renderer/examples/utils/mod.rs @@ -1,29 +1,82 @@ +use std::num::NonZeroU32; + use glow::HasContext; -use glutin::{event_loop::EventLoop, GlRequest}; +use glutin::{ + config::ConfigTemplateBuilder, + context::{ContextApi, ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentContext}, + display::{GetGlDisplay, GlDisplay}, + surface::{GlSurface, Surface, SurfaceAttributesBuilder, SwapInterval, WindowSurface}, +}; use imgui_winit_support::WinitPlatform; - -pub type Window = glutin::WindowedContext; - -pub fn create_window(title: &str, gl_request: GlRequest) -> (EventLoop<()>, Window) { - let event_loop = glutin::event_loop::EventLoop::new(); - let window = glutin::window::WindowBuilder::new() +use raw_window_handle::HasRawWindowHandle; +use winit::{ + dpi::LogicalSize, + event_loop::EventLoop, + window::{Window, WindowBuilder}, +}; + +pub fn create_window( + title: &str, + context_api: Option, +) -> ( + EventLoop<()>, + Window, + Surface, + PossiblyCurrentContext, +) { + let event_loop = EventLoop::new().unwrap(); + + let window_builder = WindowBuilder::new() .with_title(title) - .with_inner_size(glutin::dpi::LogicalSize::new(1024, 768)); - let window = glutin::ContextBuilder::new() - .with_gl(gl_request) - .with_vsync(true) - .build_windowed(window, &event_loop) - .expect("could not create window"); - let window = unsafe { - window - .make_current() - .expect("could not make window context current") + .with_inner_size(LogicalSize::new(1024, 768)); + let (window, cfg) = glutin_winit::DisplayBuilder::new() + .with_window_builder(Some(window_builder)) + .build(&event_loop, ConfigTemplateBuilder::new(), |mut configs| { + configs.next().unwrap() + }) + .expect("Failed to create OpenGL window"); + + let window = window.unwrap(); + + let mut context_attribs = ContextAttributesBuilder::new(); + if let Some(context_api) = context_api { + context_attribs = context_attribs.with_context_api(context_api); + } + let context_attribs = context_attribs.build(Some(window.raw_window_handle())); + let context = unsafe { + cfg.display() + .create_context(&cfg, &context_attribs) + .expect("Failed to create OpenGL context") + }; + + let surface_attribs = SurfaceAttributesBuilder::::new() + .with_srgb(Some(true)) + .build( + window.raw_window_handle(), + NonZeroU32::new(1024).unwrap(), + NonZeroU32::new(768).unwrap(), + ); + let surface = unsafe { + cfg.display() + .create_window_surface(&cfg, &surface_attribs) + .expect("Failed to create OpenGL surface") }; - (event_loop, window) + + let context = context + .make_current(&surface) + .expect("Failed to make OpenGL context current"); + + surface + .set_swap_interval(&context, SwapInterval::Wait(NonZeroU32::new(1).unwrap())) + .expect("Failed to set swap interval"); + + (event_loop, window, surface, context) } -pub fn glow_context(window: &Window) -> glow::Context { - unsafe { glow::Context::from_loader_function(|s| window.get_proc_address(s).cast()) } +pub fn glow_context(context: &PossiblyCurrentContext) -> glow::Context { + unsafe { + glow::Context::from_loader_function_cstr(|s| context.display().get_proc_address(s).cast()) + } } pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) { @@ -33,7 +86,7 @@ pub fn imgui_init(window: &Window) -> (WinitPlatform, imgui::Context) { let mut winit_platform = WinitPlatform::init(&mut imgui_context); winit_platform.attach_window( imgui_context.io_mut(), - window.window(), + window, imgui_winit_support::HiDpiMode::Rounded, ); diff --git a/imgui-winit-glow-renderer-viewports/Cargo.toml b/imgui-winit-glow-renderer-viewports/Cargo.toml index aea70cdf1..ea2cb12cd 100644 --- a/imgui-winit-glow-renderer-viewports/Cargo.toml +++ b/imgui-winit-glow-renderer-viewports/Cargo.toml @@ -13,8 +13,8 @@ license = "MIT OR Apache-2.0" imgui = { version = "0.11.0", path="../imgui", features=["docking"] } glow = "0.12.0" -glutin = "0.30.3" +glutin = "0.31.1" +glutin-winit = "0.4.2" raw-window-handle = "0.5.0" -winit = "0.27.5" +winit = "0.29.3" thiserror = "1.0.38" -glutin-winit = "0.2.1" diff --git a/imgui-winit-glow-renderer-viewports/examples/viewports_basic.rs b/imgui-winit-glow-renderer-viewports/examples/viewports_basic.rs index b49e70f8e..132834686 100644 --- a/imgui-winit-glow-renderer-viewports/examples/viewports_basic.rs +++ b/imgui-winit-glow-renderer-viewports/examples/viewports_basic.rs @@ -3,21 +3,24 @@ use std::{ffi::CString, num::NonZeroU32, time::Instant}; use glow::{Context, HasContext}; use glutin::{ config::ConfigTemplateBuilder, - context::ContextAttributesBuilder, + context::{ContextAttributesBuilder, NotCurrentGlContext, PossiblyCurrentGlContext}, display::GetGlDisplay, - prelude::{ - GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentContextGlSurfaceAccessor, - }, + prelude::GlDisplay, surface::{GlSurface, SurfaceAttributesBuilder, WindowSurface}, }; use glutin_winit::DisplayBuilder; use imgui::ConfigFlags; use imgui_winit_glow_renderer_viewports::Renderer; use raw_window_handle::HasRawWindowHandle; -use winit::{dpi::LogicalSize, event::WindowEvent, event_loop::EventLoop, window::WindowBuilder}; +use winit::{ + dpi::LogicalSize, + event::WindowEvent, + event_loop::{ControlFlow, EventLoop}, + window::WindowBuilder, +}; fn main() { - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().expect("Failed to create EventLoop"); let window_builder = WindowBuilder::new() .with_inner_size(LogicalSize::new(800.0, 600.0)) @@ -82,81 +85,86 @@ fn main() { let mut last_frame = Instant::now(); - event_loop.run(move |event, window_target, control_flow| { - control_flow.set_poll(); + event_loop + .run(move |event, window_target| { + window_target.set_control_flow(ControlFlow::Poll); - renderer.handle_event(&mut imgui, &window, &event); + renderer.handle_event(&mut imgui, &window, &event); - match event { - winit::event::Event::NewEvents(_) => { - let now = Instant::now(); - imgui.io_mut().update_delta_time(now - last_frame); - last_frame = now; - } - winit::event::Event::WindowEvent { - window_id, - event: WindowEvent::CloseRequested, - } if window_id == window.id() => { - control_flow.set_exit(); - } - winit::event::Event::WindowEvent { - window_id, - event: WindowEvent::Resized(new_size), - } if window_id == window.id() => { - surface.resize( - &context, - NonZeroU32::new(new_size.width).unwrap(), - NonZeroU32::new(new_size.height).unwrap(), - ); - } - winit::event::Event::MainEventsCleared => { - window.request_redraw(); - } - winit::event::Event::RedrawRequested(_) => { - let ui = imgui.frame(); + match event { + winit::event::Event::NewEvents(_) => { + let now = Instant::now(); + imgui.io_mut().update_delta_time(now - last_frame); + last_frame = now; + } + winit::event::Event::WindowEvent { + window_id, + event: WindowEvent::CloseRequested, + } if window_id == window.id() => { + window_target.exit(); + } + winit::event::Event::WindowEvent { + window_id, + event: WindowEvent::Resized(new_size), + } if window_id == window.id() => { + surface.resize( + &context, + NonZeroU32::new(new_size.width).unwrap(), + NonZeroU32::new(new_size.height).unwrap(), + ); + } + winit::event::Event::AboutToWait => { + window.request_redraw(); + } + winit::event::Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let ui = imgui.frame(); - ui.dockspace_over_main_viewport(); + ui.dockspace_over_main_viewport(); - ui.show_demo_window(&mut true); - ui.window("Style Editor").build(|| { - ui.show_default_style_editor(); - }); + ui.show_demo_window(&mut true); + ui.window("Style Editor").build(|| { + ui.show_default_style_editor(); + }); - ui.end_frame_early(); + ui.end_frame_early(); - renderer.prepare_render(&mut imgui, &window); + renderer.prepare_render(&mut imgui, &window); - imgui.update_platform_windows(); - renderer - .update_viewports(&mut imgui, window_target, &glow) - .expect("Failed to update viewports"); + imgui.update_platform_windows(); + renderer + .update_viewports(&mut imgui, window_target, &glow) + .expect("Failed to update viewports"); - let draw_data = imgui.render(); + let draw_data = imgui.render(); - if let Err(e) = context.make_current(&surface) { - // For some reason make_current randomly throws errors on windows. - // Until the reason for this is found, we just print it out instead of panicing. - eprintln!("Failed to make current: {e}"); - } + if let Err(e) = context.make_current(&surface) { + // For some reason make_current randomly throws errors on windows. + // Until the reason for this is found, we just print it out instead of panicing. + eprintln!("Failed to make current: {e}"); + } - unsafe { - glow.disable(glow::SCISSOR_TEST); - glow.clear(glow::COLOR_BUFFER_BIT); - } + unsafe { + glow.disable(glow::SCISSOR_TEST); + glow.clear(glow::COLOR_BUFFER_BIT); + } - renderer - .render(&window, &glow, draw_data) - .expect("Failed to render main viewport"); + renderer + .render(&window, &glow, draw_data) + .expect("Failed to render main viewport"); - surface - .swap_buffers(&context) - .expect("Failed to swap buffers"); + surface + .swap_buffers(&context) + .expect("Failed to swap buffers"); - renderer - .render_viewports(&glow, &mut imgui) - .expect("Failed to render viewports"); + renderer + .render_viewports(&glow, &mut imgui) + .expect("Failed to render viewports"); + } + _ => {} } - _ => {} - } - }); + }) + .expect("EventLoop error"); } diff --git a/imgui-winit-glow-renderer-viewports/src/lib.rs b/imgui-winit-glow-renderer-viewports/src/lib.rs index 51ba1b7ec..22b2c5b81 100644 --- a/imgui-winit-glow-renderer-viewports/src/lib.rs +++ b/imgui-winit-glow-renderer-viewports/src/lib.rs @@ -10,19 +10,23 @@ use std::{ use glow::HasContext; use glutin::{ config::ConfigTemplateBuilder, - context::{ContextAttributesBuilder, NotCurrentContext}, + context::{ + ContextAttributesBuilder, NotCurrentContext, NotCurrentGlContext, PossiblyCurrentGlContext, + }, display::GetGlDisplay, - prelude::{GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentGlContext}, + prelude::GlDisplay, surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface}, }; use glutin_winit::DisplayBuilder; -use imgui::{BackendFlags, ConfigFlags, Id, Key, MouseButton, ViewportFlags}; +use imgui::{BackendFlags, ConfigFlags, Id, Io, Key, MouseButton, ViewportFlags}; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use thiserror::Error; use winit::{ dpi::{PhysicalPosition, PhysicalSize}, - event::{DeviceEvent, ElementState, KeyboardInput, TouchPhase, VirtualKeyCode}, + event::{ElementState, TouchPhase}, event_loop::EventLoopWindowTarget, + keyboard::{Key as WinitKey, KeyLocation, NamedKey}, + platform::modifier_supplement::KeyEventExtModifierSupplement, window::{CursorIcon, Window, WindowBuilder}, }; @@ -438,163 +442,148 @@ impl Renderer { main_window: &Window, event: &winit::event::Event, ) { - match *event { - winit::event::Event::WindowEvent { - window_id, - ref event, - } => { - let (window, viewport) = if window_id == main_window.id() { - (main_window, imgui.main_viewport_mut()) - } else if let Some((id, wnd)) = - self.extra_windows.iter().find_map(|(id, (_, _, _, wnd))| { - if wnd.id() == window_id { - Some((*id, wnd)) - } else { - None - } - }) - { - if let Some(viewport) = imgui.viewport_by_id_mut(id) { - (wnd, viewport) + if let winit::event::Event::WindowEvent { + window_id, + ref event, + } = *event + { + let (window, viewport) = if window_id == main_window.id() { + (main_window, imgui.main_viewport_mut()) + } else if let Some((id, wnd)) = + self.extra_windows.iter().find_map(|(id, (_, _, _, wnd))| { + if wnd.id() == window_id { + Some((*id, wnd)) } else { - return; + None } + }) + { + if let Some(viewport) = imgui.viewport_by_id_mut(id) { + (wnd, viewport) } else { return; - }; + } + } else { + return; + }; - match *event { - winit::event::WindowEvent::Resized(new_size) => { - unsafe { - (*(viewport.platform_user_data.cast::())).size = - [new_size.width as f32, new_size.height as f32]; - } + match *event { + winit::event::WindowEvent::Resized(new_size) => { + unsafe { + (*(viewport.platform_user_data.cast::())).size = + [new_size.width as f32, new_size.height as f32]; + } - viewport.platform_request_resize = true; + viewport.platform_request_resize = true; - if window_id == main_window.id() { - imgui.io_mut().display_size = - [new_size.width as f32, new_size.height as f32]; - } - } - winit::event::WindowEvent::Moved(_) => unsafe { - let new_pos = window.inner_position().unwrap().cast::(); - (*(viewport.platform_user_data.cast::())).pos = - [new_pos.x, new_pos.y]; - - viewport.platform_request_move = true; - }, - winit::event::WindowEvent::CloseRequested if window_id != main_window.id() => { - viewport.platform_request_close = true; + if window_id == main_window.id() { + imgui.io_mut().display_size = + [new_size.width as f32, new_size.height as f32]; } - winit::event::WindowEvent::ReceivedCharacter(c) => { - imgui.io_mut().add_input_character(c); - } - winit::event::WindowEvent::Focused(f) => unsafe { - (*(viewport.platform_user_data.cast::())).focus = f; - }, - winit::event::WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(key), - state, - .. - }, - .. - } => { - let pressed = state == ElementState::Pressed; - - // We map both left and right ctrl to `ModCtrl`, etc. - // imgui is told both "left control is pressed" and - // "consider the control key is pressed". Allows - // applications to use either general "ctrl" or a - // specific key. Same applies to other modifiers. - // https://github.com/ocornut/imgui/issues/5047 - handle_key_modifier(imgui.io_mut(), key, pressed); - - // Add main key event - if let Some(key) = to_imgui_key(key) { - imgui.io_mut().add_key_event(key, pressed); + } + winit::event::WindowEvent::Moved(_) => unsafe { + let new_pos = window.inner_position().unwrap().cast::(); + (*(viewport.platform_user_data.cast::())).pos = + [new_pos.x, new_pos.y]; + + viewport.platform_request_move = true; + }, + winit::event::WindowEvent::CloseRequested if window_id != main_window.id() => { + viewport.platform_request_close = true; + } + winit::event::WindowEvent::Focused(f) => unsafe { + (*(viewport.platform_user_data.cast::())).focus = f; + }, + winit::event::WindowEvent::KeyboardInput { ref event, .. } => { + if let Some(txt) = &event.text { + for ch in txt.chars() { + imgui.io_mut().add_input_character(ch); } } - winit::event::WindowEvent::ModifiersChanged(modifiers) => { - imgui - .io_mut() - .add_key_event(Key::ModShift, modifiers.shift()); - imgui.io_mut().add_key_event(Key::ModCtrl, modifiers.ctrl()); - imgui.io_mut().add_key_event(Key::ModAlt, modifiers.alt()); + + let key = event.key_without_modifiers(); + + let pressed = event.state == ElementState::Pressed; + + // We map both left and right ctrl to `ModCtrl`, etc. + // imgui is told both "left control is pressed" and + // "consider the control key is pressed". Allows + // applications to use either general "ctrl" or a + // specific key. Same applies to other modifiers. + // https://github.com/ocornut/imgui/issues/5047 + handle_key_modifier(imgui.io_mut(), &key, pressed); + + // Add main key event + if let Some(key) = to_imgui_key(key, event.location) { + imgui.io_mut().add_key_event(key, pressed); + } + } + winit::event::WindowEvent::ModifiersChanged(modifiers) => { + let state = modifiers.state(); + + imgui + .io_mut() + .add_key_event(Key::ModShift, state.shift_key()); + imgui + .io_mut() + .add_key_event(Key::ModCtrl, state.control_key()); + imgui.io_mut().add_key_event(Key::ModAlt, state.alt_key()); + imgui + .io_mut() + .add_key_event(Key::ModSuper, state.super_key()); + } + winit::event::WindowEvent::CursorMoved { position, .. } => { + if imgui + .io() + .config_flags + .contains(ConfigFlags::VIEWPORTS_ENABLE) + { + let window_pos = window.inner_position().unwrap_or_default().cast::(); + imgui.io_mut().add_mouse_pos_event([ + position.x as f32 + window_pos.x, + position.y as f32 + window_pos.y, + ]); + } else { imgui .io_mut() - .add_key_event(Key::ModSuper, modifiers.logo()); + .add_mouse_pos_event([position.x as f32, position.y as f32]); + } + } + winit::event::WindowEvent::MouseWheel { + delta, + phase: TouchPhase::Moved, + .. + } => match delta { + winit::event::MouseScrollDelta::LineDelta(h, v) => { + imgui.io_mut().add_mouse_wheel_event([h, v]); } - winit::event::WindowEvent::CursorMoved { position, .. } => { - if imgui - .io() - .config_flags - .contains(ConfigFlags::VIEWPORTS_ENABLE) - { - let window_pos = - window.inner_position().unwrap_or_default().cast::(); - imgui.io_mut().add_mouse_pos_event([ - position.x as f32 + window_pos.x, - position.y as f32 + window_pos.y, - ]); + winit::event::MouseScrollDelta::PixelDelta(pos) => { + let h = if pos.x > 0.0 { + 1.0 + } else if pos.x < 0.0 { + -1.0 } else { - imgui - .io_mut() - .add_mouse_pos_event([position.x as f32, position.y as f32]); - } + 0.0 + }; + let v = if pos.y > 0.0 { + 1.0 + } else if pos.y < 0.0 { + -1.0 + } else { + 0.0 + }; + imgui.io_mut().add_mouse_wheel_event([h, v]); } - winit::event::WindowEvent::MouseWheel { - delta, - phase: TouchPhase::Moved, - .. - } => match delta { - winit::event::MouseScrollDelta::LineDelta(h, v) => { - imgui.io_mut().add_mouse_wheel_event([h, v]); - } - winit::event::MouseScrollDelta::PixelDelta(pos) => { - let h = if pos.x > 0.0 { - 1.0 - } else if pos.x < 0.0 { - -1.0 - } else { - 0.0 - }; - let v = if pos.y > 0.0 { - 1.0 - } else if pos.y < 0.0 { - -1.0 - } else { - 0.0 - }; - imgui.io_mut().add_mouse_wheel_event([h, v]); - } - }, - winit::event::WindowEvent::MouseInput { state, button, .. } => { - let state = state == ElementState::Pressed; + }, + winit::event::WindowEvent::MouseInput { state, button, .. } => { + let state = state == ElementState::Pressed; - if let Some(button) = to_imgui_mouse_button(button) { - imgui.io_mut().add_mouse_button_event(button, state); - } + if let Some(button) = to_imgui_mouse_button(button) { + imgui.io_mut().add_mouse_button_event(button, state); } - _ => {} - } - } - winit::event::Event::DeviceEvent { - event: - DeviceEvent::Key(KeyboardInput { - virtual_keycode: Some(key), - state: ElementState::Released, - .. - }), - .. - } => { - if let Some(key) = to_imgui_key(key) { - imgui.io_mut().add_key_event(key, false); } + _ => {} } - _ => {} } } @@ -630,7 +619,7 @@ impl Renderer { } ViewportEvent::SetSize(id, size) => { if let Some((_, _, _, wnd)) = self.extra_windows.get(&id) { - wnd.set_inner_size(PhysicalSize::new(size[0], size[1])); + _ = wnd.request_inner_size(PhysicalSize::new(size[0], size[1])); } } ViewportEvent::SetVisible(id) => { @@ -663,7 +652,7 @@ impl Renderer { imgui::MouseCursor::ResizeEW => winit::window::CursorIcon::EwResize, imgui::MouseCursor::ResizeNESW => winit::window::CursorIcon::NeswResize, imgui::MouseCursor::ResizeNWSE => winit::window::CursorIcon::NwseResize, - imgui::MouseCursor::Hand => winit::window::CursorIcon::Hand, + imgui::MouseCursor::Hand => winit::window::CursorIcon::Grab, imgui::MouseCursor::NotAllowed => winit::window::CursorIcon::NotAllowed, } } @@ -911,15 +900,13 @@ struct PlatformBackend { event_queue: Rc>>, } -fn handle_key_modifier(io: &mut imgui::Io, key: VirtualKeyCode, down: bool) { - if key == VirtualKeyCode::LShift || key == VirtualKeyCode::RShift { - io.add_key_event(imgui::Key::ModShift, down); - } else if key == VirtualKeyCode::LControl || key == VirtualKeyCode::RControl { - io.add_key_event(imgui::Key::ModCtrl, down); - } else if key == VirtualKeyCode::LAlt || key == VirtualKeyCode::RAlt { - io.add_key_event(imgui::Key::ModAlt, down); - } else if key == VirtualKeyCode::LWin || key == VirtualKeyCode::RWin { - io.add_key_event(imgui::Key::ModSuper, down); +fn handle_key_modifier(io: &mut Io, key: &WinitKey, down: bool) { + match key { + WinitKey::Named(NamedKey::Shift) => io.add_key_event(imgui::Key::ModShift, down), + WinitKey::Named(NamedKey::Control) => io.add_key_event(imgui::Key::ModCtrl, down), + WinitKey::Named(NamedKey::Alt) => io.add_key_event(imgui::Key::ModAlt, down), + WinitKey::Named(NamedKey::Super) => io.add_key_event(imgui::Key::ModSuper, down), + _ => {} } } @@ -1028,113 +1015,113 @@ impl imgui::RendererViewportBackend for RendererBackend { fn swap_buffers(&mut self, _viewport: &mut imgui::Viewport) {} } -fn to_imgui_key(keycode: VirtualKeyCode) -> Option { - match keycode { - VirtualKeyCode::Tab => Some(Key::Tab), - VirtualKeyCode::Left => Some(Key::LeftArrow), - VirtualKeyCode::Right => Some(Key::RightArrow), - VirtualKeyCode::Up => Some(Key::UpArrow), - VirtualKeyCode::Down => Some(Key::DownArrow), - VirtualKeyCode::PageUp => Some(Key::PageUp), - VirtualKeyCode::PageDown => Some(Key::PageDown), - VirtualKeyCode::Home => Some(Key::Home), - VirtualKeyCode::End => Some(Key::End), - VirtualKeyCode::Insert => Some(Key::Insert), - VirtualKeyCode::Delete => Some(Key::Delete), - VirtualKeyCode::Back => Some(Key::Backspace), - VirtualKeyCode::Space => Some(Key::Space), - VirtualKeyCode::Return => Some(Key::Enter), - VirtualKeyCode::Escape => Some(Key::Escape), - VirtualKeyCode::LControl => Some(Key::LeftCtrl), - VirtualKeyCode::LShift => Some(Key::LeftShift), - VirtualKeyCode::LAlt => Some(Key::LeftAlt), - VirtualKeyCode::LWin => Some(Key::LeftSuper), - VirtualKeyCode::RControl => Some(Key::RightCtrl), - VirtualKeyCode::RShift => Some(Key::RightShift), - VirtualKeyCode::RAlt => Some(Key::RightAlt), - VirtualKeyCode::RWin => Some(Key::RightSuper), - //VirtualKeyCode::Menu => Some(Key::Menu), // TODO: find out if there is a Menu key in winit - VirtualKeyCode::Key0 => Some(Key::Alpha0), - VirtualKeyCode::Key1 => Some(Key::Alpha1), - VirtualKeyCode::Key2 => Some(Key::Alpha2), - VirtualKeyCode::Key3 => Some(Key::Alpha3), - VirtualKeyCode::Key4 => Some(Key::Alpha4), - VirtualKeyCode::Key5 => Some(Key::Alpha5), - VirtualKeyCode::Key6 => Some(Key::Alpha6), - VirtualKeyCode::Key7 => Some(Key::Alpha7), - VirtualKeyCode::Key8 => Some(Key::Alpha8), - VirtualKeyCode::Key9 => Some(Key::Alpha9), - VirtualKeyCode::A => Some(Key::A), - VirtualKeyCode::B => Some(Key::B), - VirtualKeyCode::C => Some(Key::C), - VirtualKeyCode::D => Some(Key::D), - VirtualKeyCode::E => Some(Key::E), - VirtualKeyCode::F => Some(Key::F), - VirtualKeyCode::G => Some(Key::G), - VirtualKeyCode::H => Some(Key::H), - VirtualKeyCode::I => Some(Key::I), - VirtualKeyCode::J => Some(Key::J), - VirtualKeyCode::K => Some(Key::K), - VirtualKeyCode::L => Some(Key::L), - VirtualKeyCode::M => Some(Key::M), - VirtualKeyCode::N => Some(Key::N), - VirtualKeyCode::O => Some(Key::O), - VirtualKeyCode::P => Some(Key::P), - VirtualKeyCode::Q => Some(Key::Q), - VirtualKeyCode::R => Some(Key::R), - VirtualKeyCode::S => Some(Key::S), - VirtualKeyCode::T => Some(Key::T), - VirtualKeyCode::U => Some(Key::U), - VirtualKeyCode::V => Some(Key::V), - VirtualKeyCode::W => Some(Key::W), - VirtualKeyCode::X => Some(Key::X), - VirtualKeyCode::Y => Some(Key::Y), - VirtualKeyCode::Z => Some(Key::Z), - VirtualKeyCode::F1 => Some(Key::F1), - VirtualKeyCode::F2 => Some(Key::F2), - VirtualKeyCode::F3 => Some(Key::F3), - VirtualKeyCode::F4 => Some(Key::F4), - VirtualKeyCode::F5 => Some(Key::F5), - VirtualKeyCode::F6 => Some(Key::F6), - VirtualKeyCode::F7 => Some(Key::F7), - VirtualKeyCode::F8 => Some(Key::F8), - VirtualKeyCode::F9 => Some(Key::F9), - VirtualKeyCode::F10 => Some(Key::F10), - VirtualKeyCode::F11 => Some(Key::F11), - VirtualKeyCode::F12 => Some(Key::F12), - VirtualKeyCode::Apostrophe => Some(Key::Apostrophe), - VirtualKeyCode::Comma => Some(Key::Comma), - VirtualKeyCode::Minus => Some(Key::Minus), - VirtualKeyCode::Period => Some(Key::Period), - VirtualKeyCode::Slash => Some(Key::Slash), - VirtualKeyCode::Semicolon => Some(Key::Semicolon), - VirtualKeyCode::Equals => Some(Key::Equal), - VirtualKeyCode::LBracket => Some(Key::LeftBracket), - VirtualKeyCode::Backslash => Some(Key::Backslash), - VirtualKeyCode::RBracket => Some(Key::RightBracket), - VirtualKeyCode::Grave => Some(Key::GraveAccent), - VirtualKeyCode::Capital => Some(Key::CapsLock), - VirtualKeyCode::Scroll => Some(Key::ScrollLock), - VirtualKeyCode::Numlock => Some(Key::NumLock), - VirtualKeyCode::Snapshot => Some(Key::PrintScreen), - VirtualKeyCode::Pause => Some(Key::Pause), - VirtualKeyCode::Numpad0 => Some(Key::Keypad0), - VirtualKeyCode::Numpad1 => Some(Key::Keypad1), - VirtualKeyCode::Numpad2 => Some(Key::Keypad2), - VirtualKeyCode::Numpad3 => Some(Key::Keypad3), - VirtualKeyCode::Numpad4 => Some(Key::Keypad4), - VirtualKeyCode::Numpad5 => Some(Key::Keypad5), - VirtualKeyCode::Numpad6 => Some(Key::Keypad6), - VirtualKeyCode::Numpad7 => Some(Key::Keypad7), - VirtualKeyCode::Numpad8 => Some(Key::Keypad8), - VirtualKeyCode::Numpad9 => Some(Key::Keypad9), - VirtualKeyCode::NumpadDecimal => Some(Key::KeypadDecimal), - VirtualKeyCode::NumpadDivide => Some(Key::KeypadDivide), - VirtualKeyCode::NumpadMultiply => Some(Key::KeypadMultiply), - VirtualKeyCode::NumpadSubtract => Some(Key::KeypadSubtract), - VirtualKeyCode::NumpadAdd => Some(Key::KeypadAdd), - VirtualKeyCode::NumpadEnter => Some(Key::KeypadEnter), - VirtualKeyCode::NumpadEquals => Some(Key::KeypadEqual), +fn to_imgui_key(key: winit::keyboard::Key, location: KeyLocation) -> Option { + match (key.as_ref(), location) { + (WinitKey::Named(NamedKey::Tab), _) => Some(Key::Tab), + (WinitKey::Named(NamedKey::ArrowLeft), _) => Some(Key::LeftArrow), + (WinitKey::Named(NamedKey::ArrowRight), _) => Some(Key::RightArrow), + (WinitKey::Named(NamedKey::ArrowUp), _) => Some(Key::UpArrow), + (WinitKey::Named(NamedKey::ArrowDown), _) => Some(Key::DownArrow), + (WinitKey::Named(NamedKey::PageUp), _) => Some(Key::PageUp), + (WinitKey::Named(NamedKey::PageDown), _) => Some(Key::PageDown), + (WinitKey::Named(NamedKey::Home), _) => Some(Key::Home), + (WinitKey::Named(NamedKey::End), _) => Some(Key::End), + (WinitKey::Named(NamedKey::Insert), _) => Some(Key::Insert), + (WinitKey::Named(NamedKey::Delete), _) => Some(Key::Delete), + (WinitKey::Named(NamedKey::Backspace), _) => Some(Key::Backspace), + (WinitKey::Named(NamedKey::Space), _) => Some(Key::Space), + (WinitKey::Named(NamedKey::Enter), KeyLocation::Standard) => Some(Key::Enter), + (WinitKey::Named(NamedKey::Enter), KeyLocation::Numpad) => Some(Key::KeypadEnter), + (WinitKey::Named(NamedKey::Escape), _) => Some(Key::Escape), + (WinitKey::Named(NamedKey::Control), KeyLocation::Left) => Some(Key::LeftCtrl), + (WinitKey::Named(NamedKey::Control), KeyLocation::Right) => Some(Key::RightCtrl), + (WinitKey::Named(NamedKey::Shift), KeyLocation::Left) => Some(Key::LeftShift), + (WinitKey::Named(NamedKey::Shift), KeyLocation::Right) => Some(Key::RightShift), + (WinitKey::Named(NamedKey::Alt), KeyLocation::Left) => Some(Key::LeftAlt), + (WinitKey::Named(NamedKey::Alt), KeyLocation::Right) => Some(Key::RightAlt), + (WinitKey::Named(NamedKey::Super), KeyLocation::Left) => Some(Key::LeftSuper), + (WinitKey::Named(NamedKey::Super), KeyLocation::Right) => Some(Key::RightSuper), + (WinitKey::Named(NamedKey::ContextMenu), _) => Some(Key::Menu), + (WinitKey::Named(NamedKey::F1), _) => Some(Key::F1), + (WinitKey::Named(NamedKey::F2), _) => Some(Key::F2), + (WinitKey::Named(NamedKey::F3), _) => Some(Key::F3), + (WinitKey::Named(NamedKey::F4), _) => Some(Key::F4), + (WinitKey::Named(NamedKey::F5), _) => Some(Key::F5), + (WinitKey::Named(NamedKey::F6), _) => Some(Key::F6), + (WinitKey::Named(NamedKey::F7), _) => Some(Key::F7), + (WinitKey::Named(NamedKey::F8), _) => Some(Key::F8), + (WinitKey::Named(NamedKey::F9), _) => Some(Key::F9), + (WinitKey::Named(NamedKey::F10), _) => Some(Key::F10), + (WinitKey::Named(NamedKey::F11), _) => Some(Key::F11), + (WinitKey::Named(NamedKey::F12), _) => Some(Key::F12), + (WinitKey::Named(NamedKey::CapsLock), _) => Some(Key::CapsLock), + (WinitKey::Named(NamedKey::ScrollLock), _) => Some(Key::ScrollLock), + (WinitKey::Named(NamedKey::NumLock), _) => Some(Key::NumLock), + (WinitKey::Named(NamedKey::PrintScreen), _) => Some(Key::PrintScreen), + (WinitKey::Named(NamedKey::Pause), _) => Some(Key::Pause), + (WinitKey::Character("0"), KeyLocation::Standard) => Some(Key::Alpha0), + (WinitKey::Character("1"), KeyLocation::Standard) => Some(Key::Alpha1), + (WinitKey::Character("2"), KeyLocation::Standard) => Some(Key::Alpha2), + (WinitKey::Character("3"), KeyLocation::Standard) => Some(Key::Alpha3), + (WinitKey::Character("4"), KeyLocation::Standard) => Some(Key::Alpha4), + (WinitKey::Character("5"), KeyLocation::Standard) => Some(Key::Alpha5), + (WinitKey::Character("6"), KeyLocation::Standard) => Some(Key::Alpha6), + (WinitKey::Character("7"), KeyLocation::Standard) => Some(Key::Alpha7), + (WinitKey::Character("8"), KeyLocation::Standard) => Some(Key::Alpha8), + (WinitKey::Character("9"), KeyLocation::Standard) => Some(Key::Alpha9), + (WinitKey::Character("0"), KeyLocation::Numpad) => Some(Key::Keypad0), + (WinitKey::Character("1"), KeyLocation::Numpad) => Some(Key::Keypad1), + (WinitKey::Character("2"), KeyLocation::Numpad) => Some(Key::Keypad2), + (WinitKey::Character("3"), KeyLocation::Numpad) => Some(Key::Keypad3), + (WinitKey::Character("4"), KeyLocation::Numpad) => Some(Key::Keypad4), + (WinitKey::Character("5"), KeyLocation::Numpad) => Some(Key::Keypad5), + (WinitKey::Character("6"), KeyLocation::Numpad) => Some(Key::Keypad6), + (WinitKey::Character("7"), KeyLocation::Numpad) => Some(Key::Keypad7), + (WinitKey::Character("8"), KeyLocation::Numpad) => Some(Key::Keypad8), + (WinitKey::Character("9"), KeyLocation::Numpad) => Some(Key::Keypad9), + (WinitKey::Character("a"), _) => Some(Key::A), + (WinitKey::Character("b"), _) => Some(Key::B), + (WinitKey::Character("c"), _) => Some(Key::C), + (WinitKey::Character("d"), _) => Some(Key::D), + (WinitKey::Character("e"), _) => Some(Key::E), + (WinitKey::Character("f"), _) => Some(Key::F), + (WinitKey::Character("g"), _) => Some(Key::G), + (WinitKey::Character("h"), _) => Some(Key::H), + (WinitKey::Character("i"), _) => Some(Key::I), + (WinitKey::Character("j"), _) => Some(Key::J), + (WinitKey::Character("k"), _) => Some(Key::K), + (WinitKey::Character("l"), _) => Some(Key::L), + (WinitKey::Character("m"), _) => Some(Key::M), + (WinitKey::Character("n"), _) => Some(Key::N), + (WinitKey::Character("o"), _) => Some(Key::O), + (WinitKey::Character("p"), _) => Some(Key::P), + (WinitKey::Character("q"), _) => Some(Key::Q), + (WinitKey::Character("r"), _) => Some(Key::R), + (WinitKey::Character("s"), _) => Some(Key::S), + (WinitKey::Character("t"), _) => Some(Key::T), + (WinitKey::Character("u"), _) => Some(Key::U), + (WinitKey::Character("v"), _) => Some(Key::V), + (WinitKey::Character("w"), _) => Some(Key::W), + (WinitKey::Character("x"), _) => Some(Key::X), + (WinitKey::Character("y"), _) => Some(Key::Y), + (WinitKey::Character("z"), _) => Some(Key::Z), + (WinitKey::Character("'"), _) => Some(Key::Apostrophe), + (WinitKey::Character(","), KeyLocation::Standard) => Some(Key::Comma), + (WinitKey::Character("-"), KeyLocation::Standard) => Some(Key::Minus), + (WinitKey::Character("-"), KeyLocation::Numpad) => Some(Key::KeypadSubtract), + (WinitKey::Character("."), KeyLocation::Standard) => Some(Key::Period), + (WinitKey::Character("."), KeyLocation::Numpad) => Some(Key::KeypadDecimal), + (WinitKey::Character("/"), KeyLocation::Standard) => Some(Key::Slash), + (WinitKey::Character("/"), KeyLocation::Numpad) => Some(Key::KeypadDivide), + (WinitKey::Character(";"), _) => Some(Key::Semicolon), + (WinitKey::Character("="), KeyLocation::Standard) => Some(Key::Equal), + (WinitKey::Character("="), KeyLocation::Numpad) => Some(Key::KeypadEqual), + (WinitKey::Character("["), _) => Some(Key::LeftBracket), + (WinitKey::Character("\\"), _) => Some(Key::Backslash), + (WinitKey::Character("]"), _) => Some(Key::RightBracket), + (WinitKey::Character("`"), _) => Some(Key::GraveAccent), + (WinitKey::Character("*"), KeyLocation::Numpad) => Some(Key::KeypadMultiply), + (WinitKey::Character("+"), KeyLocation::Numpad) => Some(Key::KeypadAdd), _ => None, } } diff --git a/imgui-winit-support/Cargo.toml b/imgui-winit-support/Cargo.toml index 8175d5fe9..dba0b9108 100644 --- a/imgui-winit-support/Cargo.toml +++ b/imgui-winit-support/Cargo.toml @@ -11,4 +11,4 @@ categories = ["gui"] [dependencies] imgui = { version = "0.11.0", path = "../imgui" } -winit = { version = "0.27.2", default-features = false } +winit = { version = "0.29.3", default-features = false } diff --git a/imgui-winit-support/src/lib.rs b/imgui-winit-support/src/lib.rs index 47806ccee..1f5c03967 100644 --- a/imgui-winit-support/src/lib.rs +++ b/imgui-winit-support/src/lib.rs @@ -23,7 +23,7 @@ //! use winit::event_loop::{ControlFlow, EventLoop}; //! use winit::window::Window; //! -//! let mut event_loop = EventLoop::new(); +//! let mut event_loop = EventLoop::new().expect("Failed to create EventLoop"); //! let mut window = Window::new(&event_loop).unwrap(); //! //! let mut imgui = Context::create(); @@ -34,7 +34,7 @@ //! //! let mut last_frame = Instant::now(); //! let mut run = true; -//! event_loop.run(move |event, _, control_flow| { +//! event_loop.run(move |event, window_target| { //! match event { //! Event::NewEvents(_) => { //! // other application-specific logic @@ -42,13 +42,13 @@ //! imgui.io_mut().update_delta_time(now - last_frame); //! last_frame = now; //! }, -//! Event::MainEventsCleared => { +//! Event::AboutToWait => { //! // other application-specific logic //! platform.prepare_frame(imgui.io_mut(), &window) // step 4 //! .expect("Failed to prepare frame"); //! window.request_redraw(); //! } -//! Event::RedrawRequested(_) => { +//! Event::WindowEvent { event: WindowEvent::RedrawRequested, .. } => { //! let ui = imgui.frame(); //! // application-specific rendering *under the UI* //! @@ -62,7 +62,7 @@ //! // application-specific rendering *over the UI* //! }, //! Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { -//! *control_flow = ControlFlow::Exit; +//! window_target.exit(); //! } //! // other application-specific event handling //! event => { @@ -70,7 +70,7 @@ //! // other application-specific event handling //! } //! } -//! }) +//! }).expect("EventLoop error"); //! ``` use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui}; @@ -78,14 +78,15 @@ use std::cmp::Ordering; // Re-export winit to make it easier for users to use the correct version. pub use winit; -use winit::dpi::{LogicalPosition, LogicalSize}; +use winit::{ + dpi::{LogicalPosition, LogicalSize}, + keyboard::{Key as WinitKey, KeyLocation, NamedKey}, + platform::modifier_supplement::KeyEventExtModifierSupplement, +}; use winit::{ error::ExternalError, - event::{ - DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase, - VirtualKeyCode, WindowEvent, - }, + event::{ElementState, Event, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent}, window::{CursorIcon as MouseCursor, Window}, }; @@ -112,7 +113,7 @@ fn to_winit_cursor(cursor: imgui::MouseCursor) -> MouseCursor { imgui::MouseCursor::ResizeEW => MouseCursor::EwResize, imgui::MouseCursor::ResizeNESW => MouseCursor::NeswResize, imgui::MouseCursor::ResizeNWSE => MouseCursor::NwseResize, - imgui::MouseCursor::Hand => MouseCursor::Hand, + imgui::MouseCursor::Hand => MouseCursor::Grab, imgui::MouseCursor::NotAllowed => MouseCursor::NotAllowed, } } @@ -180,126 +181,124 @@ fn to_imgui_mouse_button(button: MouseButton) -> Option { } } -fn to_imgui_key(keycode: VirtualKeyCode) -> Option { - match keycode { - VirtualKeyCode::Tab => Some(Key::Tab), - VirtualKeyCode::Left => Some(Key::LeftArrow), - VirtualKeyCode::Right => Some(Key::RightArrow), - VirtualKeyCode::Up => Some(Key::UpArrow), - VirtualKeyCode::Down => Some(Key::DownArrow), - VirtualKeyCode::PageUp => Some(Key::PageUp), - VirtualKeyCode::PageDown => Some(Key::PageDown), - VirtualKeyCode::Home => Some(Key::Home), - VirtualKeyCode::End => Some(Key::End), - VirtualKeyCode::Insert => Some(Key::Insert), - VirtualKeyCode::Delete => Some(Key::Delete), - VirtualKeyCode::Back => Some(Key::Backspace), - VirtualKeyCode::Space => Some(Key::Space), - VirtualKeyCode::Return => Some(Key::Enter), - VirtualKeyCode::Escape => Some(Key::Escape), - VirtualKeyCode::LControl => Some(Key::LeftCtrl), - VirtualKeyCode::LShift => Some(Key::LeftShift), - VirtualKeyCode::LAlt => Some(Key::LeftAlt), - VirtualKeyCode::LWin => Some(Key::LeftSuper), - VirtualKeyCode::RControl => Some(Key::RightCtrl), - VirtualKeyCode::RShift => Some(Key::RightShift), - VirtualKeyCode::RAlt => Some(Key::RightAlt), - VirtualKeyCode::RWin => Some(Key::RightSuper), - //VirtualKeyCode::Menu => Some(Key::Menu), // TODO: find out if there is a Menu key in winit - VirtualKeyCode::Key0 => Some(Key::Alpha0), - VirtualKeyCode::Key1 => Some(Key::Alpha1), - VirtualKeyCode::Key2 => Some(Key::Alpha2), - VirtualKeyCode::Key3 => Some(Key::Alpha3), - VirtualKeyCode::Key4 => Some(Key::Alpha4), - VirtualKeyCode::Key5 => Some(Key::Alpha5), - VirtualKeyCode::Key6 => Some(Key::Alpha6), - VirtualKeyCode::Key7 => Some(Key::Alpha7), - VirtualKeyCode::Key8 => Some(Key::Alpha8), - VirtualKeyCode::Key9 => Some(Key::Alpha9), - VirtualKeyCode::A => Some(Key::A), - VirtualKeyCode::B => Some(Key::B), - VirtualKeyCode::C => Some(Key::C), - VirtualKeyCode::D => Some(Key::D), - VirtualKeyCode::E => Some(Key::E), - VirtualKeyCode::F => Some(Key::F), - VirtualKeyCode::G => Some(Key::G), - VirtualKeyCode::H => Some(Key::H), - VirtualKeyCode::I => Some(Key::I), - VirtualKeyCode::J => Some(Key::J), - VirtualKeyCode::K => Some(Key::K), - VirtualKeyCode::L => Some(Key::L), - VirtualKeyCode::M => Some(Key::M), - VirtualKeyCode::N => Some(Key::N), - VirtualKeyCode::O => Some(Key::O), - VirtualKeyCode::P => Some(Key::P), - VirtualKeyCode::Q => Some(Key::Q), - VirtualKeyCode::R => Some(Key::R), - VirtualKeyCode::S => Some(Key::S), - VirtualKeyCode::T => Some(Key::T), - VirtualKeyCode::U => Some(Key::U), - VirtualKeyCode::V => Some(Key::V), - VirtualKeyCode::W => Some(Key::W), - VirtualKeyCode::X => Some(Key::X), - VirtualKeyCode::Y => Some(Key::Y), - VirtualKeyCode::Z => Some(Key::Z), - VirtualKeyCode::F1 => Some(Key::F1), - VirtualKeyCode::F2 => Some(Key::F2), - VirtualKeyCode::F3 => Some(Key::F3), - VirtualKeyCode::F4 => Some(Key::F4), - VirtualKeyCode::F5 => Some(Key::F5), - VirtualKeyCode::F6 => Some(Key::F6), - VirtualKeyCode::F7 => Some(Key::F7), - VirtualKeyCode::F8 => Some(Key::F8), - VirtualKeyCode::F9 => Some(Key::F9), - VirtualKeyCode::F10 => Some(Key::F10), - VirtualKeyCode::F11 => Some(Key::F11), - VirtualKeyCode::F12 => Some(Key::F12), - VirtualKeyCode::Apostrophe => Some(Key::Apostrophe), - VirtualKeyCode::Comma => Some(Key::Comma), - VirtualKeyCode::Minus => Some(Key::Minus), - VirtualKeyCode::Period => Some(Key::Period), - VirtualKeyCode::Slash => Some(Key::Slash), - VirtualKeyCode::Semicolon => Some(Key::Semicolon), - VirtualKeyCode::Equals => Some(Key::Equal), - VirtualKeyCode::LBracket => Some(Key::LeftBracket), - VirtualKeyCode::Backslash => Some(Key::Backslash), - VirtualKeyCode::RBracket => Some(Key::RightBracket), - VirtualKeyCode::Grave => Some(Key::GraveAccent), - VirtualKeyCode::Capital => Some(Key::CapsLock), - VirtualKeyCode::Scroll => Some(Key::ScrollLock), - VirtualKeyCode::Numlock => Some(Key::NumLock), - VirtualKeyCode::Snapshot => Some(Key::PrintScreen), - VirtualKeyCode::Pause => Some(Key::Pause), - VirtualKeyCode::Numpad0 => Some(Key::Keypad0), - VirtualKeyCode::Numpad1 => Some(Key::Keypad1), - VirtualKeyCode::Numpad2 => Some(Key::Keypad2), - VirtualKeyCode::Numpad3 => Some(Key::Keypad3), - VirtualKeyCode::Numpad4 => Some(Key::Keypad4), - VirtualKeyCode::Numpad5 => Some(Key::Keypad5), - VirtualKeyCode::Numpad6 => Some(Key::Keypad6), - VirtualKeyCode::Numpad7 => Some(Key::Keypad7), - VirtualKeyCode::Numpad8 => Some(Key::Keypad8), - VirtualKeyCode::Numpad9 => Some(Key::Keypad9), - VirtualKeyCode::NumpadDecimal => Some(Key::KeypadDecimal), - VirtualKeyCode::NumpadDivide => Some(Key::KeypadDivide), - VirtualKeyCode::NumpadMultiply => Some(Key::KeypadMultiply), - VirtualKeyCode::NumpadSubtract => Some(Key::KeypadSubtract), - VirtualKeyCode::NumpadAdd => Some(Key::KeypadAdd), - VirtualKeyCode::NumpadEnter => Some(Key::KeypadEnter), - VirtualKeyCode::NumpadEquals => Some(Key::KeypadEqual), +fn to_imgui_key(key: winit::keyboard::Key, location: KeyLocation) -> Option { + match (key.as_ref(), location) { + (WinitKey::Named(NamedKey::Tab), _) => Some(Key::Tab), + (WinitKey::Named(NamedKey::ArrowLeft), _) => Some(Key::LeftArrow), + (WinitKey::Named(NamedKey::ArrowRight), _) => Some(Key::RightArrow), + (WinitKey::Named(NamedKey::ArrowUp), _) => Some(Key::UpArrow), + (WinitKey::Named(NamedKey::ArrowDown), _) => Some(Key::DownArrow), + (WinitKey::Named(NamedKey::PageUp), _) => Some(Key::PageUp), + (WinitKey::Named(NamedKey::PageDown), _) => Some(Key::PageDown), + (WinitKey::Named(NamedKey::Home), _) => Some(Key::Home), + (WinitKey::Named(NamedKey::End), _) => Some(Key::End), + (WinitKey::Named(NamedKey::Insert), _) => Some(Key::Insert), + (WinitKey::Named(NamedKey::Delete), _) => Some(Key::Delete), + (WinitKey::Named(NamedKey::Backspace), _) => Some(Key::Backspace), + (WinitKey::Named(NamedKey::Space), _) => Some(Key::Space), + (WinitKey::Named(NamedKey::Enter), KeyLocation::Standard) => Some(Key::Enter), + (WinitKey::Named(NamedKey::Enter), KeyLocation::Numpad) => Some(Key::KeypadEnter), + (WinitKey::Named(NamedKey::Escape), _) => Some(Key::Escape), + (WinitKey::Named(NamedKey::Control), KeyLocation::Left) => Some(Key::LeftCtrl), + (WinitKey::Named(NamedKey::Control), KeyLocation::Right) => Some(Key::RightCtrl), + (WinitKey::Named(NamedKey::Shift), KeyLocation::Left) => Some(Key::LeftShift), + (WinitKey::Named(NamedKey::Shift), KeyLocation::Right) => Some(Key::RightShift), + (WinitKey::Named(NamedKey::Alt), KeyLocation::Left) => Some(Key::LeftAlt), + (WinitKey::Named(NamedKey::Alt), KeyLocation::Right) => Some(Key::RightAlt), + (WinitKey::Named(NamedKey::Super), KeyLocation::Left) => Some(Key::LeftSuper), + (WinitKey::Named(NamedKey::Super), KeyLocation::Right) => Some(Key::RightSuper), + (WinitKey::Named(NamedKey::ContextMenu), _) => Some(Key::Menu), + (WinitKey::Named(NamedKey::F1), _) => Some(Key::F1), + (WinitKey::Named(NamedKey::F2), _) => Some(Key::F2), + (WinitKey::Named(NamedKey::F3), _) => Some(Key::F3), + (WinitKey::Named(NamedKey::F4), _) => Some(Key::F4), + (WinitKey::Named(NamedKey::F5), _) => Some(Key::F5), + (WinitKey::Named(NamedKey::F6), _) => Some(Key::F6), + (WinitKey::Named(NamedKey::F7), _) => Some(Key::F7), + (WinitKey::Named(NamedKey::F8), _) => Some(Key::F8), + (WinitKey::Named(NamedKey::F9), _) => Some(Key::F9), + (WinitKey::Named(NamedKey::F10), _) => Some(Key::F10), + (WinitKey::Named(NamedKey::F11), _) => Some(Key::F11), + (WinitKey::Named(NamedKey::F12), _) => Some(Key::F12), + (WinitKey::Named(NamedKey::CapsLock), _) => Some(Key::CapsLock), + (WinitKey::Named(NamedKey::ScrollLock), _) => Some(Key::ScrollLock), + (WinitKey::Named(NamedKey::NumLock), _) => Some(Key::NumLock), + (WinitKey::Named(NamedKey::PrintScreen), _) => Some(Key::PrintScreen), + (WinitKey::Named(NamedKey::Pause), _) => Some(Key::Pause), + (WinitKey::Character("0"), KeyLocation::Standard) => Some(Key::Alpha0), + (WinitKey::Character("1"), KeyLocation::Standard) => Some(Key::Alpha1), + (WinitKey::Character("2"), KeyLocation::Standard) => Some(Key::Alpha2), + (WinitKey::Character("3"), KeyLocation::Standard) => Some(Key::Alpha3), + (WinitKey::Character("4"), KeyLocation::Standard) => Some(Key::Alpha4), + (WinitKey::Character("5"), KeyLocation::Standard) => Some(Key::Alpha5), + (WinitKey::Character("6"), KeyLocation::Standard) => Some(Key::Alpha6), + (WinitKey::Character("7"), KeyLocation::Standard) => Some(Key::Alpha7), + (WinitKey::Character("8"), KeyLocation::Standard) => Some(Key::Alpha8), + (WinitKey::Character("9"), KeyLocation::Standard) => Some(Key::Alpha9), + (WinitKey::Character("0"), KeyLocation::Numpad) => Some(Key::Keypad0), + (WinitKey::Character("1"), KeyLocation::Numpad) => Some(Key::Keypad1), + (WinitKey::Character("2"), KeyLocation::Numpad) => Some(Key::Keypad2), + (WinitKey::Character("3"), KeyLocation::Numpad) => Some(Key::Keypad3), + (WinitKey::Character("4"), KeyLocation::Numpad) => Some(Key::Keypad4), + (WinitKey::Character("5"), KeyLocation::Numpad) => Some(Key::Keypad5), + (WinitKey::Character("6"), KeyLocation::Numpad) => Some(Key::Keypad6), + (WinitKey::Character("7"), KeyLocation::Numpad) => Some(Key::Keypad7), + (WinitKey::Character("8"), KeyLocation::Numpad) => Some(Key::Keypad8), + (WinitKey::Character("9"), KeyLocation::Numpad) => Some(Key::Keypad9), + (WinitKey::Character("a"), _) => Some(Key::A), + (WinitKey::Character("b"), _) => Some(Key::B), + (WinitKey::Character("c"), _) => Some(Key::C), + (WinitKey::Character("d"), _) => Some(Key::D), + (WinitKey::Character("e"), _) => Some(Key::E), + (WinitKey::Character("f"), _) => Some(Key::F), + (WinitKey::Character("g"), _) => Some(Key::G), + (WinitKey::Character("h"), _) => Some(Key::H), + (WinitKey::Character("i"), _) => Some(Key::I), + (WinitKey::Character("j"), _) => Some(Key::J), + (WinitKey::Character("k"), _) => Some(Key::K), + (WinitKey::Character("l"), _) => Some(Key::L), + (WinitKey::Character("m"), _) => Some(Key::M), + (WinitKey::Character("n"), _) => Some(Key::N), + (WinitKey::Character("o"), _) => Some(Key::O), + (WinitKey::Character("p"), _) => Some(Key::P), + (WinitKey::Character("q"), _) => Some(Key::Q), + (WinitKey::Character("r"), _) => Some(Key::R), + (WinitKey::Character("s"), _) => Some(Key::S), + (WinitKey::Character("t"), _) => Some(Key::T), + (WinitKey::Character("u"), _) => Some(Key::U), + (WinitKey::Character("v"), _) => Some(Key::V), + (WinitKey::Character("w"), _) => Some(Key::W), + (WinitKey::Character("x"), _) => Some(Key::X), + (WinitKey::Character("y"), _) => Some(Key::Y), + (WinitKey::Character("z"), _) => Some(Key::Z), + (WinitKey::Character("'"), _) => Some(Key::Apostrophe), + (WinitKey::Character(","), KeyLocation::Standard) => Some(Key::Comma), + (WinitKey::Character("-"), KeyLocation::Standard) => Some(Key::Minus), + (WinitKey::Character("-"), KeyLocation::Numpad) => Some(Key::KeypadSubtract), + (WinitKey::Character("."), KeyLocation::Standard) => Some(Key::Period), + (WinitKey::Character("."), KeyLocation::Numpad) => Some(Key::KeypadDecimal), + (WinitKey::Character("/"), KeyLocation::Standard) => Some(Key::Slash), + (WinitKey::Character("/"), KeyLocation::Numpad) => Some(Key::KeypadDivide), + (WinitKey::Character(";"), _) => Some(Key::Semicolon), + (WinitKey::Character("="), KeyLocation::Standard) => Some(Key::Equal), + (WinitKey::Character("="), KeyLocation::Numpad) => Some(Key::KeypadEqual), + (WinitKey::Character("["), _) => Some(Key::LeftBracket), + (WinitKey::Character("\\"), _) => Some(Key::Backslash), + (WinitKey::Character("]"), _) => Some(Key::RightBracket), + (WinitKey::Character("`"), _) => Some(Key::GraveAccent), + (WinitKey::Character("*"), KeyLocation::Numpad) => Some(Key::KeypadMultiply), + (WinitKey::Character("+"), KeyLocation::Numpad) => Some(Key::KeypadAdd), _ => None, } } -fn handle_key_modifier(io: &mut Io, key: VirtualKeyCode, down: bool) { - if key == VirtualKeyCode::LShift || key == VirtualKeyCode::RShift { - io.add_key_event(imgui::Key::ModShift, down); - } else if key == VirtualKeyCode::LControl || key == VirtualKeyCode::RControl { - io.add_key_event(imgui::Key::ModCtrl, down); - } else if key == VirtualKeyCode::LAlt || key == VirtualKeyCode::RAlt { - io.add_key_event(imgui::Key::ModAlt, down); - } else if key == VirtualKeyCode::LWin || key == VirtualKeyCode::RWin { - io.add_key_event(imgui::Key::ModSuper, down); +fn handle_key_modifier(io: &mut Io, key: &WinitKey, down: bool) { + match key { + WinitKey::Named(NamedKey::Shift) => io.add_key_event(imgui::Key::ModShift, down), + WinitKey::Named(NamedKey::Control) => io.add_key_event(imgui::Key::ModCtrl, down), + WinitKey::Named(NamedKey::Alt) => io.add_key_event(imgui::Key::ModAlt, down), + WinitKey::Named(NamedKey::Super) => io.add_key_event(imgui::Key::ModSuper, down), + _ => {} } } @@ -411,19 +410,18 @@ impl WinitPlatform { } // Track key release events outside our window. If we don't do this, // we might never see the release event if some other window gets focus. - Event::DeviceEvent { - event: - DeviceEvent::Key(KeyboardInput { - state: ElementState::Released, - virtual_keycode: Some(key), - .. - }), - .. - } => { - if let Some(key) = to_imgui_key(key) { - io.add_key_event(key, false); - } - } + // Event::DeviceEvent { + // event: + // DeviceEvent::Key(RawKeyEvent { + // physical_key, + // state: ElementState::Released, + // }), + // .. + // } => { + // if let Some(key) = to_imgui_key(key) { + // io.add_key_event(key, false); + // } + // } _ => (), } } @@ -456,24 +454,26 @@ impl WinitPlatform { io.display_size = [logical_size.width as f32, logical_size.height as f32]; } WindowEvent::ModifiersChanged(modifiers) => { + let state = modifiers.state(); // We need to track modifiers separately because some system like macOS, will // not reliably send modifier states during certain events like ScreenCapture. // Gotta let the people show off their pretty imgui widgets! - io.add_key_event(Key::ModShift, modifiers.shift()); - io.add_key_event(Key::ModCtrl, modifiers.ctrl()); - io.add_key_event(Key::ModAlt, modifiers.alt()); - io.add_key_event(Key::ModSuper, modifiers.logo()); + io.add_key_event(Key::ModShift, state.shift_key()); + io.add_key_event(Key::ModCtrl, state.control_key()); + io.add_key_event(Key::ModAlt, state.alt_key()); + io.add_key_event(Key::ModSuper, state.super_key()); } - WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(key), - state, - .. - }, - .. - } => { - let pressed = state == ElementState::Pressed; + WindowEvent::KeyboardInput { ref event, .. } => { + if let Some(txt) = &event.text { + for ch in txt.chars() { + if ch != '\u{7f}' { + io.add_input_character(ch) + } + } + } + + let key = event.key_without_modifiers(); + let pressed = event.state == ElementState::Pressed; // We map both left and right ctrl to `ModCtrl`, etc. // imgui is told both "left control is pressed" and @@ -481,20 +481,15 @@ impl WinitPlatform { // applications to use either general "ctrl" or a // specific key. Same applies to other modifiers. // https://github.com/ocornut/imgui/issues/5047 - handle_key_modifier(io, key, pressed); + handle_key_modifier(io, &key, pressed); + + println!("KEY EVENT: {event:?}"); // Add main key event - if let Some(key) = to_imgui_key(key) { + if let Some(key) = to_imgui_key(key, event.location) { io.add_key_event(key, pressed); } } - WindowEvent::ReceivedCharacter(ch) => { - // Exclude the backspace key ('\u{7f}'). Otherwise we will insert this char and then - // delete it. - if ch != '\u{7f}' { - io.add_input_character(ch) - } - } WindowEvent::CursorMoved { position, .. } => { let position = position.to_logical(window.scale_factor()); let position = self.scale_pos_from_winit(window, position);