Repository: glium/glium (language: rust)

Issue:
No way to dynamically open new windows?
Currently `Display::new` takes a `&EventLoop` instead of a `&EventLoopWindowTarget`. It seems like this means that there is no way to create new `Display`'s after `EventLoop::run` is called, and thus there is no way to dynamically open new windows. Since `Display::new` only needs the event_loop to call `ContextBuilder::build_windowed` it should be possible for `Display::new` to take a `&EventLoopWindowTarget`.


Discussion / hints:

Fix patch:
diff --git a/examples/multiple_windows.rs b/examples/multiple_windows.rs
new file mode 100644
index 0000000000..968ba192e3
--- /dev/null
+++ b/examples/multiple_windows.rs
@@ -0,0 +1,69 @@
+use glium::glutin::{window::WindowBuilder, ContextBuilder};
+use glium::glutin::event_loop::{EventLoop, ControlFlow};
+use glium::glutin::event::{Event, WindowEvent, ElementState, MouseButton};
+use glium::{Display, Surface};
+
+use std::collections::HashMap;
+
+// This example shows how to dynamically open new windows.
+
+fn main() {
+    let event_loop = EventLoop::new();
+
+    let wb = WindowBuilder::new()
+        .with_title("Test main");
+
+    let cb = ContextBuilder::new();
+
+    let display = Display::new(wb, cb, &event_loop).unwrap();
+
+    let mut counter = 0;
+    let mut extra_windows = HashMap::new();
+
+    event_loop.run(move |ev, event_loop, cf| {
+        match ev {
+            Event::WindowEvent { event: WindowEvent::CloseRequested, window_id } => {
+                if window_id == display.gl_window().window().id() {
+                    // Close the application when main window is closed
+                    *cf = ControlFlow::Exit;
+                } else {
+                    // For other windows we only close the specified window
+                    extra_windows.remove(&window_id);
+                }
+            }
+            // Clicking on the main window spawns new windows
+            Event::WindowEvent { event: WindowEvent::MouseInput {
+                state: ElementState::Released,
+                button: MouseButton::Left,
+                ..
+            }, window_id } if window_id == display.gl_window().window().id() => {
+                counter += 1;
+
+                let wb = WindowBuilder::new()
+                    .with_title(&format!("Test {}", counter));
+
+                let cb = ContextBuilder::new();
+
+                let extra_display = Display::new(wb, cb, &event_loop).unwrap();
+
+                let id = extra_display.gl_window().window().id();
+                extra_windows.insert(id, extra_display);
+            }
+            Event::RedrawRequested(id) => {
+                if id == display.gl_window().window().id() {
+                    let mut target = display.draw();
+                    // We draw the main window in red
+                    target.clear_color(1.0, 0.0, 0.0, 1.0);
+                    target.finish().unwrap();
+                } else if let Some(extra_display) = extra_windows.get(&id) {
+                    let mut target = extra_display.draw();
+                    // The other windows are drawn in blue
+                    target.clear_color(0.0, 0.0, 1.0, 1.0);
+                    target.finish().unwrap();
+                }
+            },
+            _ => (),
+        }
+    });
+}
+
diff --git a/src/backend/glutin/mod.rs b/src/backend/glutin/mod.rs
index 9de704e8d6..5243a4bf3c 100644
--- a/src/backend/glutin/mod.rs
+++ b/src/backend/glutin/mod.rs
@@ -70,7 +70,7 @@ impl Display {
     pub fn new<T: ContextCurrentState, E>(
         wb: glutin::window::WindowBuilder,
         cb: glutin::ContextBuilder<'_, T>,
-        events_loop: &glutin::event_loop::EventLoop<E>,
+        events_loop: &glutin::event_loop::EventLoopWindowTarget<E>,
     ) -> Result<Self, DisplayCreationError> {
         let gl_window = cb.build_windowed(wb, events_loop)?;
         Self::from_gl_window(gl_window).map_err(From::from)


Test patch: