#[macro_use] extern crate glium; use std::collections::HashMap; use glium::{Surface, Display}; use glutin::surface::WindowSurface; use support::{ApplicationContext, State}; use glium::winit::{window::WindowId, event_loop::EventLoop}; mod support; struct Application { id: i32, } // This example shows how to dynamically open new windows. impl ApplicationContext for Application { const WINDOW_TITLE:&'static str = "Main Window"; fn new(_display: &Display) -> Self { Self { id: 1 } } /// Here we just fill the window with a solid color based on the id so that we can easily /// distinguish them. fn draw_frame(&mut self, display: &Display) { let mut frame = display.draw(); let r = if self.id & 1 == 0 { 0.0 } else { 1.0 }; let g = if self.id & 2 == 0 { 0.0 } else { 1.0 }; let b = if self.id & 4 == 0 { 0.0 } else { 1.0 }; frame.clear_color(r, g, b, 1.0); frame.finish().unwrap() } } fn main() { let event_loop = EventLoop::builder() .build() .expect("event loop building"); // To simplify things we use a single type for both the main and sub windows, // since we can easily distinguish them by their id. let mut windows: HashMap> = HashMap::new(); #[allow(deprecated)] event_loop.run(move |event, window_target| { match event { // The Resumed/Suspended events are mostly for Android compatiblity since the context can get lost there at any point. // For convenience's sake the Resumed event is also delivered on other platforms on program startup. glium::winit::event::Event::Resumed => { // On startup we create the main window and insert it into the HashMap just like subsequent sub windows. let window:State = State::new(window_target, true); windows.insert(window.window.id(), window); }, glium::winit::event::Event::Suspended => { windows.clear(); }, glium::winit::event::Event::WindowEvent { event, window_id, .. } => { if let Some(state) = windows.get_mut(&window_id) { match event { glium::winit::event::WindowEvent::MouseInput { state: glium::winit::event::ElementState::Released, button: glium::winit::event::MouseButton::Left, .. } => { // This is the main part, where we actually create the new window, enumerate it and // insert it into our HashMap if state.context.id == 1 { let mut window: State = State::new(window_target, true); window.context.id = windows.len() as i32 + 1; let title = format!("Window #{}", window.context.id); window.window.set_title(&title); windows.insert(window.window.id(), window); } else { windows.remove(&window_id); } }, glium::winit::event::WindowEvent::RedrawRequested => { state.context.update(); state.context.draw_frame(&state.display); } glium::winit::event::WindowEvent::CloseRequested => { if state.context.id == 1 { window_target.exit(); } else { windows.remove(&window_id); } }, // These two aren't necessary for this particular example, but forgetting especially the Resized // event could lead to stretched images being rendered if you decide to render something more interesting based on this example. glium::winit::event::WindowEvent::Resized(new_size) => { state.display.resize(new_size.into()); }, ev => { state.context.handle_window_event(&ev, &state.window); }, } } } _ => (), }; }) .unwrap(); }